xref: /haiku/src/add-ons/kernel/bluetooth/btCoreData/ConnectionInterface.cpp (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
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