DF-5733 / l2cap_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 | /* * l2cap_stub.c -- minimal L2CAP upper-API stub for the rfcomm_harness KLD. * * The production RFCOMM code (sys/netbt/rfcomm_session.c, rfcomm_dlc.c, * rfcomm_upper.c) is compiled VERBATIM into the module. It only talks to * the L2CAP layer through the ten functions below; we implement them with * just enough behaviour (channel record keeping, OM TU, send = log+free) * for the real state machine to run unmodified, exactly as l2cap_upper.c * would drive it. */ #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 <netbt/bluetooth.h> #include <netbt/hci.h> #include <netbt/l2cap.h> #include <netbt/rfcomm.h> /* * The real malloc type lives in bt_proto.c which we do not compile in. */ MALLOC_DEFINE(M_BLUETOOTH, "Bluetooth", "Bluetooth system memory"); /* * Real struct l2cap_channel (from netbt/l2cap.h) -- the RFCOMM code only * stores the pointer, we fill in the few members that matter. The * harness fires btproto callbacks through chan->lc_proto/chan->lc_upper * exactly the way sys/netbt/l2cap_upper.c does. */ #define MAXCHAN 8 static struct l2cap_channel stub_chans[MAXCHAN]; static int stub_nchan; struct l2cap_channel *harness_first_session_channel(void); struct l2cap_channel * harness_first_session_channel(void) { if (stub_nchan < 1) return NULL; return &stub_chans[0]; /* rfcomm_session_alloc() attaches first */ } int l2cap_attach(struct l2cap_channel **handle, const struct btproto *proto, void *upper) { struct l2cap_channel *chan; if (stub_nchan >= MAXCHAN) return ENOMEM; chan = &stub_chans[stub_nchan++]; memset(chan, 0, sizeof(*chan)); chan->lc_proto = proto; chan->lc_upper = upper; chan->lc_omtu = 1024; /* > RFCOMM_MTU_MIN + 6 */ chan->lc_state = L2CAP_OPEN; /* pretend link is up */ *handle = chan; return 0; } int l2cap_detach(struct l2cap_channel **handle) { *handle = NULL; return 0; } int l2cap_bind(struct l2cap_channel *chan, struct sockaddr_bt *addr) { return 0; } int l2cap_listen(struct l2cap_channel *chan) { return 0; } int l2cap_connect(struct l2cap_channel *chan, struct sockaddr_bt *dest) { /* pretend the L2CAP connect request went out */ return 0; } int l2cap_disconnect(struct l2cap_channel *chan, int linger) { return 0; } int l2cap_send(struct l2cap_channel *chan, struct mbuf *m) { kprintf("[l2cap-stub] send: %d bytes (first octet %#02x)\n", m->m_pkthdr.len, mtod(m, uint8_t *)[0]); m_freem(m); return 0; } int l2cap_setopt(struct l2cap_channel *chan, int opt, void *addr) { /* SO_L2CAP_LM: pretend mode change is instantly complete */ return 0; } int l2cap_getopt(struct l2cap_channel *chan, int opt, void *addr) { if (opt == SO_L2CAP_OMTU) { *(uint16_t *)addr = chan->lc_omtu; return sizeof(uint16_t); } return 0; } int l2cap_sockaddr(struct l2cap_channel *chan, struct sockaddr_bt *addr) { memset(addr, 0, sizeof(*addr)); addr->bt_len = sizeof(*addr); addr->bt_family = AF_BLUETOOTH; addr->bt_psm = L2CAP_PSM_RFCOMM; addr->bt_bdaddr.b[0] = 0x11; /* "us" */ return 0; } int l2cap_peeraddr(struct l2cap_channel *chan, struct sockaddr_bt *addr) { memset(addr, 0, sizeof(*addr)); addr->bt_len = sizeof(*addr); addr->bt_family = AF_BLUETOOTH; addr->bt_psm = L2CAP_PSM_RFCOMM; addr->bt_bdaddr.b[0] = 0x22; /* "them" */ return 0; } |