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_cmn.h"
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "log.h"
23
24 #include "allocator.h"
25 #include "bt_endian.h"
26
27 #include "btm.h"
28 #include "hci/hci.h"
29
30 #include "../btm/btm_thread.h"
31
32 typedef struct {
33 uint16_t handle;
34 uint16_t length;
35 uint16_t cid;
36 Packet *pkt;
37 } L2capFragmentationPacket;
38
39 static L2capBdrCallback g_l2capBdr;
40 static L2capLeCallback g_l2capLe;
41
42 static List *g_fragmentationList;
43
L2capProcessPacket(uint16_t handle,uint16_t cid,Packet * pkt)44 static void L2capProcessPacket(uint16_t handle, uint16_t cid, Packet *pkt)
45 {
46 if (cid >= L2CAP_MIN_CID) {
47 if (g_l2capBdr.recvL2capPacket != NULL) {
48 g_l2capBdr.recvL2capPacket(handle, cid, pkt);
49 }
50 return;
51 } else if ((cid >= L2CAP_LE_MIN_CID) && (cid <= L2CAP_LE_MAX_CID)) {
52 if (g_l2capLe.recvL2capPacket != NULL) {
53 g_l2capLe.recvL2capPacket(handle, cid, pkt);
54 }
55 return;
56 }
57
58 switch (cid) {
59 case L2CAP_SIGNALING_CHANNEL:
60 if (g_l2capBdr.recvL2capPacket != NULL) {
61 g_l2capBdr.recvL2capPacket(handle, cid, pkt);
62 }
63 return;
64 case L2CAP_LE_ATTRIBUTE_PROTOCOL: // dummy
65 case L2CAP_LE_SIGNALING_CHANNEL: // dummy
66 case L2CAP_LE_SECURITY_MANAGER_PROTOCOL:
67 if (g_l2capLe.recvL2capPacket != NULL) {
68 g_l2capLe.recvL2capPacket(handle, cid, pkt);
69 }
70 return;
71 default:
72 break;
73 }
74
75 return;
76 }
77
L2capRecombineStart(uint16_t handle,uint16_t length,uint16_t cid,const Packet * pkt)78 static void L2capRecombineStart(uint16_t handle, uint16_t length, uint16_t cid, const Packet *pkt)
79 {
80 L2capFragmentationPacket *frag = NULL;
81 ListNode *node = NULL;
82 Packet *tpkt = NULL;
83
84 if (g_fragmentationList == NULL) {
85 return;
86 }
87
88 // if there are already packet with the same handle, the old packet will be discard
89 node = ListGetFirstNode(g_fragmentationList);
90 while (node != NULL) {
91 frag = ListGetNodeData(node);
92 if (frag->handle == handle) {
93 ListRemoveNode(g_fragmentationList, frag);
94 PacketFree(frag->pkt);
95 L2capFree(frag);
96 break;
97 }
98
99 node = ListGetNextNode(node);
100 }
101
102 tpkt = PacketRefMalloc(pkt);
103 frag = L2capAlloc(sizeof(L2capFragmentationPacket));
104 if (frag == NULL) {
105 LOG_WARN("malloc failed");
106 return;
107 }
108
109 frag->handle = handle;
110 frag->length = length;
111 frag->cid = cid;
112 frag->pkt = tpkt;
113
114 ListAddLast(g_fragmentationList, frag);
115 return;
116 }
117
L2capRecombineContinue(uint16_t handle,const Packet * pkt)118 static void L2capRecombineContinue(uint16_t handle, const Packet *pkt)
119 {
120 L2capFragmentationPacket *frag = NULL;
121 ListNode *node = NULL;
122 uint32_t pktLength;
123
124 if (g_fragmentationList == NULL) {
125 return;
126 }
127
128 node = ListGetFirstNode(g_fragmentationList);
129 while (node != NULL) {
130 frag = ListGetNodeData(node);
131 if (frag->handle == handle) {
132 PacketAssemble(frag->pkt, pkt);
133 pktLength = PacketSize(frag->pkt);
134 if (frag->length == (pktLength - L2CAP_HEADER_LENGTH)) {
135 L2capProcessPacket(handle, frag->cid, frag->pkt);
136
137 ListRemoveNode(g_fragmentationList, frag);
138 PacketFree(frag->pkt);
139 L2capFree(frag);
140 } else if (frag->length < (pktLength - L2CAP_HEADER_LENGTH)) { // invalid packet length
141 ListRemoveNode(g_fragmentationList, frag);
142 PacketFree(frag->pkt);
143 L2capFree(frag);
144 }
145
146 break;
147 }
148
149 node = ListGetNextNode(node);
150 }
151
152 return;
153 }
154
L2capAclDataReceived(uint16_t handle,uint8_t pb,uint8_t bc,Packet * pkt)155 static void L2capAclDataReceived(uint16_t handle, uint8_t pb, uint8_t bc, Packet *pkt)
156 {
157 if ((pb == L2CAP_FIRST_NON_AUTOMATICALLY_FLUSHABLE_PACKET) ||
158 (pb == L2CAP_FIRST_AUTOMATICALLY_FLUSHABLE_PACKET)) { // start packet
159 uint16_t pktLength = PacketSize(pkt);
160 if (pktLength <= L2CAP_HEADER_LENGTH) {
161 return;
162 }
163
164 uint8_t header[L2CAP_HEADER_LENGTH] = {0};
165 PacketRead(pkt, header, 0, sizeof(header));
166 uint16_t length = L2capLe16ToCpu(header + 0);
167 uint16_t cid = L2capLe16ToCpu(header + L2CAP_OFFSET_2);
168
169 if (length == (pktLength - L2CAP_HEADER_LENGTH)) {
170 L2capProcessPacket(handle, cid, pkt);
171 } else {
172 // invalid packet length
173 if (length < (pktLength - L2CAP_HEADER_LENGTH)) {
174 return;
175 }
176 L2capRecombineStart(handle, length, cid, pkt);
177 }
178 } else { // continue packet
179 L2capRecombineContinue(handle, pkt);
180 }
181
182 return;
183 }
184
185 typedef struct {
186 uint16_t handle;
187 uint8_t pb;
188 uint8_t bc;
189 Packet *pkt;
190 } L2capAclDataReceivedContext;
191
L2capAclDataReceivedContextDestroy(void * context)192 static void L2capAclDataReceivedContextDestroy(void *context)
193 {
194 L2capAclDataReceivedContext *ctx = NULL;
195
196 ctx = context;
197
198 PacketFree(ctx->pkt);
199 L2capFree(ctx);
200 return;
201 }
202
L2capAclDataReceivedCallbackProcess(const void * context)203 static void L2capAclDataReceivedCallbackProcess(const void *context)
204 {
205 L2capAclDataReceivedContext *ctx = NULL;
206
207 ctx = (L2capAclDataReceivedContext *)context;
208
209 L2capAclDataReceived(ctx->handle, ctx->pb, ctx->bc, ctx->pkt);
210
211 L2capAclDataReceivedContextDestroy(ctx);
212 return;
213 }
214
L2capAclDataReceivedCallback(uint16_t handle,uint8_t pb,uint8_t bc,Packet * pkt)215 static void L2capAclDataReceivedCallback(uint16_t handle, uint8_t pb, uint8_t bc, Packet *pkt)
216 {
217 L2capAclDataReceivedContext *ctx = NULL;
218
219 ctx = L2capAlloc(sizeof(L2capAclDataReceivedContext));
220 if (ctx == NULL) {
221 LOG_WARN("malloc failed");
222 return;
223 }
224
225 ctx->handle = handle;
226 ctx->pb = pb;
227 ctx->bc = bc;
228 ctx->pkt = PacketRefMalloc(pkt);
229
230 L2capAsynchronousProcess(L2capAclDataReceivedCallbackProcess, L2capAclDataReceivedContextDestroy, ctx);
231 return;
232 }
233
L2capAclDisconnected(uint8_t status,uint16_t handle,uint8_t reason,void * context)234 static void L2capAclDisconnected(uint8_t status, uint16_t handle, uint8_t reason, void *context)
235 {
236 L2capFragmentationPacket *frag = NULL;
237 ListNode *node = NULL;
238
239 if (g_fragmentationList != NULL) {
240 node = ListGetFirstNode(g_fragmentationList);
241 while (node != NULL) {
242 frag = ListGetNodeData(node);
243 if (frag->handle == handle) {
244 ListRemoveNode(g_fragmentationList, frag);
245 PacketFree(frag->pkt);
246 L2capFree(frag);
247
248 node = ListGetFirstNode(g_fragmentationList);
249 continue;
250 }
251
252 node = ListGetNextNode(node);
253 }
254 }
255
256 if (g_l2capBdr.aclDisconnected != NULL) {
257 g_l2capBdr.aclDisconnected(handle, status, reason);
258 }
259
260 if (g_l2capLe.aclDisconnected != NULL) {
261 g_l2capLe.aclDisconnected(handle, status, reason);
262 }
263 return;
264 }
265
266 typedef struct {
267 uint8_t status;
268 uint16_t handle;
269 uint8_t reason;
270 void *context;
271 } L2capAclDisconnectedContext;
272
L2capAclDisconnectedCallbackProcess(const void * context)273 static void L2capAclDisconnectedCallbackProcess(const void *context)
274 {
275 L2capAclDisconnectedContext *ctx = NULL;
276
277 ctx = (L2capAclDisconnectedContext *)context;
278
279 L2capAclDisconnected(ctx->status, ctx->handle, ctx->reason, ctx->context);
280
281 L2capFree(ctx);
282 return;
283 }
284
L2capAclDisconnectedCallback(uint8_t status,uint16_t handle,uint8_t reason,void * context)285 static void L2capAclDisconnectedCallback(uint8_t status, uint16_t handle, uint8_t reason, void *context)
286 {
287 L2capAclDisconnectedContext *ctx = NULL;
288
289 ctx = L2capAlloc(sizeof(L2capAclDisconnectedContext));
290 if (ctx == NULL) {
291 LOG_WARN("malloc failed");
292 return;
293 }
294
295 ctx->status = status;
296 ctx->handle = handle;
297 ctx->reason = reason;
298 ctx->context = context;
299
300 L2capAsynchronousProcess(L2capAclDisconnectedCallbackProcess, L2capFree, ctx);
301 return;
302 }
303
L2capBdrAclConnected(uint8_t status,uint16_t handle,const BtAddr * addr)304 static void L2capBdrAclConnected(uint8_t status, uint16_t handle, const BtAddr *addr)
305 {
306 if (g_l2capBdr.aclConnected != NULL) {
307 g_l2capBdr.aclConnected((BtAddr *)addr, handle, status);
308 }
309 return;
310 }
311
312 typedef struct {
313 uint8_t status;
314 uint16_t handle;
315 BtAddr addr;
316 } L2capBdrAclConnectedContext;
317
L2capBdrAclConnectedCallbackProcess(const void * context)318 static void L2capBdrAclConnectedCallbackProcess(const void *context)
319 {
320 L2capBdrAclConnectedContext *ctx = NULL;
321
322 ctx = (L2capBdrAclConnectedContext *)context;
323
324 L2capBdrAclConnected(ctx->status, ctx->handle, &(ctx->addr));
325
326 L2capFree(ctx);
327 return;
328 }
329
L2capBdrAclConnectedCallback(const BtmAclConnectCompleteParam * param,void * context)330 static void L2capBdrAclConnectedCallback(const BtmAclConnectCompleteParam *param, void *context)
331 {
332 L2capBdrAclConnectedContext *ctx = NULL;
333
334 ctx = L2capAlloc(sizeof(L2capBdrAclConnectedContext));
335 if (ctx == NULL) {
336 LOG_WARN("malloc failed");
337 return;
338 }
339 ctx->status = param->status;
340 ctx->handle = param->connectionHandle;
341 (void)memcpy_s(&(ctx->addr), sizeof(BtAddr), param->addr, sizeof(BtAddr));
342
343 L2capAsynchronousProcess(L2capBdrAclConnectedCallbackProcess, L2capFree, ctx);
344 return;
345 }
346
L2capLeAclConnected(uint8_t status,uint16_t handle,const BtAddr * addr,uint8_t role,void * context)347 static void L2capLeAclConnected(uint8_t status, uint16_t handle, const BtAddr *addr, uint8_t role, void *context)
348 {
349 if (g_l2capLe.aclConnected != NULL) {
350 g_l2capLe.aclConnected((BtAddr *)addr, handle, role, status);
351 }
352 return;
353 }
354
355 typedef struct {
356 uint8_t status;
357 uint16_t handle;
358 BtAddr addr;
359 uint8_t role;
360 void *context;
361 } L2capLeAclConnectedContext;
362
L2capLeAclConnectedCallbackProcess(const void * context)363 static void L2capLeAclConnectedCallbackProcess(const void *context)
364 {
365 L2capLeAclConnectedContext *ctx = NULL;
366
367 ctx = (L2capLeAclConnectedContext *)context;
368
369 L2capLeAclConnected(ctx->status, ctx->handle, &(ctx->addr), ctx->role, ctx->context);
370
371 L2capFree(ctx);
372 return;
373 }
374
L2capLeAclConnectedCallback(uint8_t status,uint16_t handle,const BtAddr * addr,uint8_t role,void * context)375 static void L2capLeAclConnectedCallback(
376 uint8_t status, uint16_t handle, const BtAddr *addr, uint8_t role, void *context)
377 {
378 L2capLeAclConnectedContext *ctx = NULL;
379
380 ctx = L2capAlloc(sizeof(L2capLeAclConnectedContext));
381 if (ctx == NULL) {
382 LOG_WARN("malloc failed");
383 return;
384 }
385
386 ctx->status = status;
387 ctx->handle = handle;
388 (void)memcpy_s(&(ctx->addr), sizeof(BtAddr), addr, sizeof(BtAddr));
389 ctx->role = role;
390 ctx->context = context;
391
392 L2capAsynchronousProcess(L2capLeAclConnectedCallbackProcess, L2capFree, ctx);
393 return;
394 }
395
L2capCpuToLe16(uint8_t * dst,uint16_t src)396 void L2capCpuToLe16(uint8_t *dst, uint16_t src)
397 {
398 uint16_t tmp;
399
400 tmp = H2LE_16(src);
401 (void)memcpy_s(dst, sizeof(uint16_t), &tmp, sizeof(uint16_t));
402 return;
403 }
404
L2capLe16ToCpu(const uint8_t * src)405 uint16_t L2capLe16ToCpu(const uint8_t *src)
406 {
407 uint16_t tmp = 0;
408
409 for (size_t i = 0; i < sizeof(uint16_t); i++) {
410 tmp += (src[i] << (L2CAP_SIZE_8 * i));
411 }
412
413 return LE2H_16(tmp);
414 }
415
L2capAlloc(int size)416 void *L2capAlloc(int size)
417 {
418 void *p;
419
420 p = MEM_MALLOC.alloc(size);
421 if (p != NULL) {
422 (void)memset_s(p, size, 0, size);
423 }
424
425 return p;
426 }
427
L2capFree(void * p)428 void L2capFree(void *p)
429 {
430 MEM_MALLOC.free(p);
431 return;
432 }
433
L2capAsynchronousProcess(void (* task)(const void * context),void (* destroy)(void * context),void * context)434 int L2capAsynchronousProcess(void (*task)(const void *context), void (*destroy)(void *context), void *context)
435 {
436 int result;
437
438 result = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_LA2CAP, (void (*)(void *))task, context);
439 if (result != BT_SUCCESS) {
440 if (destroy != NULL) {
441 destroy(context);
442 }
443 }
444
445 return result;
446 }
447
L2capBuildSignalPacket(uint16_t cid,const L2capSignalHeader * signal,const uint8_t * data)448 Packet *L2capBuildSignalPacket(uint16_t cid, const L2capSignalHeader *signal, const uint8_t *data)
449 {
450 Packet *pkt = NULL;
451 uint8_t *buff = NULL;
452
453 pkt = PacketMalloc(0, 0, L2CAP_HEADER_LENGTH + L2CAP_SIGNAL_HEADER_LENGTH + signal->length);
454 if (pkt == NULL) {
455 return NULL;
456 }
457
458 buff = BufferPtr(PacketContinuousPayload(pkt));
459
460 // build Length field
461 L2capCpuToLe16(buff + 0, L2CAP_SIGNAL_HEADER_LENGTH + signal->length);
462
463 // build cid field
464 L2capCpuToLe16(buff + L2CAP_OFFSET_2, cid);
465
466 buff[L2CAP_OFFSET_4] = signal->code;
467 buff[L2CAP_OFFSET_5] = signal->identifier;
468
469 L2capCpuToLe16(buff + L2CAP_OFFSET_6, signal->length);
470
471 if (signal->length > 0) {
472 if (memcpy_s(
473 buff + L2CAP_HEADER_LENGTH + L2CAP_SIGNAL_HEADER_LENGTH, signal->length, data, signal->length) != EOK) {
474 LOG_ERROR("L2capBuildSignalPacket memcpy_s failed");
475 }
476 }
477
478 return pkt;
479 }
480
L2capSendCommandReject(uint16_t handle,uint16_t cid,uint8_t ident,uint16_t reason,uint16_t data[2])481 int L2capSendCommandReject(uint16_t handle, uint16_t cid, uint8_t ident, uint16_t reason, uint16_t data[2])
482 {
483 Packet *pkt = NULL;
484 uint8_t buff[12] = {0};
485 L2capSignalHeader siganl = {0};
486
487 (void)memset_s(buff, sizeof(buff), 0, sizeof(buff));
488
489 L2capCpuToLe16(buff + 0, reason);
490
491 if (reason == L2CAP_COMMAND_NOT_UNDERSTOOD) {
492 siganl.length = L2CAP_SIZE_2;
493 } else if (reason == L2CAP_SIGNAL_MTU_EXCEEDED) {
494 L2capCpuToLe16(buff + L2CAP_OFFSET_2, L2CAP_SIGNAL_MTU);
495 siganl.length = L2CAP_SIZE_4;
496 } else if (reason == L2CAP_INVALID_CID_IN_REQUEST) {
497 L2capCpuToLe16(buff + L2CAP_OFFSET_2, data[0]);
498 L2capCpuToLe16(buff + L2CAP_OFFSET_4, data[1]);
499
500 siganl.length = L2CAP_SIZE_6;
501 } else {
502 return BT_BAD_PARAM;
503 }
504
505 siganl.code = L2CAP_COMMAND_REJECT;
506 siganl.identifier = ident;
507
508 pkt = L2capBuildSignalPacket(cid, &siganl, buff);
509 return L2capSendPacket(handle, L2CAP_NONE_FLUSH_PACKET, pkt);
510 }
511
L2capCreatePendingRequest(List * pendingList,uint16_t lcid,const L2capSignalHeader * signal,uint64_t timeo,AlarmCallback timerExpired)512 void L2capCreatePendingRequest(
513 List *pendingList, uint16_t lcid, const L2capSignalHeader *signal, uint64_t timeo, AlarmCallback timerExpired)
514 {
515 L2capPendingRequest *req = NULL;
516
517 req = L2capAlloc(sizeof(L2capPendingRequest));
518 if (req == NULL) {
519 LOG_WARN("malloc failed");
520 return;
521 }
522
523 req->lcid = lcid;
524 req->code = signal->code;
525 req->identifier = signal->identifier;
526 req->timer = AlarmCreate("", false);
527 AlarmSet(req->timer, timeo, timerExpired, req);
528
529 ListAddLast(pendingList, req);
530 return;
531 }
532
L2capDestroyPendingRequest(List * pendingList,uint8_t identifier)533 void L2capDestroyPendingRequest(List *pendingList, uint8_t identifier)
534 {
535 L2capPendingRequest *req = NULL;
536
537 req = L2capGetPendingRequest(pendingList, identifier);
538 if (req != NULL) {
539 ListRemoveNode(pendingList, req);
540 AlarmCancel(req->timer);
541 AlarmDelete(req->timer);
542 L2capFree(req);
543 }
544
545 return;
546 }
547
L2capGetPendingRequest(List * pendingList,uint8_t identifier)548 L2capPendingRequest *L2capGetPendingRequest(List *pendingList, uint8_t identifier)
549 {
550 L2capPendingRequest *req = NULL;
551 ListNode *node = NULL;
552
553 node = ListGetFirstNode(pendingList);
554 while (node != NULL) {
555 req = ListGetNodeData(node);
556 if (req->identifier == identifier) {
557 return req;
558 }
559
560 node = ListGetNextNode(node);
561 }
562
563 return NULL;
564 }
565
L2capGetPendingRequest2(List * pendingList,const void * request)566 L2capPendingRequest *L2capGetPendingRequest2(List *pendingList, const void *request)
567 {
568 L2capPendingRequest *req = NULL;
569 ListNode *node = NULL;
570
571 node = ListGetFirstNode(pendingList);
572 while (node != NULL) {
573 req = ListGetNodeData(node);
574 if (req == request) {
575 return req;
576 }
577
578 node = ListGetNextNode(node);
579 }
580
581 return NULL;
582 }
583
L2capClearPendingRequest(List * pendingList)584 void L2capClearPendingRequest(List *pendingList)
585 {
586 L2capPendingRequest *req = NULL;
587 ListNode *node = NULL;
588
589 while (1) {
590 node = ListGetFirstNode(pendingList);
591 if (node == NULL) {
592 break;
593 }
594
595 req = ListGetNodeData(node);
596
597 ListRemoveNode(pendingList, req);
598 AlarmCancel(req->timer);
599 AlarmDelete(req->timer);
600 L2capFree(req);
601 }
602
603 return;
604 }
605
L2capSendPacket(uint16_t handle,uint16_t flushTimeout,Packet * pkt)606 int L2capSendPacket(uint16_t handle, uint16_t flushTimeout, Packet *pkt)
607 {
608 int result;
609
610 result = L2capSendPacketNoFree(handle, flushTimeout, pkt);
611 PacketFree(pkt);
612 return result;
613 }
614
L2capSendPacketNoFree(uint16_t handle,uint16_t flushTimeout,Packet * pkt)615 int L2capSendPacketNoFree(uint16_t handle, uint16_t flushTimeout, Packet *pkt)
616 {
617 int result;
618
619 if (BTM_IsControllerSupportNonFlushablePacketBoundaryFlag()) {
620 if (flushTimeout == L2CAP_NONE_FLUSH_PACKET) {
621 result = HCI_SendAclData(handle, NON_FLUSHABLE_PACKET, pkt);
622 } else {
623 result = HCI_SendAclData(handle, FLUSHABLE_PACKET, pkt);
624 }
625 } else {
626 result = HCI_SendAclData(handle, FLUSHABLE_PACKET, pkt);
627 }
628
629 return result;
630 }
631
L2capLeSendPacket(uint16_t handle,Packet * pkt)632 int L2capLeSendPacket(uint16_t handle, Packet *pkt)
633 {
634 int result;
635
636 result = HCI_SendAclData(handle, NON_FLUSHABLE_PACKET, pkt);
637 PacketFree(pkt);
638 return result;
639 }
640
L2capGetTxBufferSize()641 uint16_t L2capGetTxBufferSize()
642 {
643 uint16_t bufferSize = 0;
644
645 BTM_GetAclDataPacketLength(&bufferSize);
646 return bufferSize;
647 }
648
L2capLeGetTxBufferSize()649 uint16_t L2capLeGetTxBufferSize()
650 {
651 uint16_t bufferSize = 0;
652
653 BTM_GetLeAclDataPacketLength(&bufferSize);
654 return bufferSize;
655 }
656
L2capGetRxBufferSize()657 uint16_t L2capGetRxBufferSize()
658 {
659 return (uint16_t)L2CAP_MTU_SIZE;
660 }
661
L2capConnectBdr(const BtAddr * addr)662 int L2capConnectBdr(const BtAddr *addr)
663 {
664 return BTM_AclConnect(addr);
665 }
666
L2capConnectLe(const BtAddr * addr)667 int L2capConnectLe(const BtAddr *addr)
668 {
669 return BTM_LeConnect(addr);
670 }
671
L2capConnectLeCancel(const BtAddr * addr)672 int L2capConnectLeCancel(const BtAddr *addr)
673 {
674 return BTM_LeCancelConnect(addr);
675 }
676
L2capAddConnectionRef(uint16_t handle)677 int L2capAddConnectionRef(uint16_t handle)
678 {
679 LOG_DEBUG("L2cap Call BTM_AclAddRef, handle = 0x%04X", handle);
680 return BTM_AclAddRef(handle);
681 }
682
L2capDisconnect(uint16_t handle,uint8_t reason)683 int L2capDisconnect(uint16_t handle, uint8_t reason)
684 {
685 LOG_DEBUG("L2cap Call BTM_AclRelease, handle = 0x%04X", handle);
686 BTM_AclRelease(handle);
687 return BT_SUCCESS;
688 }
689
690 static BtmAclCallbacks g_btmAclCallback = {
691 .connectionComplete = L2capBdrAclConnectedCallback,
692 .disconnectionComplete = L2capAclDisconnectedCallback,
693 .leConnectionComplete = L2capLeAclConnectedCallback,
694 .leDisconnectionComplete = L2capAclDisconnectedCallback,
695 };
696
697 static HciAclCallbacks g_hciAclCallback = {
698 L2capAclDataReceivedCallback,
699 };
700
L2capRegisterBdr(const L2capBdrCallback * cb)701 int L2capRegisterBdr(const L2capBdrCallback *cb)
702 {
703 (void)memcpy_s(&g_l2capBdr, sizeof(L2capBdrCallback), cb, sizeof(L2capBdrCallback));
704 return BT_SUCCESS;
705 }
706
L2capRegisterLe(const L2capLeCallback * cb)707 int L2capRegisterLe(const L2capLeCallback *cb)
708 {
709 (void)memcpy_s(&g_l2capLe, sizeof(L2capLeCallback), cb, sizeof(L2capLeCallback));
710 return BT_SUCCESS;
711 }
712
L2capCommonStartup()713 void L2capCommonStartup()
714 {
715 if (g_fragmentationList != NULL) {
716 return;
717 }
718
719 g_fragmentationList = ListCreate(NULL);
720
721 BTM_RegisterAclCallbacks(&g_btmAclCallback, NULL);
722 HCI_RegisterAclCallbacks(&g_hciAclCallback);
723
724 return;
725 }
726
L2capCommonShutdown()727 void L2capCommonShutdown()
728 {
729 BTM_DeregisterAclCallbacks(&g_btmAclCallback);
730 HCI_DeregisterAclCallbacks(&g_hciAclCallback);
731
732 if (g_fragmentationList != NULL) {
733 L2capFragmentationPacket *frag = NULL;
734 ListNode *node = NULL;
735
736 while (true) {
737 node = ListGetFirstNode(g_fragmentationList);
738 if (node == NULL) {
739 break;
740 }
741
742 frag = ListGetNodeData(node);
743 ListRemoveNode(g_fragmentationList, frag);
744 PacketFree(frag->pkt);
745 L2capFree(frag);
746 }
747
748 ListDelete(g_fragmentationList);
749 g_fragmentationList = NULL;
750 }
751
752 return;
753 }
754