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 <util/DoublyLinkedList.h> 7 8 #include <KernelExport.h> 9 10 #include <bluetooth/bluetooth.h> 11 #include <bluetooth/bdaddrUtils.h> 12 13 #include <btDebug.h> 14 15 #include <l2cap.h> 16 17 #include "ConnectionInterface.h" 18 19 20 void PurgeChannels(HciConnection* conn); 21 22 23 HciConnection::HciConnection() 24 { 25 mutex_init(&fLock, "conn outgoing"); 26 mutex_init(&fLockExpected, "frame expected"); 27 } 28 29 30 HciConnection::~HciConnection() 31 { 32 mutex_destroy(&fLock); 33 mutex_destroy(&fLockExpected); 34 } 35 36 37 HciConnection* 38 AddConnection(uint16 handle, int type, const bdaddr_t& dst, hci_id hid) 39 { 40 // Create connection descriptor 41 42 HciConnection* conn = ConnectionByHandle(handle, hid); 43 if (conn != NULL) 44 goto update; 45 46 conn = new (std::nothrow) HciConnection; 47 if (conn == NULL) 48 goto bail; 49 50 // memset(conn, 0, sizeof(HciConnection)); 51 52 conn->currentRxPacket = NULL; 53 conn->currentRxExpectedLength = 0; 54 update: 55 // fill values 56 bdaddrUtils::Copy(conn->destination, dst); 57 conn->type = type; 58 conn->handle = handle; 59 conn->Hid = hid; 60 conn->status = HCI_CONN_OPEN; 61 conn->mtu = L2CAP_MTU_MINIMUM; // TODO: give the mtu to the connection 62 conn->lastCid = L2CAP_FIRST_CID; 63 conn->lastIdent = L2CAP_FIRST_IDENT; 64 65 sConnectionList.Add(conn); 66 67 bail: 68 return conn; 69 } 70 71 72 status_t 73 RemoveConnection(const bdaddr_t& destination, hci_id hid) 74 { 75 HciConnection* conn; 76 77 DoublyLinkedList<HciConnection>::Iterator iterator 78 = sConnectionList.GetIterator(); 79 80 while (iterator.HasNext()) { 81 82 conn = iterator.Next(); 83 if (conn->Hid == hid 84 && bdaddrUtils::Compare(conn->destination, destination)) { 85 86 // if the device is still part of the list, remove it 87 if (conn->GetDoublyLinkedListLink()->next != NULL 88 || conn->GetDoublyLinkedListLink()->previous != NULL 89 || conn == sConnectionList.Head()) { 90 sConnectionList.Remove(conn); 91 92 delete conn; 93 return B_OK; 94 } 95 } 96 } 97 return B_ERROR; 98 } 99 100 101 status_t 102 RemoveConnection(uint16 handle, hci_id hid) 103 { 104 HciConnection* conn; 105 106 DoublyLinkedList<HciConnection>::Iterator iterator 107 = sConnectionList.GetIterator(); 108 while (iterator.HasNext()) { 109 110 conn = iterator.Next(); 111 if (conn->Hid == hid && conn->handle == handle) { 112 113 // if the device is still part of the list, remove it 114 if (conn->GetDoublyLinkedListLink()->next != NULL 115 || conn->GetDoublyLinkedListLink()->previous != NULL 116 || conn == sConnectionList.Head()) { 117 sConnectionList.Remove(conn); 118 119 PurgeChannels(conn); 120 delete conn; 121 return B_OK; 122 } 123 } 124 } 125 return B_ERROR; 126 } 127 128 129 hci_id 130 RouteConnection(const bdaddr_t& destination) { 131 132 HciConnection* conn; 133 134 DoublyLinkedList<HciConnection>::Iterator iterator 135 = sConnectionList.GetIterator(); 136 while (iterator.HasNext()) { 137 138 conn = iterator.Next(); 139 if (bdaddrUtils::Compare(conn->destination, destination)) { 140 return conn->Hid; 141 } 142 } 143 144 return -1; 145 } 146 147 148 HciConnection* 149 ConnectionByHandle(uint16 handle, hci_id hid) 150 { 151 HciConnection* conn; 152 153 DoublyLinkedList<HciConnection>::Iterator iterator 154 = sConnectionList.GetIterator(); 155 while (iterator.HasNext()) { 156 157 conn = iterator.Next(); 158 if (conn->Hid == hid && conn->handle == handle) { 159 return conn; 160 } 161 } 162 163 return NULL; 164 } 165 166 167 HciConnection* 168 ConnectionByDestination(const bdaddr_t& destination, hci_id hid) 169 { 170 HciConnection* conn; 171 172 DoublyLinkedList<HciConnection>::Iterator iterator 173 = sConnectionList.GetIterator(); 174 while (iterator.HasNext()) { 175 176 conn = iterator.Next(); 177 if (conn->Hid == hid 178 && bdaddrUtils::Compare(conn->destination, destination)) { 179 return conn; 180 } 181 } 182 183 return NULL; 184 } 185 186 187 #if 0 188 #pragma mark - ACL helper funcs 189 #endif 190 191 void 192 SetAclBuffer(HciConnection* conn, net_buffer* nbuf) 193 { 194 conn->currentRxPacket = nbuf; 195 } 196 197 198 void 199 SetAclExpectedSize(HciConnection* conn, size_t size) 200 { 201 conn->currentRxExpectedLength = size; 202 } 203 204 205 void 206 AclPutting(HciConnection* conn, size_t size) 207 { 208 conn->currentRxExpectedLength -= size; 209 } 210 211 212 bool 213 AclComplete(HciConnection* conn) 214 { 215 return conn->currentRxExpectedLength == 0; 216 } 217 218 219 bool 220 AclOverFlowed(HciConnection* conn) 221 { 222 return conn->currentRxExpectedLength < 0; 223 } 224 225 226 #if 0 227 #pragma mark - private funcs 228 #endif 229 230 void 231 PurgeChannels(HciConnection* conn) 232 { 233 234 } 235