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/bluetooth_util.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, 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 bacpy(&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(bdaddr_t* destination, hci_id hid) 76 { 77 HciConnection* conn; 78 79 DoublyLinkedList<HciConnection>::Iterator iterator = sConnectionList.GetIterator(); 80 while (iterator.HasNext()) { 81 82 conn = iterator.Next(); 83 if (conn->Hid == hid && bacmp(&conn->destination, destination)==0) { 84 85 // if the device is still part of the list, remove it 86 if (conn->GetDoublyLinkedListLink()->next != NULL 87 || conn->GetDoublyLinkedListLink()->previous != NULL 88 || conn == sConnectionList.Head()) { 89 sConnectionList.Remove(conn); 90 91 delete conn; 92 return B_OK; 93 } 94 } 95 } 96 return B_ERROR; 97 } 98 99 100 status_t 101 RemoveConnection(uint16 handle, hci_id hid) 102 { 103 HciConnection* conn; 104 105 DoublyLinkedList<HciConnection>::Iterator iterator = sConnectionList.GetIterator(); 106 while (iterator.HasNext()) { 107 108 conn = iterator.Next(); 109 if (conn->Hid == hid && conn->handle == handle) { 110 111 // if the device is still part of the list, remove it 112 if (conn->GetDoublyLinkedListLink()->next != NULL 113 || conn->GetDoublyLinkedListLink()->previous != NULL 114 || conn == sConnectionList.Head()) { 115 sConnectionList.Remove(conn); 116 117 PurgeChannels(conn); 118 delete conn; 119 return B_OK; 120 } 121 } 122 } 123 return B_ERROR; 124 } 125 126 127 hci_id 128 RouteConnection(bdaddr_t* destination) { 129 130 HciConnection* conn; 131 132 DoublyLinkedList<HciConnection>::Iterator iterator = sConnectionList.GetIterator(); 133 while (iterator.HasNext()) { 134 135 conn = iterator.Next(); 136 if (bacmp(&conn->destination, destination)==0) { 137 return conn->Hid; 138 } 139 } 140 141 return -1; 142 } 143 144 145 HciConnection* 146 ConnectionByHandle(uint16 handle, hci_id hid) 147 { 148 HciConnection* conn; 149 150 DoublyLinkedList<HciConnection>::Iterator iterator = sConnectionList.GetIterator(); 151 while (iterator.HasNext()) { 152 153 conn = iterator.Next(); 154 if (conn->Hid == hid && conn->handle==handle) { 155 return conn; 156 } 157 } 158 159 return NULL; 160 } 161 162 163 HciConnection* 164 ConnectionByDestination(bdaddr_t* destination, hci_id hid) 165 { 166 HciConnection* conn; 167 168 DoublyLinkedList<HciConnection>::Iterator iterator = sConnectionList.GetIterator(); 169 while (iterator.HasNext()) { 170 171 conn = iterator.Next(); 172 if (conn->Hid == hid && bacmp(&conn->destination, destination)==0) { 173 return conn; 174 } 175 } 176 177 return NULL; 178 } 179 180 #if 0 181 #pragma mark - ACL helper funcs 182 #endif 183 184 void 185 SetAclBuffer(HciConnection* conn, net_buffer* nbuf) 186 { 187 conn->currentRxPacket = nbuf; 188 } 189 190 191 void 192 SetAclExpectedSize(HciConnection* conn, size_t size) 193 { 194 conn->currentRxExpectedLength = size; 195 } 196 197 198 void 199 AclPutting(HciConnection* conn, size_t size) 200 { 201 conn->currentRxExpectedLength -= size; 202 } 203 204 205 bool 206 AclComplete(HciConnection* conn) 207 { 208 return conn->currentRxExpectedLength == 0; 209 } 210 211 212 bool 213 AclOverFlowed(HciConnection* conn) 214 { 215 return conn->currentRxExpectedLength < 0; 216 } 217 218 #if 0 219 #pragma mark - private funcs 220 #endif 221 222 void 223 PurgeChannels(HciConnection* conn) 224 { 225 226 } 227