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 20void PurgeChannels(HciConnection* conn); 21 22 23HciConnection::HciConnection() 24{ 25 mutex_init(&fLock, "conn outgoing"); 26 mutex_init(&fLockExpected, "frame expected"); 27} 28 29 30HciConnection::~HciConnection() 31{ 32 mutex_destroy(&fLock); 33 mutex_destroy(&fLockExpected); 34} 35 36 37HciConnection* 38AddConnection(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; 54update: 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 67bail: 68 return conn; 69} 70 71 72status_t 73RemoveConnection(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 101status_t 102RemoveConnection(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 129hci_id 130RouteConnection(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 148HciConnection* 149ConnectionByHandle(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 167HciConnection* 168ConnectionByDestination(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 191void 192SetAclBuffer(HciConnection* conn, net_buffer* nbuf) 193{ 194 conn->currentRxPacket = nbuf; 195} 196 197 198void 199SetAclExpectedSize(HciConnection* conn, size_t size) 200{ 201 conn->currentRxExpectedLength = size; 202} 203 204 205void 206AclPutting(HciConnection* conn, size_t size) 207{ 208 conn->currentRxExpectedLength -= size; 209} 210 211 212bool 213AclComplete(HciConnection* conn) 214{ 215 return conn->currentRxExpectedLength == 0; 216} 217 218 219bool 220AclOverFlowed(HciConnection* conn) 221{ 222 return conn->currentRxExpectedLength < 0; 223} 224 225 226#if 0 227#pragma mark - private funcs 228#endif 229 230void 231PurgeChannels(HciConnection* conn) 232{ 233 234} 235