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