static void hci_acl_received(u8* input, u16 isize) { u8 handle; u8 flags; hci_dumphex("ACLI", input, isize); /* acl format bits 0-11 handle bits 12-13 pb flag bits 14-15 bc flag bits 16-31 input total length */ handle = bt_read_u16(input) & 0xFFF; flags = input[1] >> 4; //acl_len = bt_read_u16(input +2); if ((hci.le.hconn != handle) #if !DISABLE_BT_CLASSICAL && (hci.edr.hconn != handle) #endif ) return; if (l2cap_input(input + 4, isize - 4, flags)) { hci_write_later(BT_ACL_OUT_CHANNEL); } }
void l2cap_input(u8* input, u16 isize, u8 flags) { u8 l2len; u16 cid; u8 pb; /* l2cap format u16 length u16 cid */ l2len = bt_read_u16(input); cid = bt_read_u16(input + 2); l2cap_printf("L2IN %x,%x\n", cid, l2len); if (cid == L2CAP_ATT_CID) { gatt_input(input + 4, isize - 4); } else { // edr pb = flags & 0x3; //bc = flags >> 2; if (pb != HCI_PB_CONTINUE) { // first packet l2cap.offset = 0; l2cap.length = l2len; } memcpy(l2cap.buffer + l2cap.offset, input + 4, isize - 4); l2cap.offset += isize - 4; if (l2cap.offset == l2cap.length) { // we've got a complete packet, now pass to upper layer if (cid == L2CAP_SIG_CID) { l2cap_sig_input(input + 4, isize - 4); } else if (cid == l2cap.sdp_cid) { sdp_input(input + 4, isize - 4); } else if (cid == l2cap.rfcomm_cid) { rfcomm_input(input + 4, isize - 4); } } } }
static void hci_le_conn_cmplt( u8* data, u8 len ) { hci_printf("le connected\n"); hci.le.hconn = bt_read_u16(data + 2); hci.tasks.set_adv_en = 1; hci_write_later(BT_COMMAND_CHANNEL); }
static void hci_conn_cmplt( u8* data, u8 len ) { if (data[0] == 0) { hci_printf("edr connected\n"); hci.edr.hconn = bt_read_u16(data + 1); hci.tasks.write_scan_en = 1; hci_write_later(BT_COMMAND_CHANNEL); } }
static void hci_disconn_cmplt( u8* data, u8 len ) { u16 handle; handle = bt_read_u16(data + 1); #if !DISABLE_BT_CLASSICAL if (handle == hci.edr.hconn) { hci_printf("edr disconnected\n"); hci.edr.hconn = 0; hci.tasks.write_scan_en = 1; } else #endif if (handle == hci.le.hconn) { hci_printf("le disconnected\n"); hci.le.hconn = 0; hci.tasks.set_adv_en = 1; } hci_write_later(BT_COMMAND_CHANNEL); }
static void l2cap_sig_input(u8* input, u16 isize) { l2cap.request.code = input[0]; l2cap.request.id = input[1]; l2cap_printf("L2SIG-IN: 0x%x\n", l2cap.request.code); switch (l2cap.request.code) { case L2CAP_COMMAND_REJECT: break; case L2CAP_CONNECTION_REQUEST: l2cap.request.u.connection.psm = bt_read_u16(input + 4); l2cap.request.u.connection.scid = bt_read_u16(input + 6); sys_set_event(L2CAP_TASK_ID, L2CAP_SEND_SIG_EVENT_ID); break; case L2CAP_CONNECTION_RESPONSE: break; case L2CAP_CONFIGURE_REQUEST: l2cap.request.u.configure.dcid = bt_read_u16(input + 4); sys_set_event(L2CAP_TASK_ID, L2CAP_SEND_SIG_EVENT_ID); break; case L2CAP_CONFIGURE_RESPONSE: break; case L2CAP_DISCONNECTION_REQUEST: l2cap.request.u.disconnection.dcid = bt_read_u16(input + 4); l2cap.request.u.disconnection.scid = bt_read_u16(input + 6); sys_set_event(L2CAP_TASK_ID, L2CAP_SEND_SIG_EVENT_ID); break; case L2CAP_DISCONNECTION_RESPONSE: break; case L2CAP_INFORMATION_REQUEST: l2cap.request.u.info.type = bt_read_u16(input + 4); sys_set_event(L2CAP_TASK_ID, L2CAP_SEND_SIG_EVENT_ID); break; } }