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