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