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 "rfcomm_defs.h"
17
18 static void RfcommRecvConnectReqCallback(
19 uint16_t lcid, uint8_t id, const L2capConnectionInfo *info, uint16_t lpsm, void *context);
20 static void RfcommRecvConnectRspCallback(
21 uint16_t lcid, const L2capConnectionInfo *info, uint16_t result, uint16_t status, void *context);
22 static void RfcommRecvConfigReqCallback(uint16_t lcid, uint8_t id, const L2capConfigInfo *cfg, void *context);
23 static void RfcommRecvConfigRspCallback(uint16_t lcid, const L2capConfigInfo *cfg, uint16_t result, void *context);
24 static void RfcommRecvDisconnectReqCallback(uint16_t lcid, uint8_t id, void *context);
25 static void RfcommRecvDisconnectRspCallback(uint16_t lcid, void *context);
26 static void RfcommDisconnectAbnormalCallback(uint16_t lcid, uint8_t reason, void *context);
27 static void RfcommRecvDataCallback(uint16_t lcid, Packet *pkt, void *context);
28
29 /**
30 * @brief Register callback function to L2CAP when RFCOMM initialize.
31 *
32 */
RfcommRegisterL2cap()33 void RfcommRegisterL2cap()
34 {
35 LOG_INFO("%{public}s", __func__);
36
37 static const L2capService svc = {
38 RfcommRecvConnectReqCallback,
39 RfcommRecvConnectRspCallback,
40 RfcommRecvConfigReqCallback,
41 RfcommRecvConfigRspCallback,
42 RfcommRecvDisconnectReqCallback,
43 RfcommRecvDisconnectRspCallback,
44 RfcommDisconnectAbnormalCallback,
45 RfcommRecvDataCallback,
46 NULL
47 };
48 L2CIF_RegisterService(BT_PSM_RFCOMM, &svc, NULL, NULL);
49 }
50
51 /**
52 * @brief Deregister L2CAP when RFCOMM finalize.
53 *
54 */
RfcommDeregisterL2cap()55 void RfcommDeregisterL2cap()
56 {
57 LOG_INFO("%{public}s", __func__);
58
59 L2CIF_DeregisterService(BT_PSM_RFCOMM, NULL);
60 }
61
62 typedef struct {
63 uint16_t lcid;
64 uint8_t id;
65 L2capConnectionInfo info;
66 uint16_t lpsm;
67 void *context;
68 } RfcommRecvConnectReqInfo;
69
RfcommRecvConnectReqTsk(void * context)70 static void RfcommRecvConnectReqTsk(void *context)
71 {
72 LOG_INFO("%{public}s", __func__);
73
74 RfcommRecvConnectReqInfo *ctx = context;
75
76 if (ctx == NULL) {
77 LOG_ERROR("%{public}s context is NULL.", __func__);
78 return;
79 }
80
81 RfcommRecvConnectReqCback(ctx->lcid, ctx->id, &ctx->info, ctx->lpsm);
82 free(ctx);
83 }
84
RfcommRecvConnectReqCallback(uint16_t lcid,uint8_t id,const L2capConnectionInfo * info,uint16_t lpsm,void * context)85 void RfcommRecvConnectReqCallback(
86 uint16_t lcid, uint8_t id, const L2capConnectionInfo *info, uint16_t lpsm, void *context)
87 {
88 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
89
90 RfcommRecvConnectReqInfo *ctx = malloc(sizeof(RfcommRecvConnectReqInfo));
91 if (ctx == NULL) {
92 return;
93 }
94
95 (void)memset_s(ctx, sizeof(RfcommRecvConnectReqInfo), 0x00, sizeof(RfcommRecvConnectReqInfo));
96 ctx->lcid = lcid;
97 ctx->id = id;
98 ctx->lpsm = lpsm;
99 ctx->context = context;
100 (void)memcpy_s(&ctx->info, sizeof(L2capConnectionInfo), info, sizeof(L2capConnectionInfo));
101
102 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRecvConnectReqTsk, ctx);
103 if (ret != BT_SUCCESS) {
104 free(ctx);
105 }
106 }
107
108 typedef struct {
109 uint16_t lcid;
110 L2capConnectionInfo info;
111 uint16_t result;
112 uint16_t status;
113 void *context;
114 } RfcommRecvConnectRspInfo;
115
RfcommRecvConnectRspTsk(void * context)116 static void RfcommRecvConnectRspTsk(void *context)
117 {
118 LOG_INFO("%{public}s", __func__);
119
120 RfcommRecvConnectRspInfo *ctx = context;
121
122 if (ctx == NULL) {
123 LOG_ERROR("%{public}s context is NULL.", __func__);
124 return;
125 }
126
127 RfcommRecvConnectRspCback(ctx->lcid, &ctx->info, ctx->result, ctx->status);
128 free(ctx);
129 }
130
RfcommRecvConnectRspCallback(uint16_t lcid,const L2capConnectionInfo * info,uint16_t result,uint16_t status,void * context)131 void RfcommRecvConnectRspCallback(
132 uint16_t lcid, const L2capConnectionInfo *info, uint16_t result, uint16_t status, void *context)
133 {
134 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
135
136 RfcommRecvConnectRspInfo *ctx = malloc(sizeof(RfcommRecvConnectRspInfo));
137 if (ctx == NULL) {
138 return;
139 }
140
141 (void)memset_s(ctx, sizeof(RfcommRecvConnectRspInfo), 0x00, sizeof(RfcommRecvConnectRspInfo));
142 ctx->lcid = lcid;
143 ctx->result = result;
144 ctx->status = status;
145 ctx->context = context;
146 (void)memcpy_s(&ctx->info, sizeof(L2capConnectionInfo), info, sizeof(L2capConnectionInfo));
147
148 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRecvConnectRspTsk, ctx);
149 if (ret != BT_SUCCESS) {
150 free(ctx);
151 }
152 }
153
154 typedef struct {
155 uint16_t lcid;
156 uint8_t id;
157 L2capConfigInfo cfg;
158 void *context;
159 } RfcommRecvConfigReqInfo;
160
RfcommRecvConfigReqTsk(void * context)161 static void RfcommRecvConfigReqTsk(void *context)
162 {
163 LOG_INFO("%{public}s", __func__);
164
165 RfcommRecvConfigReqInfo *ctx = context;
166
167 if (ctx == NULL) {
168 LOG_ERROR("%{public}s context is NULL.", __func__);
169 return;
170 }
171
172 RfcommRecvConfigReqCback(ctx->lcid, ctx->id, &ctx->cfg);
173 free(ctx);
174 }
175
RfcommRecvConfigReqCallback(uint16_t lcid,uint8_t id,const L2capConfigInfo * cfg,void * context)176 void RfcommRecvConfigReqCallback(uint16_t lcid, uint8_t id, const L2capConfigInfo *cfg, void *context)
177 {
178 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
179
180 RfcommRecvConfigReqInfo *ctx = malloc(sizeof(RfcommRecvConfigReqInfo));
181 if (ctx == NULL) {
182 return;
183 }
184
185 (void)memset_s(ctx, sizeof(RfcommRecvConfigReqInfo), 0x00, sizeof(RfcommRecvConfigReqInfo));
186 ctx->lcid = lcid;
187 ctx->id = id;
188 ctx->context = context;
189 (void)memcpy_s(&ctx->cfg, sizeof(L2capConfigInfo), cfg, sizeof(L2capConfigInfo));
190
191 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRecvConfigReqTsk, ctx);
192 if (ret != BT_SUCCESS) {
193 free(ctx);
194 }
195 }
196
197 typedef struct {
198 uint16_t lcid;
199 L2capConfigInfo cfg;
200 uint16_t result;
201 void *context;
202 } RfcommRecvConfigRspInfo;
203
RfcommRecvConfigRspTsk(void * context)204 static void RfcommRecvConfigRspTsk(void *context)
205 {
206 LOG_INFO("%{public}s", __func__);
207
208 RfcommRecvConfigRspInfo *ctx = context;
209
210 if (ctx == NULL) {
211 LOG_ERROR("%{public}s context is NULL.", __func__);
212 return;
213 }
214
215 RfcommRecvConfigRspCback(ctx->lcid, &ctx->cfg, ctx->result);
216 free(ctx);
217 }
218
RfcommRecvConfigRspCallback(uint16_t lcid,const L2capConfigInfo * cfg,uint16_t result,void * context)219 void RfcommRecvConfigRspCallback(uint16_t lcid, const L2capConfigInfo *cfg, uint16_t result, void *context)
220 {
221 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
222
223 RfcommRecvConfigRspInfo *ctx = malloc(sizeof(RfcommRecvConfigRspInfo));
224 if (ctx == NULL) {
225 return;
226 }
227
228 (void)memset_s(ctx, sizeof(RfcommRecvConfigRspInfo), 0x00, sizeof(RfcommRecvConfigRspInfo));
229 ctx->lcid = lcid;
230 ctx->result = result;
231 ctx->context = context;
232 (void)memcpy_s(&ctx->cfg, sizeof(L2capConfigInfo), cfg, sizeof(L2capConfigInfo));
233
234 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRecvConfigRspTsk, ctx);
235 if (ret != BT_SUCCESS) {
236 free(ctx);
237 }
238 }
239
240 typedef struct {
241 uint16_t lcid;
242 uint8_t id;
243 void *context;
244 } RfcommRecvDisconnectReqInfo;
245
RfcommRecvDisconnectReqTsk(void * context)246 static void RfcommRecvDisconnectReqTsk(void *context)
247 {
248 LOG_INFO("%{public}s", __func__);
249
250 RfcommRecvDisconnectReqInfo *ctx = context;
251
252 if (ctx == NULL) {
253 LOG_ERROR("%{public}s context is NULL.", __func__);
254 return;
255 }
256
257 RfcommRecvDisconnectReqCback(ctx->lcid, ctx->id);
258 free(ctx);
259 }
260
RfcommRecvDisconnectReqCallback(uint16_t lcid,uint8_t id,void * context)261 void RfcommRecvDisconnectReqCallback(uint16_t lcid, uint8_t id, void *context)
262 {
263 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
264
265 RfcommRecvDisconnectReqInfo *ctx = malloc(sizeof(RfcommRecvDisconnectReqInfo));
266 if (ctx == NULL) {
267 return;
268 }
269
270 (void)memset_s(ctx, sizeof(RfcommRecvDisconnectReqInfo), 0x00, sizeof(RfcommRecvDisconnectReqInfo));
271 ctx->lcid = lcid;
272 ctx->id = id;
273 ctx->context = context;
274
275 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRecvDisconnectReqTsk, ctx);
276 if (ret != BT_SUCCESS) {
277 free(ctx);
278 }
279 }
280
281 /**
282 * @brief L2CAP calls this function to notify RFCOMM disconnect response from peer.
283 * After receiving the response, RFCOMM calls the state machine.
284 *
285 * @param lcid L2CAP channel id.
286 * @param context Context registered by RFCOMM to L2CAP.
287 */
RfcommRecvDisconnectRspCallback(uint16_t lcid,void * context)288 void RfcommRecvDisconnectRspCallback(uint16_t lcid, void *context)
289 {
290 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
291 }
292
293 typedef struct {
294 uint16_t lcid;
295 uint8_t reason;
296 void *context;
297 } RfcommDisconnectAbnormalInfo;
298
RfcommDisconnectAbnormalTsk(void * context)299 static void RfcommDisconnectAbnormalTsk(void *context)
300 {
301 LOG_INFO("%{public}s", __func__);
302
303 RfcommDisconnectAbnormalInfo *ctx = context;
304
305 if (ctx == NULL) {
306 LOG_ERROR("%{public}s context is NULL.", __func__);
307 return;
308 }
309
310 RfcommDisconnectAbnormalCback(ctx->lcid, ctx->reason);
311 free(ctx);
312 }
313
RfcommDisconnectAbnormalCallback(uint16_t lcid,uint8_t reason,void * context)314 void RfcommDisconnectAbnormalCallback(uint16_t lcid, uint8_t reason, void *context)
315 {
316 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
317
318 RfcommDisconnectAbnormalInfo *ctx = malloc(sizeof(RfcommDisconnectAbnormalInfo));
319 if (ctx == NULL) {
320 return;
321 }
322
323 (void)memset_s(ctx, sizeof(RfcommDisconnectAbnormalInfo), 0x00, sizeof(RfcommDisconnectAbnormalInfo));
324 ctx->lcid = lcid;
325 ctx->reason = reason;
326 ctx->context = context;
327
328 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommDisconnectAbnormalTsk, ctx);
329 if (ret != BT_SUCCESS) {
330 free(ctx);
331 }
332 }
333
334 typedef struct {
335 uint16_t lcid;
336 Packet *pkt;
337 void *context;
338 } RfcommRecvDataInfo;
339
RfcommRecvDataTsk(void * context)340 static void RfcommRecvDataTsk(void *context)
341 {
342 LOG_INFO("%{public}s", __func__);
343
344 RfcommRecvDataInfo *ctx = context;
345
346 if (ctx == NULL) {
347 LOG_ERROR("%{public}s context is NULL.", __func__);
348 return;
349 }
350
351 RfcommRecvDataCback(ctx->lcid, ctx->pkt);
352 PacketFree(ctx->pkt);
353 free(ctx);
354 }
355
RfcommRecvDataCallback(uint16_t lcid,Packet * pkt,void * context)356 void RfcommRecvDataCallback(uint16_t lcid, Packet *pkt, void *context)
357 {
358 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
359
360 RfcommRecvDataInfo *ctx = malloc(sizeof(RfcommRecvDataInfo));
361 if (ctx == NULL) {
362 return;
363 }
364
365 (void)memset_s(ctx, sizeof(RfcommRecvDataInfo), 0x00, sizeof(RfcommRecvDataInfo));
366 ctx->lcid = lcid;
367 ctx->pkt = PacketRefMalloc(pkt);
368 ctx->context = context;
369
370 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRecvDataTsk, ctx);
371 if (ret != BT_SUCCESS) {
372 PacketFree(ctx->pkt);
373 free(ctx);
374 }
375 }
376
377 typedef struct {
378 BtAddr addr;
379 uint16_t lcid;
380 int result;
381 void *context;
382 } RfcommSendConnectReqInfo;
383
RfcommSendConnectReqCbackTsk(void * context)384 static void RfcommSendConnectReqCbackTsk(void *context)
385 {
386 LOG_INFO("%{public}s", __func__);
387
388 RfcommSendConnectReqInfo *ctx = context;
389
390 if (ctx == NULL) {
391 LOG_ERROR("%{public}s context is NULL.", __func__);
392 return;
393 }
394
395 RfcommSendConnectReqCback(&ctx->addr, ctx->lcid, ctx->result);
396 free(ctx);
397 }
398
RfcommSendConnectReqCallback(const BtAddr * addr,uint16_t lcid,int result,void * context)399 static void RfcommSendConnectReqCallback(const BtAddr *addr, uint16_t lcid, int result, void *context)
400 {
401 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
402
403 RfcommSendConnectReqInfo *ctx = malloc(sizeof(RfcommSendConnectReqInfo));
404 if (ctx == NULL) {
405 return;
406 }
407
408 (void)memset_s(ctx, sizeof(RfcommSendConnectReqInfo), 0x00, sizeof(RfcommSendConnectReqInfo));
409 ctx->lcid = lcid;
410 ctx->result = result;
411 (void)memcpy_s(&ctx->addr, sizeof(BtAddr), addr, sizeof(BtAddr));
412 ctx->context = context;
413
414 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommSendConnectReqCbackTsk, ctx);
415 if (ret != BT_SUCCESS) {
416 free(ctx);
417 }
418 }
419
420 /**
421 * @brief Call L2CAP_ConnectReq to request connection from L2CAP.
422 *
423 * @param addr The peer's BT address.
424 * @param lcid The L2CAP's channel id.
425 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
426 */
RfcommSendConnectReq(const BtAddr * addr)427 int RfcommSendConnectReq(const BtAddr *addr)
428 {
429 LOG_INFO("%{public}s", __func__);
430
431 int ret = L2CIF_ConnectReq(addr, BT_PSM_RFCOMM, BT_PSM_RFCOMM, NULL, RfcommSendConnectReqCallback);
432 if (ret != RFCOMM_SUCCESS) {
433 LOG_ERROR("%{public}s L2CIF_ConnectReq return value is error.", __func__);
434 }
435
436 return ret;
437 }
438
439 /**
440 * @brief Call L2CAP_ConnectRsp to send connection response to peer.
441 *
442 * @param lcid The L2CAP's channel id.
443 * @param id L2CAP's id information.
444 * @param result The result of the response.
445 * @param status The status information.
446 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
447 */
RfcommSendConnectRsp(uint16_t lcid,uint8_t id,uint16_t result,uint16_t status)448 int RfcommSendConnectRsp(uint16_t lcid, uint8_t id, uint16_t result, uint16_t status)
449 {
450 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
451
452 L2CIF_ConnectRsp(lcid, id, result, status, NULL);
453
454 return RFCOMM_SUCCESS;
455 }
456
457 /**
458 * @brief Call L2CAP_ConfigReq to send config request to peer.
459 *
460 * @param lcid The L2CAP's channel id.
461 * @param cfg Config information.
462 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
463 */
RfcommSendConfigReq(uint16_t lcid,const L2capConfigInfo * cfg)464 int RfcommSendConfigReq(uint16_t lcid, const L2capConfigInfo *cfg)
465 {
466 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
467
468 int ret = L2CIF_ConfigReq(lcid, cfg, NULL);
469 if (ret != RFCOMM_SUCCESS) {
470 LOG_ERROR("%{public}s L2CIF_ConfigReq return value is error.", __func__);
471 }
472
473 return ret;
474 }
475
476 /**
477 * @brief Call L2CAP_ConfigRsp to send config response to peer.
478 *
479 * @param lcid The L2CAP's channel id.
480 * @param id L2CAP's id information.
481 * @param cfg Config information.
482 * @param result The result of the response.
483 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
484 */
RfcommSendConfigRsp(uint16_t lcid,uint8_t id,const L2capConfigInfo * cfg,uint16_t result)485 int RfcommSendConfigRsp(uint16_t lcid, uint8_t id, const L2capConfigInfo *cfg, uint16_t result)
486 {
487 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
488
489 int ret = L2CIF_ConfigRsp(lcid, id, cfg, result, NULL);
490 if (ret != RFCOMM_SUCCESS) {
491 LOG_ERROR("%{public}s L2CIF_ConfigRsp return value is error.", __func__);
492 }
493
494 return ret;
495 }
496
497 /**
498 * @brief Call L2CAP_DisconnectionReq to send disconnect request to peer.
499 *
500 * @param lcid The L2CAP's channel id.
501 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
502 */
RfcommSendDisconnectReq(uint16_t lcid)503 int RfcommSendDisconnectReq(uint16_t lcid)
504 {
505 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
506
507 L2CIF_DisconnectionReq(lcid, NULL);
508
509 return RFCOMM_SUCCESS;
510 }
511
512 /**
513 * @brief Call L2CAP_DisconnectionRsp to send disconnect response to peer.
514 *
515 * @param lcid The L2CAP's channel id.
516 * @param id L2CAP's id information.
517 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
518 */
RfcommSendDisconnectRsp(uint16_t lcid,uint8_t id)519 int RfcommSendDisconnectRsp(uint16_t lcid, uint8_t id)
520 {
521 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
522
523 L2CIF_DisconnectionRsp(lcid, id, NULL);
524
525 return RFCOMM_SUCCESS;
526 }
527
528 /**
529 * @brief Call L2CAP_SendData to send RFCOMM frame to peer.
530 *
531 * @param lcid The L2CAP's channel id.
532 * @param header RFCOMM frame header information.
533 * @param headSize RFCOMM frame header length.
534 * @param tail RFCOMM frame tail information.
535 * @param pkt The RFCOMM frame information.
536 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
537 */
RfcommSendData(uint16_t lcid,const uint8_t * header,uint8_t headSize,uint8_t tail,Packet * pkt)538 int RfcommSendData(uint16_t lcid, const uint8_t *header, uint8_t headSize, uint8_t tail, Packet *pkt)
539 {
540 LOG_INFO("%{public}s lcid:%hu", __func__, lcid);
541
542 Packet *packet = NULL;
543 uint8_t *headerBuf = NULL;
544 uint8_t *tailBuf = NULL;
545
546 if (pkt == NULL) {
547 packet = PacketMalloc(headSize, 1, 0);
548 } else {
549 packet = PacketInheritMalloc(pkt, headSize, 1);
550 }
551
552 headerBuf = (uint8_t *)BufferPtr(PacketHead(packet));
553 tailBuf = (uint8_t *)BufferPtr(PacketTail(packet));
554 (void)memcpy_s(headerBuf, (sizeof(uint8_t) * headSize), header, (sizeof(uint8_t) * headSize));
555 *tailBuf = tail;
556
557 int ret = L2CIF_SendData(lcid, packet, NULL);
558 if (ret != RFCOMM_SUCCESS) {
559 LOG_ERROR("%{public}s L2CIF_SendData return value is error.", __func__);
560 }
561 PacketFree(packet);
562
563 return ret;
564 }
565