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_if.h"
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "module.h"
23
24 #include "semaphore.h"
25
26 #include "../btm/btm_thread.h"
27 #include "l2cap.h"
28 #include "l2cap_cmn.h"
29
30 typedef struct {
31 uint16_t lpsm;
32 L2capService service;
33 void *context;
34 void (*cb)(uint16_t lpsm, int result);
35 } L2cifRegisterServiceContext;
36
L2cifRegisterService(const void * context)37 static void L2cifRegisterService(const void *context)
38 {
39 L2cifRegisterServiceContext *ctx = NULL;
40 int result;
41
42 ctx = (L2cifRegisterServiceContext *)context;
43
44 result = L2CAP_RegisterService(ctx->lpsm, &(ctx->service), ctx->context);
45 if (ctx->cb != NULL) {
46 ctx->cb(ctx->lpsm, result);
47 }
48
49 L2capFree(ctx);
50 return;
51 }
52
L2CIF_RegisterService(uint16_t lpsm,const L2capService * svc,void * context,void (* cb)(uint16_t lpsm,int result))53 int L2CIF_RegisterService(uint16_t lpsm, const L2capService *svc, void *context, void (*cb)(uint16_t lpsm, int result))
54 {
55 L2cifRegisterServiceContext *ctx = NULL;
56
57 if (svc == NULL) {
58 return BT_BAD_PARAM;
59 }
60
61 ctx = L2capAlloc(sizeof(L2cifRegisterServiceContext));
62 if (ctx == NULL) {
63 return BT_NO_MEMORY;
64 }
65
66 ctx->lpsm = lpsm;
67 (void)memcpy_s(&(ctx->service), sizeof(L2capService), svc, sizeof(L2capService));
68 ctx->context = context;
69 ctx->cb = cb;
70
71 L2capAsynchronousProcess(L2cifRegisterService, L2capFree, ctx);
72 return BT_SUCCESS;
73 }
74
75 typedef struct {
76 uint16_t lpsm;
77 void (*cb)(uint16_t lpsm, int result);
78 } L2cifDeregisterServiceContext;
79
L2cifDeregisterService(const void * context)80 static void L2cifDeregisterService(const void *context)
81 {
82 L2cifDeregisterServiceContext *ctx = NULL;
83 int result;
84
85 ctx = (L2cifDeregisterServiceContext *)context;
86
87 result = L2CAP_DeregisterService(ctx->lpsm);
88 if (ctx->cb != NULL) {
89 ctx->cb(ctx->lpsm, result);
90 }
91
92 L2capFree(ctx);
93 return;
94 }
95
L2CIF_DeregisterService(uint16_t lpsm,void (* cb)(uint16_t lpsm,int result))96 void L2CIF_DeregisterService(uint16_t lpsm, void (*cb)(uint16_t lpsm, int result))
97 {
98 L2cifDeregisterServiceContext *ctx = NULL;
99
100 ctx = L2capAlloc(sizeof(L2cifDeregisterServiceContext));
101 if (ctx == NULL) {
102 LOG_WARN("malloc failed");
103 return;
104 }
105
106 ctx->lpsm = lpsm;
107 ctx->cb = cb;
108
109 L2capAsynchronousProcess(L2cifDeregisterService, L2capFree, ctx);
110 return;
111 }
112
113 typedef struct {
114 BtAddr addr;
115 uint16_t lpsm;
116 uint16_t rpsm;
117 void *context;
118 void (*cb)(const BtAddr *addr, uint16_t lcid, int result, void *context);
119 } L2cifConnectReqContext;
120
L2cifConnectReq(const void * context)121 static void L2cifConnectReq(const void *context)
122 {
123 L2cifConnectReqContext *ctx = NULL;
124 uint16_t lcid = 0;
125 int result;
126
127 ctx = (L2cifConnectReqContext *)context;
128
129 result = L2CAP_ConnectReq(&(ctx->addr), ctx->lpsm, ctx->rpsm, &lcid);
130 if (ctx->cb != NULL) {
131 ctx->cb(&(ctx->addr), lcid, result, ctx->context);
132 }
133
134 L2capFree(ctx);
135 return;
136 }
137
L2CIF_ConnectReq(const BtAddr * addr,uint16_t lpsm,uint16_t rpsm,void * context,void (* cb)(const BtAddr * addr,uint16_t lcid,int result,void * context))138 int L2CIF_ConnectReq(const BtAddr *addr, uint16_t lpsm, uint16_t rpsm, void *context,
139 void (*cb)(const BtAddr *addr, uint16_t lcid, int result, void *context))
140 {
141 L2cifConnectReqContext *ctx = NULL;
142
143 if (addr == NULL) {
144 return BT_BAD_PARAM;
145 }
146
147 ctx = L2capAlloc(sizeof(L2cifConnectReqContext));
148 if (ctx == NULL) {
149 return BT_NO_MEMORY;
150 }
151
152 (void)memcpy_s(&(ctx->addr), sizeof(BtAddr), addr, sizeof(BtAddr));
153 ctx->lpsm = lpsm;
154 ctx->rpsm = rpsm;
155 ctx->context = context;
156 ctx->cb = cb;
157
158 L2capAsynchronousProcess(L2cifConnectReq, L2capFree, ctx);
159 return BT_SUCCESS;
160 }
161
162 typedef struct {
163 uint16_t lcid;
164 uint8_t id;
165 uint16_t result;
166 uint16_t status;
167 void (*cb)(uint16_t lcid, int result);
168 } L2cifConnectRspContext;
169
L2cifConnectRsp(const void * context)170 static void L2cifConnectRsp(const void *context)
171 {
172 L2cifConnectRspContext *ctx = NULL;
173 int result;
174
175 ctx = (L2cifConnectRspContext *)context;
176
177 result = L2CAP_ConnectRsp(ctx->lcid, ctx->id, ctx->result, ctx->status);
178 if (ctx->cb != NULL) {
179 ctx->cb(ctx->lcid, result);
180 }
181
182 L2capFree(ctx);
183 return;
184 }
185
L2CIF_ConnectRsp(uint16_t lcid,uint8_t id,uint16_t result,uint16_t status,void (* cb)(uint16_t lcid,int result))186 void L2CIF_ConnectRsp(
187 uint16_t lcid, uint8_t id, uint16_t result, uint16_t status, void (*cb)(uint16_t lcid, int result))
188 {
189 L2cifConnectRspContext *ctx = NULL;
190
191 ctx = L2capAlloc(sizeof(L2cifConnectRspContext));
192 if (ctx == NULL) {
193 LOG_WARN("malloc failed");
194 return;
195 }
196
197 ctx->lcid = lcid;
198 ctx->id = id;
199 ctx->result = result;
200 ctx->status = status;
201 ctx->cb = cb;
202
203 L2capAsynchronousProcess(L2cifConnectRsp, L2capFree, ctx);
204 return;
205 }
206
207 typedef struct {
208 uint16_t lcid;
209 L2capConfigInfo cfg;
210 void (*cb)(uint16_t lcid, int result);
211 } L2cifConfigReqContext;
212
L2cifConfigReq(const void * context)213 static void L2cifConfigReq(const void *context)
214 {
215 L2cifConfigReqContext *ctx = NULL;
216 int result;
217
218 ctx = (L2cifConfigReqContext *)context;
219
220 result = L2CAP_ConfigReq(ctx->lcid, &(ctx->cfg));
221 if (ctx->cb != NULL) {
222 ctx->cb(ctx->lcid, result);
223 }
224
225 L2capFree(ctx);
226 return;
227 }
228
L2CIF_ConfigReq(uint16_t lcid,const L2capConfigInfo * cfg,void (* cb)(uint16_t lcid,int result))229 int L2CIF_ConfigReq(uint16_t lcid, const L2capConfigInfo *cfg, void (*cb)(uint16_t lcid, int result))
230 {
231 L2cifConfigReqContext *ctx = NULL;
232
233 if (cfg == NULL) {
234 return BT_BAD_PARAM;
235 }
236
237 ctx = L2capAlloc(sizeof(L2cifConfigReqContext));
238 if (ctx == NULL) {
239 return BT_NO_MEMORY;
240 }
241
242 ctx->lcid = lcid;
243 (void)memcpy_s(&(ctx->cfg), sizeof(L2capConfigInfo), cfg, sizeof(L2capConfigInfo));
244 ctx->cb = cb;
245
246 L2capAsynchronousProcess(L2cifConfigReq, L2capFree, ctx);
247 return BT_SUCCESS;
248 }
249
250 typedef struct {
251 uint16_t lcid;
252 uint8_t id;
253 L2capConfigInfo cfg;
254 uint16_t result;
255 void (*cb)(uint16_t lcid, int result);
256 } L2cifConfigRspContext;
257
L2cifConfigRsp(const void * context)258 static void L2cifConfigRsp(const void *context)
259 {
260 L2cifConfigRspContext *ctx = NULL;
261 int result;
262
263 ctx = (L2cifConfigRspContext *)context;
264
265 result = L2CAP_ConfigRsp(ctx->lcid, ctx->id, &(ctx->cfg), ctx->result);
266 if (ctx->cb != NULL) {
267 ctx->cb(ctx->lcid, result);
268 }
269
270 L2capFree(ctx);
271 return;
272 }
273
L2CIF_ConfigRsp(uint16_t lcid,uint8_t id,const L2capConfigInfo * cfg,uint16_t result,void (* cb)(uint16_t lcid,int result))274 int L2CIF_ConfigRsp(
275 uint16_t lcid, uint8_t id, const L2capConfigInfo *cfg, uint16_t result, void (*cb)(uint16_t lcid, int result))
276 {
277 L2cifConfigRspContext *ctx = NULL;
278
279 if (cfg == NULL) {
280 return BT_BAD_PARAM;
281 }
282
283 ctx = L2capAlloc(sizeof(L2cifConfigRspContext));
284 if (ctx == NULL) {
285 return BT_NO_MEMORY;
286 }
287
288 ctx->lcid = lcid;
289 ctx->id = id;
290 (void)memcpy_s(&(ctx->cfg), sizeof(L2capConfigInfo), cfg, sizeof(L2capConfigInfo));
291 ctx->result = result;
292 ctx->cb = cb;
293
294 L2capAsynchronousProcess(L2cifConfigRsp, L2capFree, ctx);
295 return BT_SUCCESS;
296 }
297
298 typedef struct {
299 uint16_t lcid;
300 void (*cb)(uint16_t lcid, int result);
301 } L2cifDisconnectionReqContext;
302
L2cifDisconnectionReq(const void * context)303 static void L2cifDisconnectionReq(const void *context)
304 {
305 L2cifDisconnectionReqContext *ctx = NULL;
306 int result;
307
308 ctx = (L2cifDisconnectionReqContext *)context;
309
310 result = L2CAP_DisconnectionReq(ctx->lcid);
311 if (ctx->cb != NULL) {
312 ctx->cb(ctx->lcid, result);
313 }
314
315 L2capFree(ctx);
316 return;
317 }
318
L2CIF_DisconnectionReq(uint16_t lcid,void (* cb)(uint16_t lcid,int result))319 void L2CIF_DisconnectionReq(uint16_t lcid, void (*cb)(uint16_t lcid, int result))
320 {
321 L2cifDisconnectionReqContext *ctx = NULL;
322
323 ctx = L2capAlloc(sizeof(L2cifDisconnectionReqContext));
324 if (ctx == NULL) {
325 LOG_WARN("malloc failed");
326 return;
327 }
328
329 ctx->lcid = lcid;
330 ctx->cb = cb;
331
332 L2capAsynchronousProcess(L2cifDisconnectionReq, L2capFree, ctx);
333 return;
334 }
335
336 typedef struct {
337 uint16_t lcid;
338 uint8_t id;
339 void (*cb)(uint16_t lcid, int result);
340 } L2cifDisconnectionRspContext;
341
L2cifDisconnectionRsp(const void * context)342 static void L2cifDisconnectionRsp(const void *context)
343 {
344 L2cifDisconnectionRspContext *ctx = NULL;
345 int result;
346
347 ctx = (L2cifDisconnectionRspContext *)context;
348
349 result = L2CAP_DisconnectionRsp(ctx->lcid, ctx->id);
350 if (ctx->cb != NULL) {
351 ctx->cb(ctx->lcid, result);
352 }
353
354 L2capFree(ctx);
355 return;
356 }
357
L2CIF_DisconnectionRsp(uint16_t lcid,uint8_t id,void (* cb)(uint16_t lcid,int result))358 void L2CIF_DisconnectionRsp(uint16_t lcid, uint8_t id, void (*cb)(uint16_t lcid, int result))
359 {
360 L2cifDisconnectionRspContext *ctx = NULL;
361
362 ctx = L2capAlloc(sizeof(L2cifDisconnectionRspContext));
363 if (ctx == NULL) {
364 LOG_WARN("malloc failed");
365 return;
366 }
367
368 ctx->lcid = lcid;
369 ctx->id = id;
370 ctx->cb = cb;
371
372 L2capAsynchronousProcess(L2cifDisconnectionRsp, L2capFree, ctx);
373 return;
374 }
375
376 typedef struct {
377 uint16_t lcid;
378 uint8_t isBusy;
379 void (*cb)(uint16_t lcid, int result);
380 } L2cifLocalBusyContext;
381
L2cifLocalBusy(const void * context)382 static void L2cifLocalBusy(const void *context)
383 {
384 L2cifLocalBusyContext *ctx = NULL;
385 int result;
386
387 ctx = (L2cifLocalBusyContext *)context;
388
389 result = L2CAP_LocalBusy(ctx->lcid, ctx->isBusy);
390 if (ctx->cb != NULL) {
391 ctx->cb(ctx->lcid, result);
392 }
393
394 L2capFree(ctx);
395 return;
396 }
397
L2CIF_LocalBusy(uint16_t lcid,uint8_t isBusy,void (* cb)(uint16_t lcid,int result))398 void L2CIF_LocalBusy(uint16_t lcid, uint8_t isBusy, void (*cb)(uint16_t lcid, int result))
399 {
400 L2cifLocalBusyContext *ctx = NULL;
401
402 ctx = L2capAlloc(sizeof(L2cifLocalBusyContext));
403 if (ctx == NULL) {
404 LOG_WARN("malloc failed");
405 return;
406 }
407
408 ctx->lcid = lcid;
409 ctx->isBusy = isBusy;
410 ctx->cb = cb;
411
412 L2capAsynchronousProcess(L2cifLocalBusy, L2capFree, ctx);
413 return;
414 }
415
416 typedef struct {
417 uint16_t lcid;
418 Packet *pkt;
419 void (*cb)(uint16_t lcid, int result);
420 } L2cifSendDataContext;
421
L2cifSendDataContextDestroy(void * context)422 static void L2cifSendDataContextDestroy(void *context)
423 {
424 L2cifSendDataContext *ctx = NULL;
425
426 ctx = context;
427
428 PacketFree(ctx->pkt);
429 L2capFree(ctx);
430 return;
431 }
432
L2cifSendData(const void * context)433 static void L2cifSendData(const void *context)
434 {
435 L2cifSendDataContext *ctx = NULL;
436 int result;
437
438 ctx = (L2cifSendDataContext *)context;
439
440 result = L2CAP_SendData(ctx->lcid, ctx->pkt);
441 if (ctx->cb != NULL) {
442 ctx->cb(ctx->lcid, result);
443 }
444
445 L2cifSendDataContextDestroy(ctx);
446 return;
447 }
448
L2CIF_SendData(uint16_t lcid,const Packet * pkt,void (* cb)(uint16_t lcid,int result))449 int L2CIF_SendData(uint16_t lcid, const Packet *pkt, void (*cb)(uint16_t lcid, int result))
450 {
451 L2cifSendDataContext *ctx = NULL;
452
453 if (pkt == NULL) {
454 return BT_BAD_PARAM;
455 }
456
457 ctx = L2capAlloc(sizeof(L2cifSendDataContext));
458 if (ctx == NULL) {
459 return BT_NO_MEMORY;
460 }
461
462 ctx->lcid = lcid;
463 ctx->pkt = PacketRefMalloc((Packet *)pkt);
464 ctx->cb = cb;
465
466 L2capAsynchronousProcess(L2cifSendData, L2cifSendDataContextDestroy, ctx);
467 return BT_SUCCESS;
468 }
469
470 typedef struct {
471 L2capEcho echoCallback;
472 void *context;
473 } L2cifRegisterEchoContext;
474
L2cifRegisterEcho(const void * context)475 static void L2cifRegisterEcho(const void *context)
476 {
477 L2cifRegisterEchoContext *ctx = NULL;
478
479 ctx = (L2cifRegisterEchoContext *)context;
480
481 L2CAP_RegisterEcho(&(ctx->echoCallback), ctx->context);
482
483 L2capFree(ctx);
484 return;
485 }
486
L2CIF_RegisterEcho(const L2capEcho * echoCallback,void * context)487 int L2CIF_RegisterEcho(const L2capEcho *echoCallback, void *context)
488 {
489 L2cifRegisterEchoContext *ctx = NULL;
490
491 if (echoCallback == NULL) {
492 return BT_BAD_PARAM;
493 }
494
495 ctx = L2capAlloc(sizeof(L2cifRegisterEchoContext));
496 if (ctx == NULL) {
497 return BT_NO_MEMORY;
498 }
499
500 (void)memcpy_s(&(ctx->echoCallback), sizeof(L2capEcho), echoCallback, sizeof(L2capEcho));
501 ctx->context = context;
502
503 L2capAsynchronousProcess(L2cifRegisterEcho, L2capFree, ctx);
504 return BT_SUCCESS;
505 }
506
L2cifDeregisterEcho(const void * context)507 static void L2cifDeregisterEcho(const void *context)
508 {
509 L2CAP_DeregisterEcho();
510 return;
511 }
512
L2CIF_DeregisterEcho()513 void L2CIF_DeregisterEcho()
514 {
515 L2capAsynchronousProcess(L2cifDeregisterEcho, NULL, NULL);
516 return;
517 }
518
519 typedef struct {
520 uint16_t aclHandle;
521 uint8_t *data;
522 uint16_t dataLen;
523 void (*cb)(uint16_t aclHandle, int result);
524 } L2cifEchoReqContext;
525
L2cifEchoReqContextDestroy(void * context)526 static void L2cifEchoReqContextDestroy(void *context)
527 {
528 L2cifEchoReqContext *ctx = NULL;
529
530 ctx = context;
531 if (ctx->data != NULL) {
532 L2capFree(ctx->data);
533 }
534
535 L2capFree(ctx);
536 return;
537 }
538
L2cifEchoReq(const void * context)539 static void L2cifEchoReq(const void *context)
540 {
541 L2cifEchoReqContext *ctx = NULL;
542 int result;
543
544 ctx = (L2cifEchoReqContext *)context;
545
546 result = L2CAP_EchoReq(ctx->aclHandle, ctx->data, ctx->dataLen);
547 if (ctx->cb != NULL) {
548 ctx->cb(ctx->aclHandle, result);
549 }
550
551 L2cifEchoReqContextDestroy(ctx);
552 return;
553 }
554
L2CIF_EchoReq(uint16_t aclHandle,const uint8_t * data,uint16_t dataLen,void (* cb)(uint16_t aclHandle,int result))555 void L2CIF_EchoReq(
556 uint16_t aclHandle, const uint8_t *data, uint16_t dataLen, void (*cb)(uint16_t aclHandle, int result))
557 {
558 L2cifEchoReqContext *ctx = NULL;
559
560 ctx = L2capAlloc(sizeof(L2cifEchoReqContext));
561 if (ctx == NULL) {
562 LOG_WARN("malloc failed");
563 return;
564 }
565
566 ctx->aclHandle = aclHandle;
567 ctx->data = NULL;
568 ctx->dataLen = 0;
569 ctx->cb = cb;
570
571 if (data != NULL) {
572 ctx->data = L2capAlloc(dataLen);
573 if (ctx->data == NULL) {
574 LOG_WARN("malloc failed");
575 return;
576 }
577 (void)memcpy_s(ctx->data, dataLen, data, dataLen);
578 ctx->dataLen = dataLen;
579 }
580
581 L2capAsynchronousProcess(L2cifEchoReq, L2cifEchoReqContextDestroy, ctx);
582 return;
583 }
584
585 typedef struct {
586 uint16_t aclHandle;
587 uint8_t id;
588 uint8_t *data;
589 uint16_t dataLen;
590 void (*cb)(uint16_t aclHandle, int result);
591 } L2cifEchoRspContext;
592
L2cifEchoRspContextDestroy(void * context)593 static void L2cifEchoRspContextDestroy(void *context)
594 {
595 L2cifEchoRspContext *ctx = NULL;
596
597 ctx = context;
598 if (ctx->data != NULL) {
599 L2capFree(ctx->data);
600 }
601
602 L2capFree(ctx);
603 return;
604 }
605
L2cifEchoRsp(const void * context)606 static void L2cifEchoRsp(const void *context)
607 {
608 L2cifEchoRspContext *ctx = NULL;
609 int result;
610
611 ctx = (L2cifEchoRspContext *)context;
612
613 result = L2CAP_EchoRsp(ctx->aclHandle, ctx->id, ctx->data, ctx->dataLen);
614 if (ctx->cb != NULL) {
615 ctx->cb(ctx->aclHandle, result);
616 }
617
618 L2cifEchoRspContextDestroy(ctx);
619 return;
620 }
621
L2CIF_EchoRsp(uint16_t aclHandle,uint8_t id,const uint8_t * data,uint16_t dataLen,void (* cb)(uint16_t aclHandle,int result))622 void L2CIF_EchoRsp(
623 uint16_t aclHandle, uint8_t id, const uint8_t *data, uint16_t dataLen, void (*cb)(uint16_t aclHandle, int result))
624 {
625 L2cifEchoRspContext *ctx = NULL;
626
627 ctx = L2capAlloc(sizeof(L2cifEchoRspContext));
628 if (ctx == NULL) {
629 LOG_WARN("malloc failed");
630 return;
631 }
632
633 ctx->aclHandle = aclHandle;
634 ctx->id = id;
635 ctx->data = NULL;
636 ctx->dataLen = 0;
637 ctx->cb = cb;
638
639 if (data != NULL) {
640 ctx->data = L2capAlloc(dataLen);
641 if (ctx->data == NULL) {
642 LOG_WARN("malloc failed");
643 return;
644 }
645
646 (void)memcpy_s(ctx->data, dataLen, data, dataLen);
647 ctx->dataLen = dataLen;
648 }
649
650 L2capAsynchronousProcess(L2cifEchoRsp, L2cifEchoRspContextDestroy, ctx);
651 return;
652 }
653
654 typedef struct {
655 Semaphore *sem;
656 int traceLevel;
657 } L2cifContext;
658
L2cifStartup(void * context)659 static void L2cifStartup(void *context)
660 {
661 L2cifContext *ctx = NULL;
662
663 ctx = context;
664
665 L2CAP_Initialize(ctx->traceLevel);
666
667 SemaphorePost(ctx->sem);
668 L2capFree(ctx);
669 return;
670 }
671
L2CIF_Startup()672 void L2CIF_Startup()
673 {
674 int result;
675 L2cifContext *ctx = NULL;
676 Semaphore *sem = NULL;
677
678 result = BTM_CreateProcessingQueue(PROCESSING_QUEUE_ID_LA2CAP, BTM_PROCESSING_QUEUE_SIZE_DEFAULT);
679 if (result != BT_SUCCESS) {
680 return;
681 }
682
683 sem = SemaphoreCreate(0);
684 if (sem == NULL) {
685 LOG_WARN("malloc failed");
686 return;
687 }
688 ctx = L2capAlloc(sizeof(L2cifContext));
689 if (ctx == NULL) {
690 LOG_WARN("malloc failed");
691 SemaphoreDelete(sem);
692 return;
693 }
694
695 ctx->sem = sem;
696 ctx->traceLevel = 0;
697
698 result = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_LA2CAP, L2cifStartup, ctx);
699 if (result != BT_SUCCESS) {
700 L2capFree(ctx);
701 SemaphoreDelete(sem);
702 return;
703 }
704
705 SemaphoreWait(sem);
706 SemaphoreDelete(sem);
707 return;
708 }
709
L2cifShutdown(void * context)710 static void L2cifShutdown(void *context)
711 {
712 L2cifContext *ctx = NULL;
713
714 ctx = context;
715
716 L2CAP_Finalize();
717
718 BTM_DeleteProcessingQueue(PROCESSING_QUEUE_ID_LA2CAP);
719
720 SemaphorePost(ctx->sem);
721 L2capFree(ctx);
722 return;
723 }
724
L2CIF_Shutdown()725 void L2CIF_Shutdown()
726 {
727 int result;
728 L2cifContext *ctx = NULL;
729 Semaphore *sem = NULL;
730
731 sem = SemaphoreCreate(0);
732 if (sem == NULL) {
733 LOG_WARN("malloc failed");
734 return;
735 }
736 ctx = L2capAlloc(sizeof(L2cifContext));
737 if (ctx == NULL) {
738 LOG_WARN("malloc failed");
739 SemaphoreDelete(sem);
740 return;
741 }
742 ctx->sem = sem;
743 ctx->traceLevel = 0;
744
745 result = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_LA2CAP, L2cifShutdown, ctx);
746 if (result != BT_SUCCESS) {
747 L2capFree(ctx);
748 SemaphoreDelete(sem);
749 return;
750 }
751
752 SemaphoreWait(sem);
753 SemaphoreDelete(sem);
754
755 return;
756 }
757
L2CIF_Initialize(int traceLevel)758 void L2CIF_Initialize(int traceLevel)
759 {
760 // passthrough
761 return;
762 }
763
L2CIF_Finalize()764 void L2CIF_Finalize()
765 {
766 // passthrough
767 return;
768 }
769
770 static Module g_l2cap = {
771 .name = MODULE_NAME_L2CAP,
772 .init = L2CIF_Initialize,
773 .startup = L2CIF_Startup,
774 .shutdown = L2CIF_Shutdown,
775 .cleanup = L2CIF_Finalize,
776 .dependencies = {MODULE_NAME_HCI},
777 };
778
779 MODULE_DECL(g_l2cap);