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.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 #include "l2cap_core.h"
26 #include "l2cap_inst.h"
27 #include "l2cap_le.h"
28 
L2CAP_ConnectReq(const BtAddr * addr,uint16_t lpsm,uint16_t rpsm,uint16_t * lcid)29 int L2CAP_ConnectReq(const BtAddr *addr, uint16_t lpsm, uint16_t rpsm, uint16_t *lcid)
30 {
31     L2capConnection *conn = NULL;
32     L2capChannel *chan = NULL;
33     L2capPsm *psm = NULL;
34 
35     LOG_INFO("%{public}s:%{public}d enter, lpsm = 0x%04X, rpsm = 0x%04X", __FUNCTION__, __LINE__, lpsm, rpsm);
36 
37     if (L2capInitialized() != BT_SUCCESS) {
38         return BT_BAD_STATUS;
39     }
40 
41     if ((addr == NULL) || (lcid == NULL)) {
42         return BT_BAD_PARAM;
43     }
44 
45     psm = L2capGetPsm(lpsm);
46     if (psm == NULL) {
47         return BT_BAD_PARAM;
48     }
49 
50     conn = L2capGetConnection2(addr);
51     if (conn == NULL) {
52         conn = L2capNewConnection(addr, 0);
53     }
54 
55     chan = L2capNewChannel(conn, lpsm, rpsm);
56     *lcid = chan->lcid;
57 
58     if (conn->state == L2CAP_CONNECTION_IDLE) {
59         conn->state = L2CAP_CONNECTION_CONNECTING;
60         if (L2capConnectBdr(addr) != BT_SUCCESS) {
61             L2capDeleteConnection(conn);
62             return BT_OPERATION_FAILED;
63         }
64 
65         return BT_SUCCESS;
66     }
67 
68     if ((conn->state == L2CAP_CONNECTION_CONNECTING) || (conn->state == L2CAP_CONNECTION_DISCONNECTING)) {
69         return BT_SUCCESS;
70     }
71 
72     if (conn->info.state == L2CAP_INFO_STATE_NONE) {
73         L2capSendInformationReq(conn, L2CAP_INFORMATION_TYPE_EXTENDED_FEATURE);
74     } else if (conn->info.state == L2CAP_INFO_STATE_DONE) {
75         L2capSendConnectionReq(conn, chan);
76     }
77 
78     return BT_SUCCESS;
79 }
80 
L2CAP_ConnectRsp(uint16_t lcid,uint8_t id,uint16_t result,uint16_t status)81 int L2CAP_ConnectRsp(uint16_t lcid, uint8_t id, uint16_t result, uint16_t status)
82 {
83     L2capConnection *conn = NULL;
84     L2capChannel *chan = NULL;
85 
86     LOG_INFO("%{public}s:%{public}d enter, lcid = 0x%04X, id = %{public}d, result = %{public}d, status = %{public}d",
87         __FUNCTION__,
88         __LINE__,
89         lcid,
90         id,
91         result,
92         status);
93 
94     if (L2capInitialized() != BT_SUCCESS) {
95         return BT_BAD_STATUS;
96     }
97 
98     L2capGetChannel2(lcid, &conn, &chan);
99     if (chan == NULL) {
100         return BT_BAD_PARAM;
101     }
102 
103     if (chan->state != L2CAP_CHANNEL_CONNECT_IN_REQ) {
104         return BT_BAD_STATUS;
105     }
106 
107     L2capSendConnectionRsp(conn, chan, id, result, status);
108 
109     if ((result != L2CAP_CONNECTION_SUCCESSFUL) && (result != L2CAP_CONNECTION_PENDING)) {
110         L2capDeleteChannel(conn, chan, 0);
111     }
112 
113     return BT_SUCCESS;
114 }
115 
L2CAP_ConfigReq(uint16_t lcid,const L2capConfigInfo * cfg)116 int L2CAP_ConfigReq(uint16_t lcid, const L2capConfigInfo *cfg)
117 {
118     L2capConnection *conn = NULL;
119     L2capChannel *chan = NULL;
120 
121     LOG_INFO("%{public}s:%{public}d enter, lcid = 0x%04X", __FUNCTION__, __LINE__, lcid);
122 
123     if (L2capInitialized() != BT_SUCCESS) {
124         return BT_BAD_STATUS;
125     }
126 
127     if (cfg == NULL) {
128         return BT_BAD_PARAM;
129     }
130 
131     if ((cfg->mtu < L2CAP_MIN_MTU) || (cfg->flushTimeout == 0)) {
132         return BT_BAD_PARAM;
133     }
134 
135     L2capGetChannel2(lcid, &conn, &chan);
136     if (chan == NULL) {
137         return BT_BAD_PARAM;
138     }
139 
140     if ((chan->state != L2CAP_CHANNEL_CONFIGING) && (chan->state != L2CAP_CHANNEL_CONNECTED)) {
141         return BT_BAD_STATUS;
142     }
143 
144     chan->lcfg.mtu = cfg->mtu;
145     chan->lcfg.flushTimeout = cfg->flushTimeout;
146     chan->lcfg.fcs = cfg->fcs;
147     chan->lcfg.rfc.mode = cfg->rfc.mode;
148 
149     if (chan->lcfg.rfc.mode == L2CAP_ENHANCED_RETRANSMISSION_MODE) {
150         if (cfg->rfc.rxWindowSize != 0) {
151             chan->lcfg.rfc.rxWindowSize = cfg->rfc.rxWindowSize;
152         }
153 
154         if (cfg->rfc.maxTransmit != 0) {
155             chan->lcfg.rfc.maxTransmit = cfg->rfc.maxTransmit;
156         }
157 
158         if (chan->lcfg.rfc.mps > cfg->mtu) {
159             chan->lcfg.rfc.mps = cfg->mtu;
160         }
161     } else if (chan->lcfg.rfc.mode == L2CAP_STREAM_MODE) {
162         chan->lcfg.rfc.maxTransmit = 0;
163         chan->lcfg.rfc.retransmissionTimeout = 0;
164         chan->lcfg.rfc.monitorTimeout = 0;
165         chan->lcfg.rfc.txWindowSize = 0;
166         chan->lcfg.rfc.rxWindowSize = 0;
167 
168         if (chan->lcfg.rfc.mps > cfg->mtu) {
169             chan->lcfg.rfc.mps = cfg->mtu;
170         }
171     }
172 
173     if (cfg->rfc.mode == L2CAP_BASIC_MODE) {
174         chan->lcfg.fcs = 0x01;
175     }
176 
177     L2capSendConfigurationReq(conn, chan);
178     return BT_SUCCESS;
179 }
180 
L2CAP_ConfigRsp(uint16_t lcid,uint8_t id,const L2capConfigInfo * cfg,uint16_t result)181 int L2CAP_ConfigRsp(uint16_t lcid, uint8_t id, const L2capConfigInfo *cfg, uint16_t result)
182 {
183     L2capConnection *conn = NULL;
184     L2capChannel *chan = NULL;
185 
186     LOG_INFO("%{public}s:%{public}d enter, lcid = 0x%04X, id = %{public}d, result = %{public}d", __FUNCTION__, __LINE__, lcid, id, result);
187 
188     if (L2capInitialized() != BT_SUCCESS) {
189         return BT_BAD_STATUS;
190     }
191 
192     if (cfg == NULL) {
193         return BT_BAD_PARAM;
194     }
195 
196     if (cfg->mtu < L2CAP_MIN_MTU) {
197         return BT_BAD_PARAM;
198     }
199 
200     if (cfg->flushTimeout == 0) {
201         return BT_BAD_PARAM;
202     }
203 
204     L2capGetChannel2(lcid, &conn, &chan);
205     if (chan == NULL) {
206         return BT_BAD_PARAM;
207     }
208 
209     if ((chan->state != L2CAP_CHANNEL_CONFIGING) && (chan->state != L2CAP_CHANNEL_CONNECTED)) {
210         return BT_BAD_STATUS;
211     }
212 
213     if (cfg->rfc.mode == L2CAP_ENHANCED_RETRANSMISSION_MODE) {
214         chan->lcfg.rfc.txWindowSize = chan->rcfg.rfc.rxWindowSize;
215         chan->lcfg.rfc.retransmissionTimeout = L2CAP_DEFAULT_RETRANSMISSION_TIMEOUT;
216         chan->lcfg.rfc.monitorTimeout = L2CAP_DEFAULT_MONITOR_TIMEOUT;
217 
218         if (chan->rcfg.rfc.mps > (L2capGetTxBufferSize() - L2CAP_SIZE_10)) {
219             chan->rcfg.rfc.mps = (L2capGetTxBufferSize() - L2CAP_SIZE_10);
220         }
221     } else if (chan->lcfg.rfc.mode == L2CAP_STREAM_MODE) {
222         chan->lcfg.rfc.maxTransmit = 0;
223         chan->lcfg.rfc.retransmissionTimeout = 0;
224         chan->lcfg.rfc.monitorTimeout = 0;
225         chan->lcfg.rfc.txWindowSize = 0;
226         chan->lcfg.rfc.rxWindowSize = 0;
227 
228         if (chan->rcfg.rfc.mps > (L2capGetTxBufferSize() - L2CAP_SIZE_10)) {
229             chan->rcfg.rfc.mps = (L2capGetTxBufferSize() - L2CAP_SIZE_10);
230         }
231     }
232 
233     L2capSendConfigurationRsp(conn, chan, id, result, cfg);
234     return BT_SUCCESS;
235 }
236 
L2CAP_DisconnectionReq(uint16_t lcid)237 int L2CAP_DisconnectionReq(uint16_t lcid)
238 {
239     L2capConnection *conn = NULL;
240     L2capChannel *chan = NULL;
241 
242     LOG_INFO("%{public}s:%{public}d enter, lcid = 0x%04X", __FUNCTION__, __LINE__, lcid);
243 
244     if (L2capInitialized() != BT_SUCCESS) {
245         return BT_BAD_STATUS;
246     }
247 
248     L2capGetChannel2(lcid, &conn, &chan);
249     if (chan == NULL) {
250         return BT_BAD_PARAM;
251     }
252 
253     if ((chan->state != L2CAP_CHANNEL_CONNECTED) && (chan->state != L2CAP_CHANNEL_CONFIGING)) {
254         return BT_BAD_STATUS;
255     }
256 
257     L2capSendDisconnectionReq(conn, chan);
258     return BT_SUCCESS;
259 }
260 
L2CAP_DisconnectionRsp(uint16_t lcid,uint8_t id)261 int L2CAP_DisconnectionRsp(uint16_t lcid, uint8_t id)
262 {
263     L2capConnection *conn = NULL;
264     L2capChannel *chan = NULL;
265 
266     LOG_INFO("%{public}s:%{public}d enter, lcid = 0x%04X, id = %{public}d", __FUNCTION__, __LINE__, lcid, id);
267 
268     if (L2capInitialized() != BT_SUCCESS) {
269         return BT_BAD_STATUS;
270     }
271 
272     L2capGetChannel2(lcid, &conn, &chan);
273     if (chan == NULL) {
274         return BT_BAD_PARAM;
275     }
276 
277     if (chan->state != L2CAP_CHANNEL_DISCONNECT_IN_REQ) {
278         return BT_BAD_STATUS;
279     }
280 
281     L2capSendDisconnectionRsp(conn, chan, id);
282     L2capDeleteChannel(conn, chan, 0);
283     return BT_SUCCESS;
284 }
285 
L2CAP_LocalBusy(uint16_t lcid,uint8_t isBusy)286 int L2CAP_LocalBusy(uint16_t lcid, uint8_t isBusy)
287 {
288     L2capConnection *conn = NULL;
289     L2capChannel *chan = NULL;
290 
291     LOG_INFO("%{public}s:%{public}d enter, lcid = 0x%04X, isBusy = %{public}d", __FUNCTION__, __LINE__, lcid, isBusy);
292 
293     if (L2capInitialized() != BT_SUCCESS) {
294         return BT_BAD_STATUS;
295     }
296 
297     L2capGetChannel2(lcid, &conn, &chan);
298     if (chan == NULL) {
299         return BT_BAD_PARAM;
300     }
301 
302     if (chan->lcfg.rfc.mode != L2CAP_ENHANCED_RETRANSMISSION_MODE) {
303         return BT_BAD_PARAM;
304     }
305 
306     if (chan->state != L2CAP_CHANNEL_CONNECTED) {
307         return BT_BAD_STATUS;
308     }
309 
310     if (isBusy > 0) {
311         isBusy = L2CAP_BUSY_LOCAL_BUSY;
312     }
313 
314     if ((chan->erfc.busyState & L2CAP_BUSY_LOCAL_BUSY) == isBusy) {
315         return BT_BAD_STATUS;
316     }
317 
318     if (isBusy) {
319         chan->erfc.busyState |= L2CAP_BUSY_LOCAL_BUSY;
320         L2capSendSFrame(conn, chan, L2CAP_ERFC_PBIT_OFF, L2CAP_ERFC_FBIT_OFF, L2CAP_ERFC_RNR);
321     } else {
322         chan->erfc.busyState &= (~L2CAP_BUSY_LOCAL_BUSY);
323         chan->erfc.busyState |= L2CAP_BUSY_WAIT_F;
324         L2capSendSFrame(conn, chan, L2CAP_ERFC_PBIT_ON, L2CAP_ERFC_FBIT_OFF, L2CAP_ERFC_RR);
325 
326         chan->erfc.retryCount = 1;
327         L2capErfcStartMonitorTimer(chan);
328     }
329 
330     return BT_SUCCESS;
331 }
332 
L2CAP_SendData(uint16_t lcid,Packet * pkt)333 int L2CAP_SendData(uint16_t lcid, Packet *pkt)
334 {
335     L2capConnection *conn = NULL;
336     L2capChannel *chan = NULL;
337     uint16_t length;
338 
339     if (pkt == NULL) {
340         return BT_BAD_PARAM;
341     }
342 
343     LOG_INFO("%{public}s:%{public}d enter, lcid = 0x%04X, pktLength = %{public}d", __FUNCTION__, __LINE__, lcid, PacketSize(pkt));
344 
345     if (L2capInitialized() != BT_SUCCESS) {
346         return BT_BAD_STATUS;
347     }
348 
349     L2capGetChannel2(lcid, &conn, &chan);
350     if (chan == NULL) {
351         return BT_BAD_PARAM;
352     }
353 
354     length = PacketSize(pkt);
355     if (length > chan->rcfg.mtu) {
356         return BT_BAD_PARAM;
357     }
358 
359     if (chan->state != L2CAP_CHANNEL_CONNECTED) {
360         return BT_BAD_STATUS;
361     }
362 
363     if (chan->lcfg.rfc.mode == L2CAP_BASIC_MODE) {
364         Packet *tpkt = NULL;
365         uint8_t *header = NULL;
366 
367         tpkt = PacketInheritMalloc(pkt, L2CAP_HEADER_LENGTH, 0);
368         header = BufferPtr(PacketHead(tpkt));
369 
370         L2capCpuToLe16(header + 0, length);
371         L2capCpuToLe16(header + L2CAP_OFFSET_2, chan->rcid);
372 
373         L2capSendPacket(conn->aclHandle, chan->lcfg.flushTimeout, tpkt);
374     } else {
375         L2capSendIFrame(conn, chan, pkt);
376     }
377 
378     return BT_SUCCESS;
379 }
380 
L2CAP_RegisterEcho(const L2capEcho * echoCallback,void * context)381 int L2CAP_RegisterEcho(const L2capEcho *echoCallback, void *context)
382 {
383     L2capInstance *inst = NULL;
384 
385     LOG_INFO("%{public}s:%{public}d enter", __FUNCTION__, __LINE__);
386 
387     if (L2capInitialized() != BT_SUCCESS) {
388         return BT_BAD_STATUS;
389     }
390 
391     if (echoCallback == NULL) {
392         return BT_BAD_PARAM;
393     }
394 
395     inst = L2capGetInstance();
396     inst->echo.ctx = context;
397     (void)memcpy_s(&(inst->echo.cb), sizeof(L2capEcho), echoCallback, sizeof(L2capEcho));
398 
399     return BT_SUCCESS;
400 }
401 
L2CAP_DeregisterEcho()402 int L2CAP_DeregisterEcho()
403 {
404     L2capInstance *inst = NULL;
405 
406     LOG_INFO("%{public}s:%{public}d enter", __FUNCTION__, __LINE__);
407 
408     if (L2capInitialized() != BT_SUCCESS) {
409         return BT_BAD_STATUS;
410     }
411 
412     inst = L2capGetInstance();
413     (void)memset_s(&(inst->echo), sizeof(L2capEcho), 0, sizeof(L2capEcho));
414     return BT_SUCCESS;
415 }
416 
L2CAP_EchoReq(uint16_t aclHandle,const uint8_t * data,uint16_t dataLen)417 int L2CAP_EchoReq(uint16_t aclHandle, const uint8_t *data, uint16_t dataLen)
418 {
419     L2capConnection *conn = NULL;
420 
421     LOG_INFO("%{public}s:%{public}d enter, aclHandle = %{public}d, dataLen = %{public}d", __FUNCTION__, __LINE__, aclHandle, dataLen);
422 
423     if (L2capInitialized() != BT_SUCCESS) {
424         return BT_BAD_STATUS;
425     }
426 
427     if ((data == NULL) && (dataLen > 0)) {
428         return BT_BAD_PARAM;
429     }
430 
431     conn = L2capGetConnection(aclHandle);
432     if (conn == NULL) {
433         return BT_BAD_PARAM;
434     }
435 
436     L2capSendEchoReq(conn, data, dataLen);
437     return BT_SUCCESS;
438 }
439 
L2CAP_EchoRsp(uint16_t aclHandle,uint8_t id,const uint8_t * data,uint16_t dataLen)440 int L2CAP_EchoRsp(uint16_t aclHandle, uint8_t id, const uint8_t *data, uint16_t dataLen)
441 {
442     L2capConnection *conn = NULL;
443 
444     LOG_INFO("%{public}s:%{public}d enter, aclHandle = %{public}d, id = %{public}d, dataLen = %{public}d", __FUNCTION__, __LINE__, aclHandle, id, dataLen);
445 
446     if (L2capInitialized() != BT_SUCCESS) {
447         return BT_BAD_STATUS;
448     }
449 
450     if ((dataLen > 0) && (data == NULL)) {
451         return BT_BAD_PARAM;
452     }
453 
454     conn = L2capGetConnection(aclHandle);
455     if (conn == NULL) {
456         return BT_BAD_PARAM;
457     }
458 
459     L2capSendEchoRsp(conn, id, data, dataLen);
460     return BT_SUCCESS;
461 }
462 
L2CAP_RegisterService(uint16_t lpsm,const L2capService * svc,void * context)463 int L2CAP_RegisterService(uint16_t lpsm, const L2capService *svc, void *context)
464 {
465     L2capInstance *inst = NULL;
466     L2capPsm *psm = NULL;
467 
468     LOG_INFO("%{public}s:%{public}d enter, psm = 0x%04X", __FUNCTION__, __LINE__, lpsm);
469 
470     if (L2capInitialized() != BT_SUCCESS) {
471         return BT_BAD_STATUS;
472     }
473 
474     if (svc == NULL) {
475         return BT_BAD_PARAM;
476     }
477 
478     // check whether the psm is valid
479     if (!(lpsm & 0x0001) || (lpsm & 0x0100)) {
480         return BT_BAD_PARAM;
481     }
482 
483     psm = L2capGetPsm(lpsm);
484     if (psm != NULL) {
485         return BT_BAD_STATUS;
486     }
487 
488     psm = L2capAlloc(sizeof(L2capPsm));
489     if (psm == NULL) {
490         return BT_NO_MEMORY;
491     }
492 
493     inst = L2capGetInstance();
494 
495     psm->lpsm = lpsm;
496     psm->ctx = context;
497     (void)memcpy_s(&(psm->service), sizeof(L2capService), svc, sizeof(L2capService));
498     ListAddFirst(inst->psmList, psm);
499 
500     return BT_SUCCESS;
501 }
502 
L2CAP_DeregisterService(uint16_t lpsm)503 int L2CAP_DeregisterService(uint16_t lpsm)
504 {
505     L2capInstance *inst = NULL;
506     L2capPsm *psm = NULL;
507     L2capConnection *conn = NULL;
508     L2capChannel *chan = NULL;
509     ListNode *node = NULL;
510     ListNode *nodeChan = NULL;
511 
512     LOG_INFO("%{public}s:%{public}d enter, psm = 0x%04X", __FUNCTION__, __LINE__, lpsm);
513 
514     if (L2capInitialized() != BT_SUCCESS) {
515         return BT_BAD_STATUS;
516     }
517 
518     psm = L2capGetPsm(lpsm);
519     if (psm == NULL) {
520         return BT_BAD_PARAM;
521     }
522 
523     inst = L2capGetInstance();
524     node = ListGetFirstNode(inst->connList);
525     while (node != NULL) {
526         conn = ListGetNodeData(node);
527         nodeChan = ListGetFirstNode(conn->chanList);
528         while (nodeChan != NULL) {
529             chan = ListGetNodeData(nodeChan);
530             // if any channel used the psm, return error
531             if (chan->lpsm == lpsm) {
532                 return BT_BAD_STATUS;
533             }
534 
535             nodeChan = ListGetNextNode(nodeChan);
536         }
537 
538         node = ListGetNextNode(node);
539     }
540 
541     ListRemoveNode(inst->psmList, psm);
542     L2capFree(psm);
543     return BT_SUCCESS;
544 }
545 
L2CAP_Initialize(int traceLevel)546 void L2CAP_Initialize(int traceLevel)
547 {
548     L2capInstance *inst = NULL;
549     L2capBdrCallback cmnCallback = {0};
550 
551     LOG_INFO("%{public}s:%{public}d enter", __FUNCTION__, __LINE__);
552 
553     cmnCallback.aclConnected = L2capConnectComplete;
554     cmnCallback.aclDisconnected = L2capDisconnectComplete;
555     cmnCallback.recvL2capPacket = L2capReceivePacket;
556     L2capRegisterBdr(&cmnCallback);
557 
558     inst = L2capGetInstance();
559     inst->psmList = ListCreate(NULL);
560     inst->connList = ListCreate(NULL);
561     inst->nextLcid = L2CAP_MIN_CID;
562     (void)memset_s(&(inst->echo), sizeof(L2capEcho), 0, sizeof(L2capEcho));
563 
564     L2CAP_LeInitialize(traceLevel);
565 
566     L2capCommonStartup();
567     return;
568 }
569 
L2CAP_Finalize()570 void L2CAP_Finalize()
571 {
572     L2capInstance *inst = NULL;
573     ListNode *node = NULL;
574     L2capConnection *conn = NULL;
575     L2capPsm *psm = NULL;
576 
577     LOG_INFO("%{public}s:%{public}d enter", __FUNCTION__, __LINE__);
578 
579     L2capCommonShutdown();
580 
581     inst = L2capGetInstance();
582     node = ListGetFirstNode(inst->connList);
583     while (node != NULL) {
584         conn = ListGetNodeData(node);
585         L2capDeleteConnection(conn);
586 
587         node = ListGetFirstNode(inst->connList);
588     }
589 
590     ListDelete(inst->connList);
591     inst->connList = NULL;
592 
593     node = ListGetFirstNode(inst->psmList);
594     while (node != NULL) {
595         psm = ListGetNodeData(node);
596         ListRemoveNode(inst->psmList, psm);
597         L2capFree(psm);
598 
599         node = ListGetFirstNode(inst->psmList);
600     }
601 
602     ListDelete(inst->psmList);
603     inst->psmList = NULL;
604 
605     (void)memset_s(&(inst->echo), sizeof(L2capEcho), 0, sizeof(L2capEcho));
606 
607     L2CAP_LeFinalize();
608     return;
609 }
610