10 #include "oswald_main.h"
12 static bt_l2cap_con_t _l2cap_con;
16 memset(&_l2cap_con, 0, sizeof(bt_l2cap_con_t));
19 void bt_l2cap_proc_dyn_channel(const uint16_t channel, const uint16_t handle, const void *mdat, uint16_t mlen)
21 if (channel == _l2cap_con.locCID) {
22 debug_uart_tx("L2CAP data rcvd: ");
23 debug_dump_ascii(mlen, mdat);
24 if (_l2cap_con.PSM == 0x1001) {
25 oswald_handle_comm_input(mlen, mdat);
26 } else if (_l2cap_con.PSM == 0x0001) { // SDP
27 debug_uart_tx("SDP req: ");
28 debug_dump_hex(mlen, mdat);
30 debug_uart_tx("L2CAP data on unhandled PSM\n");
32 debug_uart_tx("L2CAP CID does not match local CID\n");
36 uint8_t bt_l2cap_get_connected(const uint16_t channel)
38 if (_l2cap_con.locCID == channel)
39 return _l2cap_con.cstate;
41 return BT_L2CAP_CON_IDLE;
44 void bt_l2cap_send_channel(const uint16_t channel, const void *mdat, uint16_t mlen)
46 if (_l2cap_con.cstate == BT_L2CAP_CON_CONNECTED && _l2cap_con.hci_handle != 0 && _l2cap_con.remCID != 0 &&
47 mlen != 0 && mdat != NULL) {
48 bt_acl_send(_l2cap_con.hci_handle, PB_FIRST_FLUSHABLE, BC_NO_BROADCAST, _l2cap_con.remCID, mlen, mdat);
58 } __attribute__((packed)) bt_l2cap_disconn_resp_t;
68 } __attribute__((packed)) bt_l2cap_conf_resp_t;
71 void bt_l2cap_proc_signalling(const uint16_t handle, unsigned char *mdat, uint16_t mlen)
73 #if defined MW_DEVBOARD_V2
76 debug_uart_tx("ACL L2CAP signalling ");
79 debug_uart_tx("command reject\n");
81 case CONNECTION_REQUEST: {
82 uint8_t ident = mdat[1];
83 uint16_t PSM = mdat[4] | (mdat[5] << 8);;
84 uint16_t src_CID = mdat[6] | (mdat[7] << 8);;
86 #if defined MW_DEVBOARD_V2
87 debug_uart_tx("connection request on ");
88 snprintf(tstr, 16, "PSM 0x%04x ", PSM);
90 snprintf(tstr, 16, "srcCID 0x%04x\n", src_CID);
93 bt_l2cap_handle_connection_request(handle, ident, PSM, src_CID);
95 case CONNECTION_RESPONSE:
96 debug_uart_tx("connection response\n");
98 case CONFIGURE_REQUEST: {
99 uint8_t ident = mdat[1];
100 uint16_t len = mdat[2] | (mdat[3] << 8);
101 uint16_t dst_CID = mdat[4] | (mdat[5] << 8);
102 uint16_t flags = mdat[6] | (mdat[7] << 8);
103 bt_l2cap_conf_resp_t resp;
105 #if defined MW_DEVBOARD_V2
106 debug_uart_tx("configure request ");
107 snprintf(tstr, 16, "len 0x%04x ", len);
109 snprintf(tstr, 16, "DCID 0x%04x ", dst_CID);
111 snprintf(tstr, 16, "flags 0x%04x\n", flags);
114 for (i=8; i<((len-4)+8); i++) {
115 snprintf(tstr, 16, "0x%02x ", mdat[i]);
120 debug_dump_hex(len-4+8, (mdat+8));
122 resp.resp = CONFIGURE_RESPONSE;
125 if (dst_CID != _l2cap_con.locCID)
126 debug_uart_tx("warning: DCID does not match\n");
127 resp.SCID = _l2cap_con.remCID;
129 resp.result = 0x0000; // success
130 resp.config = 0x0000; // OK?
132 bt_acl_send(handle, PB_FIRST_FLUSHABLE, BC_NO_BROADCAST, L2CAP_CID_SIGNALING, sizeof(bt_l2cap_conf_resp_t)-2, &resp);
135 case CONFIGURE_RESPONSE:
136 debug_uart_tx("configure response\n");
138 case DISCONNECTION_REQUEST: {
139 bt_l2cap_disconn_resp_t resp;
140 uint8_t ident = mdat[1];
141 uint16_t dst_CID = mdat[4] | (mdat[5] << 8);
142 uint16_t src_CID = mdat[6] | (mdat[7] << 8);
144 debug_uart_tx("disconnect request\n");
146 if (dst_CID != _l2cap_con.locCID || src_CID != _l2cap_con.remCID)
147 debug_uart_tx("warning: discon on unknown CID\n");
148 resp.resp = DISCONNECTION_RESPONSE;
150 resp.length = 0x0004;
151 resp.DCID = _l2cap_con.locCID;
152 resp.SCID = _l2cap_con.remCID;
154 bt_acl_send(handle, PB_FIRST_FLUSHABLE, BC_NO_BROADCAST, L2CAP_CID_SIGNALING, sizeof(bt_l2cap_disconn_resp_t), &resp);
158 case DISCONNECTION_RESPONSE:
159 debug_uart_tx("disconnect response\n");
162 debug_uart_tx("echo request\n");
163 mdat[0] = ECHO_RESPONSE;
164 bt_acl_send(handle, PB_FIRST_FLUSHABLE, BC_NO_BROADCAST, L2CAP_CID_SIGNALING, mlen, mdat);
167 debug_uart_tx("echo response\n");
169 case INFORMATION_REQUEST: {
170 uint16_t info_type = mdat[4] | (mdat[5] << 8);
171 debug_uart_tx("information request ");
174 debug_uart_tx("connectionless mtu\n");
177 debug_uart_tx("ext. feat. support\n");
178 mdat[0] = INFORMATION_RESPONSE;
181 mdat[6] = 0x01; // not supported
183 bt_acl_send(handle, PB_FIRST_FLUSHABLE, BC_NO_BROADCAST, L2CAP_CID_SIGNALING, 0x08, mdat);
186 debug_uart_tx("fixed channel support\n");
189 debug_uart_tx("unknown\n");
193 case INFORMATION_RESPONSE:
194 debug_uart_tx("information response\n");
197 debug_uart_tx("unknown\n");
210 } __attribute__((packed)) bt_l2cap_conn_resp_t;
221 } __attribute__((packed)) bt_l2cap_conf_req_t;
223 void bt_l2cap_handle_connection_request(const uint16_t handle, const uint8_t ident, const uint16_t PSM, const uint16_t src_CID)
225 bt_l2cap_conn_resp_t resp;
227 // for now we only support one connection, only on PSM 0x1001
228 if (_l2cap_con.cstate == BT_L2CAP_CON_IDLE && PSM == 0x1001) {
229 bt_l2cap_conf_req_t req;
231 _l2cap_con.cstate = BT_L2CAP_CON_CONNECTED;
232 _l2cap_con.hci_handle = handle;
233 _l2cap_con.PSM = PSM;
235 _l2cap_con.locCID = 0x0040;
236 _l2cap_con.remCID = src_CID;
238 _l2cap_con.locMTU = 0xf0;
239 _l2cap_con.remMTU = 0x00;
241 resp.resp = CONNECTION_RESPONSE;
243 resp.length = 0x0008;
244 resp.DCID = _l2cap_con.locCID;
245 resp.SCID = _l2cap_con.remCID;
246 resp.result = BT_L2CAP_CON_RES_SUCCESS;
247 resp.status = BT_L2CAP_CON_STAT_NOINFO;
249 debug_uart_tx("l2cap accepting connection\n");
250 bt_acl_send(handle, PB_FIRST_FLUSHABLE, BC_NO_BROADCAST, L2CAP_CID_SIGNALING, sizeof(bt_l2cap_conn_resp_t), &resp);
252 req.resp = CONFIGURE_REQUEST;
255 req.DCID = _l2cap_con.remCID;
257 req.option = 0x01; // MTU
259 req.odat = _l2cap_con.locMTU;
261 bt_acl_send(handle, PB_FIRST_FLUSHABLE, BC_NO_BROADCAST, L2CAP_CID_SIGNALING, sizeof(bt_l2cap_conf_req_t), &req);
263 // max_interval Mandatory Range: 0x0006 to 0x0540
264 // min_interval Mandatory Range: 0x0006 to 0x0540
265 // sniff_attempt Mandatory Range for Controller: 1 to Tsniff/2
266 // sniff_timeout Mandatory Range for Controller: 0 to 0x0028
267 bt_hci_set_sniff_mode(handle, 0x10, 0x06, 0x20, 0x10);
269 resp.resp = CONNECTION_RESPONSE;
271 resp.length = 0x0008;
274 resp.result = BT_L2CAP_CON_RES_REFUSED_RSRC;
275 resp.status = BT_L2CAP_CON_STAT_NOINFO;
277 debug_uart_tx("l2cap refusing connection\n");
278 bt_acl_send(handle, PB_FIRST_FLUSHABLE, BC_NO_BROADCAST, L2CAP_CID_SIGNALING, sizeof(bt_l2cap_conn_resp_t), &resp);