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