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);