1 /* 2 * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6 #include <KernelExport.h> 7 #include <string.h> 8 9 #include <NetBufferUtilities.h> 10 #include <net_protocol.h> 11 12 #include <bluetooth/HCI/btHCI_acl.h> 13 #include <bluetooth/HCI/btHCI_transport.h> 14 #include <bluetooth/HCI/btHCI_event.h> 15 #include <bluetooth/bdaddrUtils.h> 16 17 #include <btDebug.h> 18 #include <btCoreData.h> 19 #include <btModules.h> 20 #include <l2cap.h> 21 22 #include "acl.h" 23 24 extern struct bluetooth_core_data_module_info* btCoreData; 25 26 struct net_protocol_module_info* L2cap = NULL; 27 28 extern void RegisterConnection(hci_id hid, uint16 handle); 29 extern void unRegisterConnection(hci_id hid, uint16 handle); 30 31 status_t PostToUpper(HciConnection* conn, net_buffer* buf); 32 33 status_t 34 AclAssembly(net_buffer* nbuf, hci_id hid) 35 { 36 status_t error = B_OK; 37 38 // Check ACL data packet. Driver should ensure report complete ACL packets 39 if (nbuf->size < sizeof(struct hci_acl_header)) { 40 ERROR("%s: Invalid ACL data packet, small length=%" B_PRIu32 "\n", 41 __func__, nbuf->size); 42 gBufferModule->free(nbuf); 43 return (EMSGSIZE); 44 } 45 46 // Strip ACL data packet header 47 NetBufferHeaderReader<struct hci_acl_header> aclHeader(nbuf); 48 status_t status = aclHeader.Status(); 49 if (status < B_OK) { 50 gBufferModule->free(nbuf); 51 return ENOBUFS; 52 } 53 54 55 // Get ACL connection handle, PB flag and payload length 56 aclHeader->handle = le16toh(aclHeader->handle); 57 58 uint16 con_handle = get_acl_handle(aclHeader->handle); 59 uint16 pb = get_acl_pb_flag(aclHeader->handle); 60 uint16 length = le16toh(aclHeader->alen); 61 62 aclHeader.Remove(); 63 64 TRACE("%s: ACL data packet, handle=%#x, PB=%#x, length=%d\n", __func__, 65 con_handle, pb, length); 66 67 // a) Ensure there is HCI connection 68 // b) Get connection descriptor 69 // c) veryfy the status of the connection 70 71 HciConnection* conn = btCoreData->ConnectionByHandle(con_handle, hid); 72 if (conn == NULL) { 73 ERROR("%s: expected handle=%#x does not exist!\n", __func__, 74 con_handle); 75 conn = btCoreData->AddConnection(con_handle, BT_ACL, BDADDR_NULL, hid); 76 } 77 78 // Verify connection state 79 if (conn->status!= HCI_CONN_OPEN) { 80 ERROR("%s: unexpected ACL data packet. Connection not open\n", 81 __func__); 82 gBufferModule->free(nbuf); 83 return EHOSTDOWN; 84 } 85 86 87 // Process packet 88 if (pb == HCI_ACL_PACKET_START) { 89 if (conn->currentRxPacket != NULL) { 90 TRACE("%s: Dropping incomplete L2CAP packet, got %" B_PRIu32 91 " want %d \n", __func__, conn->currentRxPacket->size, length ); 92 gBufferModule->free(conn->currentRxPacket); 93 conn->currentRxPacket = NULL; 94 conn->currentRxExpectedLength = 0; 95 } 96 97 // Get L2CAP header, ACL header was dimissed 98 if (nbuf->size < sizeof(l2cap_hdr_t)) { 99 TRACE("%s: Invalid L2CAP start fragment, small, length=%" B_PRIu32 100 "\n", __func__, nbuf->size); 101 gBufferModule->free(nbuf); 102 return (EMSGSIZE); 103 } 104 105 106 NetBufferHeaderReader<l2cap_hdr_t> l2capHeader(nbuf); 107 status_t status = l2capHeader.Status(); 108 if (status < B_OK) { 109 gBufferModule->free(nbuf); 110 return ENOBUFS; 111 } 112 113 l2capHeader->length = le16toh(l2capHeader->length); 114 l2capHeader->dcid = le16toh(l2capHeader->dcid); 115 116 TRACE("%s: New L2CAP, handle=%#x length=%d\n", __func__, con_handle, 117 le16toh(l2capHeader->length)); 118 119 // Start new L2CAP packet 120 conn->currentRxPacket = nbuf; 121 conn->currentRxExpectedLength = l2capHeader->length + sizeof(l2cap_hdr_t); 122 123 124 } else if (pb == HCI_ACL_PACKET_FRAGMENT) { 125 if (conn->currentRxPacket == NULL) { 126 gBufferModule->free(nbuf); 127 return (EINVAL); 128 } 129 130 // Add fragment to the L2CAP packet 131 gBufferModule->merge(conn->currentRxPacket, nbuf, true); 132 133 } else { 134 ERROR("%s: invalid ACL data packet. Invalid PB flag=%#x\n", __func__, 135 pb); 136 gBufferModule->free(nbuf); 137 return (EINVAL); 138 } 139 140 // substract the length of content of the ACL packet 141 conn->currentRxExpectedLength -= length; 142 143 if (conn->currentRxExpectedLength < 0) { 144 TRACE("%s: Mismatch. Got %" B_PRIu32 ", expected %" B_PRIuSIZE "\n", 145 __func__, conn->currentRxPacket->size, 146 conn->currentRxExpectedLength); 147 148 gBufferModule->free(conn->currentRxPacket); 149 conn->currentRxPacket = NULL; 150 conn->currentRxExpectedLength = 0; 151 152 } else if (conn->currentRxExpectedLength == 0) { 153 // OK, we have got complete L2CAP packet, so process it 154 TRACE("%s: L2cap packet ready %" B_PRIu32 " bytes\n", __func__, 155 conn->currentRxPacket->size); 156 error = PostToUpper(conn, conn->currentRxPacket); 157 // clean 158 conn->currentRxPacket = NULL; 159 conn->currentRxExpectedLength = 0; 160 } else { 161 TRACE("%s: Expected %ld current adds %d\n", __func__, 162 conn->currentRxExpectedLength, length); 163 } 164 165 return error; 166 } 167 168 169 status_t 170 PostToUpper(HciConnection* conn, net_buffer* buf) 171 { 172 if (L2cap == NULL) 173 174 if (get_module(NET_BLUETOOTH_L2CAP_NAME, (module_info**)&L2cap) != B_OK) { 175 ERROR("%s: cannot get module \"%s\"\n", __func__, 176 NET_BLUETOOTH_L2CAP_NAME); 177 return B_ERROR; 178 } // TODO: someone put it 179 180 return L2cap->receive_data((net_buffer*)conn);// XXX pass handle in type 181 182 } 183