1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "l2cap_inst.h"
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "log.h"
23
24 #include "l2cap_cmn.h"
25
26 static L2capInstance g_l2capInst;
27
L2capGetInstance()28 L2capInstance *L2capGetInstance()
29 {
30 return &g_l2capInst;
31 }
32
L2capInitialized()33 int L2capInitialized()
34 {
35 L2capInstance *inst = L2capGetInstance();
36
37 if (inst->connList != NULL) {
38 return BT_SUCCESS;
39 }
40
41 return BT_BAD_STATUS;
42 }
43
L2capGetPsm(uint16_t lpsm)44 L2capPsm *L2capGetPsm(uint16_t lpsm)
45 {
46 L2capInstance *inst = L2capGetInstance();
47 L2capPsm *psm = NULL;
48 ListNode *node = NULL;
49
50 node = ListGetFirstNode(inst->psmList);
51 while (node != NULL) {
52 psm = ListGetNodeData(node);
53 if (psm->lpsm == lpsm) {
54 return psm;
55 }
56
57 node = ListGetNextNode(node);
58 }
59
60 return NULL;
61 }
62
L2capGetConnection(uint16_t aclHandle)63 L2capConnection *L2capGetConnection(uint16_t aclHandle)
64 {
65 L2capInstance *inst = L2capGetInstance();
66 L2capConnection *conn = NULL;
67 ListNode *node = NULL;
68
69 node = ListGetFirstNode(inst->connList);
70 while (node != NULL) {
71 conn = ListGetNodeData(node);
72 if (conn->aclHandle == aclHandle) {
73 return conn;
74 }
75
76 node = ListGetNextNode(node);
77 }
78
79 return NULL;
80 }
81
L2capGetConnection2(const BtAddr * addr)82 L2capConnection *L2capGetConnection2(const BtAddr *addr)
83 {
84 L2capInstance *inst = L2capGetInstance();
85 L2capConnection *conn = NULL;
86 ListNode *node = NULL;
87
88 node = ListGetFirstNode(inst->connList);
89 while (node != NULL) {
90 conn = ListGetNodeData(node);
91 if (memcmp(conn->addr.addr, addr->addr, sizeof(addr->addr)) == 0) {
92 return conn;
93 }
94
95 node = ListGetNextNode(node);
96 }
97
98 return NULL;
99 }
100
L2capGetConnection3(const L2capChannel * chan)101 L2capConnection *L2capGetConnection3(const L2capChannel *chan)
102 {
103 L2capInstance *inst = L2capGetInstance();
104 L2capConnection *conn = NULL;
105 ListNode *node = NULL;
106 ListNode *nodeChan = NULL;
107
108 node = ListGetFirstNode(inst->connList);
109 while (node != NULL) {
110 conn = ListGetNodeData(node);
111
112 nodeChan = ListGetFirstNode(conn->chanList);
113 while (nodeChan != NULL) {
114 if (ListGetNodeData(nodeChan) == chan) {
115 return conn;
116 }
117
118 nodeChan = ListGetNextNode(nodeChan);
119 }
120
121 node = ListGetNextNode(node);
122 }
123
124 return conn;
125 }
126
L2capGetChannel(const L2capConnection * conn,int16_t lcid)127 L2capChannel *L2capGetChannel(const L2capConnection *conn, int16_t lcid)
128 {
129 L2capChannel *chan = NULL;
130 ListNode *node = NULL;
131
132 node = ListGetFirstNode(conn->chanList);
133 while (node != NULL) {
134 chan = ListGetNodeData(node);
135 if (chan->lcid == lcid) {
136 return chan;
137 }
138
139 node = ListGetNextNode(node);
140 }
141
142 return NULL;
143 }
144
L2capGetChannel2(uint16_t lcid,L2capConnection ** conn,L2capChannel ** chan)145 void L2capGetChannel2(uint16_t lcid, L2capConnection **conn, L2capChannel **chan)
146 {
147 L2capInstance *inst = L2capGetInstance();
148 ListNode *node = NULL;
149
150 node = ListGetFirstNode(inst->connList);
151 while (node != NULL) {
152 *conn = ListGetNodeData(node);
153 *chan = L2capGetChannel(*conn, lcid);
154 if ((*chan) != NULL) {
155 break;
156 }
157
158 node = ListGetNextNode(node);
159 }
160
161 return;
162 }
163
L2capGetChannel3(uint16_t aclHandle,uint16_t lcid,L2capConnection ** conn,L2capChannel ** chan)164 void L2capGetChannel3(uint16_t aclHandle, uint16_t lcid, L2capConnection **conn, L2capChannel **chan)
165 {
166 *conn = L2capGetConnection(aclHandle);
167 if ((*conn) == NULL) {
168 return;
169 }
170
171 *chan = L2capGetChannel(*conn, lcid);
172 return;
173 }
174
L2capGetNewLcid()175 static uint16_t L2capGetNewLcid()
176 {
177 L2capInstance *inst = L2capGetInstance();
178 uint16_t lcid = L2CAP_MIN_CID;
179
180 if (inst->nextLcid == 0) {
181 L2capConnection *conn = NULL;
182 L2capChannel *chan = NULL;
183
184 while (1) {
185 L2capGetChannel2(lcid, &conn, &chan);
186 if (chan == NULL) {
187 break;
188 }
189
190 lcid += 1;
191 }
192 } else {
193 lcid = inst->nextLcid;
194
195 if (lcid == L2CAP_MAX_CID) {
196 inst->nextLcid = 0;
197 } else {
198 inst->nextLcid += 1;
199 }
200 }
201
202 return lcid;
203 }
204
L2capSetDefaultConfigOptions(L2capConfigInfo * cfg)205 static void L2capSetDefaultConfigOptions(L2capConfigInfo *cfg)
206 {
207 cfg->mtu = L2CAP_DEFAULT_MTU;
208 cfg->flushTimeout = L2CAP_NONE_FLUSH_PACKET;
209 cfg->rfc.mode = L2CAP_BASIC_MODE;
210 cfg->rfc.maxTransmit = L2CAP_DEFAULT_MAX_TRANSMIT;
211 cfg->rfc.txWindowSize = L2CAP_DEFAULT_TX_WINDOW;
212 cfg->rfc.rxWindowSize = L2CAP_DEFAULT_TX_WINDOW;
213 cfg->rfc.retransmissionTimeout = 0;
214 cfg->rfc.monitorTimeout = 0;
215 cfg->rfc.mps = L2capGetRxBufferSize() - L2CAP_SIZE_10;
216 cfg->fcs = 0x01;
217
218 return;
219 }
220
L2capNewChannel(L2capConnection * conn,uint16_t lpsm,uint16_t rpsm)221 L2capChannel *L2capNewChannel(L2capConnection *conn, uint16_t lpsm, uint16_t rpsm)
222 {
223 L2capChannel *chan = NULL;
224
225 chan = L2capAlloc(sizeof(L2capChannel));
226 if (chan == NULL) {
227 return NULL;
228 }
229
230 if (conn->discTimer != NULL) {
231 AlarmCancel(conn->discTimer);
232 AlarmDelete(conn->discTimer);
233 conn->discTimer = NULL;
234 } else {
235 if ((conn->state == L2CAP_CONNECTION_CONNECTED) && (ListGetFirstNode(conn->chanList) == NULL)) {
236 if (L2capAddConnectionRef(conn->aclHandle) != BT_SUCCESS) {
237 conn->state = L2CAP_CONNECTION_DISCONNECTING;
238 }
239 }
240 }
241
242 chan->lcid = L2capGetNewLcid();
243 chan->lpsm = lpsm;
244 chan->rpsm = rpsm;
245 chan->state = L2CAP_CHANNEL_IDLE;
246 chan->cfgState = 0;
247
248 chan->part.options = NULL;
249 chan->part.length = 0;
250
251 L2capSetDefaultConfigOptions(&(chan->lcfg));
252 L2capSetDefaultConfigOptions(&(chan->rcfg));
253
254 ListAddLast(conn->chanList, chan);
255 return chan;
256 }
257
L2capDestroyChannelTx(L2capChannel * chan)258 static void L2capDestroyChannelTx(L2capChannel *chan)
259 {
260 ListNode *node = NULL;
261
262 if (chan->lcfg.rfc.mode == L2CAP_STREAM_MODE) {
263 Packet *pkt = NULL;
264
265 while (1) {
266 node = ListGetFirstNode(chan->erfc.txList);
267 if (node == NULL) {
268 break;
269 }
270
271 pkt = ListGetNodeData(node);
272 ListRemoveNode(chan->erfc.txList, pkt);
273 PacketFree(pkt);
274 }
275 } else {
276 L2capErfcTxPacket *tx = NULL;
277
278 while (1) {
279 node = ListGetFirstNode(chan->erfc.txList);
280 if (node == NULL) {
281 break;
282 }
283
284 tx = ListGetNodeData(node);
285 ListRemoveNode(chan->erfc.txList, tx);
286 PacketFree(tx->pkt);
287 L2capFree(tx);
288 }
289 }
290
291 ListDelete(chan->erfc.txList);
292 return;
293 }
294
L2capDestroyChannel(L2capChannel * chan)295 void L2capDestroyChannel(L2capChannel *chan)
296 {
297 if (chan->erfc.monitorTimer != NULL) {
298 AlarmCancel(chan->erfc.monitorTimer);
299 AlarmDelete(chan->erfc.monitorTimer);
300 }
301
302 if (chan->erfc.retransmissionTimer != NULL) {
303 AlarmCancel(chan->erfc.retransmissionTimer);
304 AlarmDelete(chan->erfc.retransmissionTimer);
305 }
306
307 if (chan->part.options != NULL) {
308 L2capFree(chan->part.options);
309 }
310
311 if (chan->erfc.txList != NULL) {
312 L2capDestroyChannelTx(chan);
313 }
314
315 if (chan->erfc.rxSarPacket != NULL) {
316 PacketFree(chan->erfc.rxSarPacket);
317 }
318
319 L2capFree(chan);
320 return;
321 }
322
L2capDisconnectTimeout(const void * parameter)323 static void L2capDisconnectTimeout(const void *parameter)
324 {
325 L2capInstance *inst = L2capGetInstance();
326 L2capConnection *conn = NULL;
327 ListNode *node = NULL;
328
329 if (inst->connList == NULL) {
330 return;
331 }
332
333 node = ListGetFirstNode(inst->connList);
334 while (node != NULL) {
335 conn = ListGetNodeData(node);
336 if (conn == parameter) {
337 if (ListGetFirstNode(conn->chanList) != NULL) {
338 break;
339 }
340
341 AlarmDelete(conn->discTimer);
342 conn->discTimer = NULL;
343 // Reason: REMOTE USER TERMINATED CONNECTION
344 L2capDisconnect(conn->aclHandle, 0x13);
345 break;
346 }
347
348 node = ListGetNextNode(node);
349 }
350
351 return;
352 }
353
L2capDisconnectTimeoutCallback(void * parameter)354 static void L2capDisconnectTimeoutCallback(void *parameter)
355 {
356 L2capAsynchronousProcess(L2capDisconnectTimeout, NULL, parameter);
357 return;
358 }
359
L2capDeleteChannel(L2capConnection * conn,L2capChannel * chan,uint16_t removeAcl)360 void L2capDeleteChannel(L2capConnection *conn, L2capChannel *chan, uint16_t removeAcl)
361 {
362 ListRemoveNode(conn->chanList, chan);
363 L2capDestroyChannel(chan);
364
365 if (removeAcl) {
366 if (ListGetFirstNode(conn->chanList) == NULL) {
367 // Reason: REMOTE USER TERMINATED CONNECTION
368 L2capDisconnect(conn->aclHandle, 0x13);
369 }
370 } else {
371 if (ListGetFirstNode(conn->chanList) == NULL) {
372 if (conn->discTimer != NULL) {
373 AlarmCancel(conn->discTimer);
374 } else {
375 conn->discTimer = AlarmCreate("", false);
376 }
377
378 AlarmSet(conn->discTimer, L2CAP_DISCONNECTION_TIME_OUT, L2capDisconnectTimeoutCallback, conn);
379 }
380 }
381
382 return;
383 }
384
L2capNewConnection(const BtAddr * addr,uint16_t aclHandle)385 L2capConnection *L2capNewConnection(const BtAddr *addr, uint16_t aclHandle)
386 {
387 L2capInstance *inst = L2capGetInstance();
388 L2capConnection *conn = NULL;
389
390 conn = L2capAlloc(sizeof(L2capConnection));
391 if (conn == NULL) {
392 return NULL;
393 }
394
395 (void)memcpy_s(&(conn->addr), sizeof(BtAddr), addr, sizeof(BtAddr));
396 conn->aclHandle = aclHandle;
397 conn->state = L2CAP_CONNECTION_IDLE;
398 conn->info.state = L2CAP_INFO_STATE_NONE;
399 conn->nextIdentifier = L2CAP_MIN_IDENTIFIER;
400
401 conn->chanList = ListCreate(NULL);
402 conn->pendingList = ListCreate(NULL);
403 conn->discTimer = NULL;
404
405 ListAddFirst(inst->connList, conn);
406 return conn;
407 }
408
L2capDeleteConnection(L2capConnection * conn)409 void L2capDeleteConnection(L2capConnection *conn)
410 {
411 L2capInstance *inst = L2capGetInstance();
412 ListNode *node = NULL;
413
414 if (conn->chanList != NULL) {
415 L2capChannel *chan = NULL;
416
417 while (1) {
418 node = ListGetFirstNode(conn->chanList);
419 if (node == NULL) {
420 break;
421 }
422
423 chan = ListGetNodeData(node);
424 ListRemoveNode(conn->chanList, chan);
425
426 L2capDestroyChannel(chan);
427 }
428
429 ListDelete(conn->chanList);
430 }
431
432 if (conn->pendingList != NULL) {
433 L2capClearPendingRequest(conn->pendingList);
434 ListDelete(conn->pendingList);
435 }
436
437 if (conn->discTimer != NULL) {
438 AlarmCancel(conn->discTimer);
439 AlarmDelete(conn->discTimer);
440 conn->discTimer = NULL;
441 }
442
443 ListRemoveNode(inst->connList, conn);
444 L2capFree(conn);
445
446 // if no connection exists, reset nextLcid value
447 if (ListGetFirstNode(inst->connList) == NULL) {
448 inst->nextLcid = L2CAP_MIN_CID;
449 }
450
451 return;
452 }