DF-5764 / stub.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | /* * stub.c -- HCI/SCO-layer stubs for the l2pw_harness KLD (DF-5764). * * The production netbt files compiled VERBATIM into this module are * l2cap_upper.c (l2cap_send / l2cap_disconnect / l2cap_detach) * l2cap_lower.c (THE FILE UNDER AUDIT: l2cap_start / l2cap_close) * l2cap_misc.c (zones, cid alloc, request alloc/free) * l2cap_signal.c (l2cap_send_disconnect_req et al.) * hci_link.c (hci_acl_send / hci_acl_start / hci_acl_complete / * hci_link_alloc / hci_link_free / hci_acl_close) * -- so the failure path under test (hci_acl_send's ENETDOWN branch, * hci_link.c:546-549) is production code, not a stub. * * Everything those files need from the layers we do NOT compile * (hci_event.c, hci_unit.c, hci_socket.c, bt_proto.c, sco_upper.c, * l2cap_socket.c) is provided here with the minimum faithful behaviour: * * - bluetooth_debug (defined by hci_event.c in production): keep at 0 * - M_BLUETOOTH malloc type (bt_proto.c) * - empty sco_pcb listener list (sco_upper.c) -- never matched * - sco_detach(): symbol only, never called on our paths * - hci_send_cmd(): symbol only (hci_acl_open/timeout paths we don't drive) * - hci_output_acl(): fragment sink -- count + free (what the USB * transport + controller would do with the fragment) * * The channel upper layer (what l2cap_socket.c provides in production) * is a fake btproto with counters. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/systm.h> #include <sys/types.h> #include <net/if.h> #include <netbt/bluetooth.h> #include <netbt/hci.h> #include <netbt/l2cap.h> #include <netbt/sco.h> #include "l2uh.h" /* defined by hci_event.c in production; keep debug prints OFF */ int bluetooth_debug = 0; /* real malloc type lives in bt_proto.c which we do not compile in */ MALLOC_DEFINE(M_BLUETOOTH, "Bluetooth", "Bluetooth system memory"); /* empty SCO listener list (sco_upper.c) */ struct sco_pcb_list sco_pcb = LIST_HEAD_INITIALIZER(sco_pcb); /* counters for the fake upper layer (what l2cap_socket.c would do) */ int stub_proto_disconnected_count; int stub_proto_complete_count; int stub_proto_connecting_count; /* ACL fragments handed to the transport (hci_output_acl sink) */ int stub_acl_output_count; static void stub_connecting(void *); static void stub_connected(void *); static void stub_disconnected(void *, int); static void *stub_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); static void stub_complete(void *, int); static void stub_linkmode(void *, int); static void stub_input(void *, struct mbuf *); const struct btproto stub_btproto = { stub_connecting, stub_connected, stub_disconnected, stub_newconn, stub_complete, stub_linkmode, stub_input, }; static void stub_connecting(void *arg) { stub_proto_connecting_count++; } static void stub_connected(void *arg) { } static void stub_disconnected(void *arg, int err) { stub_proto_disconnected_count++; } static void * stub_newconn(void *arg, struct sockaddr_bt *laddr, struct sockaddr_bt *raddr) { return NULL; } static void stub_complete(void *arg, int count) { stub_proto_complete_count++; } static void stub_linkmode(void *arg, int new) { } static void stub_input(void *arg, struct mbuf *m) { m_freem(m); } /* ------------------------------------------------------------------ */ /* HCI-layer symbols used by the compiled production files */ int hci_send_cmd(struct hci_unit *unit, uint16_t opcode, void *ptr, uint8_t len) { /* symbol only: hci_acl_open()/hci_acl_timeout() paths are not driven */ return 0; } void hci_output_acl(struct hci_unit *unit, struct mbuf *m) { /* the transport took the fragment */ stub_acl_output_count++; m_freem(m); } int sco_detach(struct sco_pcb **handle) { /* symbol only, never called on our paths */ return 0; } struct hci_unit * hci_unit_lookup(bdaddr_t *bdaddr) { /* symbol only (hci_unit.c in production), not on our paths */ return NULL; } int hci_route_lookup(bdaddr_t *laddr, bdaddr_t *raddr) { /* symbol only (l2cap_connect() path, which the harness bypasses) */ return 0; } struct hci_memo * hci_memo_find(struct hci_unit *unit, bdaddr_t *bdaddr) { /* symbol only (hci_unit.c): hci_acl_open() path, not driven */ return NULL; } struct hci_memo * hci_memo_new(struct hci_unit *unit, bdaddr_t *bdaddr) { /* symbol only (hci_unit.c): hci_link_free() takes this only when * hl_clock != 0; the rig's links never have one */ return NULL; } |