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 // Get ACL connection handle, PB flag and payload length 55 aclHeader->handle = B_LENDIAN_TO_HOST_INT16(aclHeader->handle); 56 57 uint16 con_handle = get_acl_handle(aclHeader->handle); 58 uint16 pb = get_acl_pb_flag(aclHeader->handle); 59 uint16 length = B_LENDIAN_TO_HOST_INT16(aclHeader->alen); 60 61 aclHeader.Remove(); 62 63 TRACE("%s: ACL data packet, handle=%#x, PB=%#x, length=%d\n", __func__, 64 con_handle, pb, length); 65 66 // a) Ensure there is HCI connection 67 // b) Get connection descriptor 68 // c) veryfy the status of the connection 69 70 HciConnection* conn = btCoreData->ConnectionByHandle(con_handle, hid); 71 if (conn == NULL) { 72 ERROR("%s: expected handle=%#x does not exist!\n", __func__, 73 con_handle); 74 conn = btCoreData->AddConnection(con_handle, BT_ACL, BDADDR_NULL, hid); 75 } 76 77 // Verify connection state 78 if (conn->status!= HCI_CONN_OPEN) { 79 ERROR("%s: unexpected ACL data packet. Connection not open\n", 80 __func__); 81 gBufferModule->free(nbuf); 82 return EHOSTDOWN; 83 } 84 85 86 // Process packet 87 if (pb == HCI_ACL_PACKET_START) { 88 if (conn->currentRxPacket != NULL) { 89 TRACE("%s: Dropping incomplete L2CAP packet, got %" B_PRIu32 90 " want %d \n", __func__, conn->currentRxPacket->size, length ); 91 gBufferModule->free(conn->currentRxPacket); 92 conn->currentRxPacket = NULL; 93 conn->currentRxExpectedLength = 0; 94 } 95 96 // Get L2CAP header, ACL header was dimissed 97 if (nbuf->size < sizeof(l2cap_basic_header)) { 98 TRACE("%s: Invalid L2CAP start fragment, small, length=%" B_PRIu32 99 "\n", __func__, nbuf->size); 100 gBufferModule->free(nbuf); 101 return (EMSGSIZE); 102 } 103 104 NetBufferHeaderReader<l2cap_basic_header> l2capHeader(nbuf); 105 if (l2capHeader.Status() != B_OK) { 106 gBufferModule->free(nbuf); 107 return ENOBUFS; 108 } 109 110 TRACE("%s: New L2CAP, handle=%#x length=%d\n", __func__, con_handle, 111 le16toh(l2capHeader->length)); 112 113 // Start new L2CAP packet 114 conn->currentRxPacket = nbuf; 115 conn->currentRxExpectedLength = B_LENDIAN_TO_HOST_INT16(l2capHeader->length) 116 + sizeof(l2cap_basic_header); 117 } else if (pb == HCI_ACL_PACKET_FRAGMENT) { 118 if (conn->currentRxPacket == NULL) { 119 gBufferModule->free(nbuf); 120 return (EINVAL); 121 } 122 123 // Add fragment to the L2CAP packet 124 gBufferModule->merge(conn->currentRxPacket, nbuf, true); 125 } else { 126 ERROR("%s: invalid ACL data packet. Invalid PB flag=%#x\n", __func__, 127 pb); 128 gBufferModule->free(nbuf); 129 return (EINVAL); 130 } 131 132 // substract the length of content of the ACL packet 133 conn->currentRxExpectedLength -= length; 134 135 if (conn->currentRxExpectedLength < 0) { 136 TRACE("%s: Mismatch. Got %" B_PRIu32 ", expected %" B_PRIuSIZE "\n", 137 __func__, conn->currentRxPacket->size, 138 conn->currentRxExpectedLength); 139 140 gBufferModule->free(conn->currentRxPacket); 141 conn->currentRxPacket = NULL; 142 conn->currentRxExpectedLength = 0; 143 144 } else if (conn->currentRxExpectedLength == 0) { 145 // OK, we have got complete L2CAP packet, so process it 146 TRACE("%s: L2cap packet ready %" B_PRIu32 " bytes\n", __func__, 147 conn->currentRxPacket->size); 148 149 memcpy(conn->currentRxPacket->source, &conn->address_dest, sizeof(sockaddr_storage)); 150 conn->currentRxPacket->interface_address = &conn->interface_address; 151 152 error = PostToUpper(conn, conn->currentRxPacket); 153 // clean 154 conn->currentRxPacket = NULL; 155 conn->currentRxExpectedLength = 0; 156 } else { 157 TRACE("%s: Expected %ld current adds %d\n", __func__, 158 conn->currentRxExpectedLength, length); 159 } 160 161 return error; 162 } 163 164 165 status_t 166 PostToUpper(HciConnection* conn, net_buffer* buf) 167 { 168 if (L2cap == NULL) 169 170 if (get_module(NET_BLUETOOTH_L2CAP_NAME, (module_info**)&L2cap) != B_OK) { 171 ERROR("%s: cannot get module \"%s\"\n", __func__, 172 NET_BLUETOOTH_L2CAP_NAME); 173 return B_ERROR; 174 } // TODO: someone put it 175 176 return L2cap->receive_data(buf); 177 } 178