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 #include "platform/include/module.h"
19
20 #define WAIT_TIME (-1)
21
RfcommInitializeTsk(void * context)22 static void RfcommInitializeTsk(void *context)
23 {
24 LOG_INFO("%{public}s", __func__);
25
26 Event *ctx = context;
27
28 if (ctx == NULL) {
29 LOG_ERROR("%{public}s context is NULL.", __func__);
30 return;
31 }
32
33 RfcommInitialize();
34
35 EventSet(ctx);
36 }
37
38 /**
39 * @brief This function is used to initialize rfcomm resources and
40 * register the callback function to L2CAP.
41 *
42 * @since 6
43 */
RFCOMM_Startup()44 static void RFCOMM_Startup()
45 {
46 LOG_INFO("%{public}s", __func__);
47
48 Event *ctx = EventCreate(true);
49
50 int ret = BTM_CreateProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, BTM_PROCESSING_QUEUE_SIZE_DEFAULT);
51 if (ret != BT_SUCCESS) {
52 EventDelete(ctx);
53 return;
54 }
55
56 ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommInitializeTsk, ctx);
57 if (ret != BT_SUCCESS) {
58 EventDelete(ctx);
59 return;
60 }
61
62 EventWait(ctx, WAIT_TIME);
63 EventDelete(ctx);
64 }
65
RfcommFinalizeTsk(void * context)66 static void RfcommFinalizeTsk(void *context)
67 {
68 LOG_INFO("%{public}s", __func__);
69
70 Event *ctx = context;
71
72 if (ctx == NULL) {
73 LOG_ERROR("%{public}s context is NULL.", __func__);
74 return;
75 }
76
77 RfcommFinalize();
78
79 BTM_DeleteProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM);
80
81 EventSet(ctx);
82 }
83
84 /**
85 * @brief This function is used to release rfcomm internal resources and
86 * deregister the callback function to L2CAP.
87 *
88 * @since 6
89 */
RFCOMM_Shutdown()90 static void RFCOMM_Shutdown()
91 {
92 LOG_INFO("%{public}s", __func__);
93
94 Event *ctx = EventCreate(true);
95
96 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommFinalizeTsk, ctx);
97 if (ret != BT_SUCCESS) {
98 EventDelete(ctx);
99 return;
100 }
101
102 EventWait(ctx, WAIT_TIME);
103 EventDelete(ctx);
104 }
105
106 typedef struct {
107 uint8_t scn;
108 Event *event;
109 } RfcommAssignScnInfo;
110
RfcommAssignServerNumTsk(void * context)111 static void RfcommAssignServerNumTsk(void *context)
112 {
113 LOG_INFO("%{public}s", __func__);
114
115 RfcommAssignScnInfo *ctx = context;
116
117 if (ctx == NULL) {
118 LOG_ERROR("%{public}s context is NULL.", __func__);
119 return;
120 }
121
122 ctx->scn = RfcommAssignServerNum();
123
124 if (ctx->event != NULL) {
125 EventSet(ctx->event);
126 }
127 }
128
129 /**
130 * @brief The function is used to assign server numbers to individual servers.
131 * Server number is used to register with the RFCOMM service interface, range is 1~30.
132 * When the return value is 0, it means that there is no available server number.
133 * This Server number shall be registered in the Service Discovery Database;
134 * RFCOMM_SPEC_V12 #5.4
135 *
136 * @return Server number.0(unavailable number),1~30(available number)
137 * @since 6
138 */
RFCOMM_AssignServerNum()139 uint8_t RFCOMM_AssignServerNum()
140 {
141 LOG_INFO("%{public}s", __func__);
142
143 uint8_t scn = 0;
144 RfcommAssignScnInfo *ctx = malloc(sizeof(RfcommAssignScnInfo));
145 if (ctx == NULL) {
146 return scn;
147 }
148
149 (void)memset_s(ctx, sizeof(RfcommAssignScnInfo), 0x00, sizeof(RfcommAssignScnInfo));
150 ctx->event = EventCreate(true);
151
152 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommAssignServerNumTsk, ctx);
153 if (ret != BT_SUCCESS) {
154 EventDelete(ctx->event);
155 free(ctx);
156 return scn;
157 }
158
159 EventWait(ctx->event, WAIT_TIME);
160 EventDelete(ctx->event);
161 scn = ctx->scn;
162
163 free(ctx);
164 return scn;
165 }
166
167 typedef struct {
168 uint8_t scn;
169 } RfcommFreeScnInfo;
170
RfcommFreeServerNumTsk(void * context)171 static void RfcommFreeServerNumTsk(void *context)
172 {
173 LOG_INFO("%{public}s", __func__);
174
175 RfcommFreeScnInfo *ctx = context;
176
177 if (ctx == NULL) {
178 LOG_ERROR("%{public}s context is NULL.", __func__);
179 return;
180 }
181
182 RfcommFreeServerNum(ctx->scn);
183
184 free(ctx);
185 }
186
187 /**
188 * @brief After close the server, free the server number.
189 *
190 * @param scn Server number.
191 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
192 * @since 6
193 */
RFCOMM_FreeServerNum(uint8_t scn)194 int RFCOMM_FreeServerNum(uint8_t scn)
195 {
196 LOG_INFO("%{public}s scn:%hhu", __func__, scn);
197
198 RfcommFreeScnInfo *ctx = malloc(sizeof(RfcommFreeScnInfo));
199 if (ctx == NULL) {
200 return BT_NO_MEMORY;
201 }
202
203 ctx->scn = scn;
204
205 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommFreeServerNumTsk, ctx);
206 if (ret != BT_SUCCESS) {
207 free(ctx);
208 }
209
210 return ret;
211 }
212
213 typedef struct {
214 RfcommConnectReqInfo reqInfo;
215 uint16_t handle;
216 Event *event;
217 int result;
218 } RfcommConnectDlcInfo;
219
RfcommConnectChannelTsk(void * context)220 static void RfcommConnectChannelTsk(void *context)
221 {
222 LOG_INFO("%{public}s", __func__);
223
224 uint16_t handle = 0;
225 RfcommConnectDlcInfo *ctx = context;
226
227 if (ctx == NULL) {
228 LOG_ERROR("%{public}s context is NULL.", __func__);
229 return;
230 }
231
232 int ret = RfcommConnectChannel(&ctx->reqInfo, &handle);
233 ctx->handle = handle;
234 ctx->result = ret;
235
236 if (ctx->event != NULL) {
237 EventSet(ctx->event);
238 }
239 }
240
241 /**
242 * @brief The function is used by the client to establish a connection of the channel
243 *
244 * @param reqInfo Connection request information.
245 * @param handle The handle of the channel created by rfcomm.
246 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
247 * @since 6
248 */
RFCOMM_ConnectChannel(const RfcommConnectReqInfo * reqInfo,uint16_t * handle)249 int RFCOMM_ConnectChannel(const RfcommConnectReqInfo *reqInfo, uint16_t *handle)
250 {
251 LOG_INFO("%{public}s", __func__);
252
253 RfcommConnectDlcInfo *ctx = malloc(sizeof(RfcommConnectDlcInfo));
254 if (ctx == NULL) {
255 return BT_NO_MEMORY;
256 }
257
258 (void)memset_s(ctx, sizeof(RfcommConnectDlcInfo), 0x00, sizeof(RfcommConnectDlcInfo));
259 (void)memcpy_s(&ctx->reqInfo, sizeof(RfcommConnectReqInfo), reqInfo, sizeof(RfcommConnectReqInfo));
260 ctx->event = EventCreate(true);
261
262 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommConnectChannelTsk, ctx);
263 if (ret != BT_SUCCESS) {
264 EventDelete(ctx->event);
265 free(ctx);
266 return ret;
267 }
268
269 EventWait(ctx->event, WAIT_TIME);
270 EventDelete(ctx->event);
271 *handle = ctx->handle;
272 ret = ctx->result;
273
274 free(ctx);
275 return ret;
276 }
277
278 typedef struct {
279 uint8_t scn;
280 uint16_t mtu;
281 uint32_t eventMask;
282 RFCOMM_EventCallback callback;
283 void *context;
284 Event *event;
285 int retValue;
286 } RfcommRegistServerInfo;
287
RfcommRegisterServerTsk(void * context)288 static void RfcommRegisterServerTsk(void *context)
289 {
290 LOG_INFO("%{public}s", __func__);
291
292 RfcommRegistServerInfo *ctx = context;
293
294 if (ctx == NULL) {
295 LOG_ERROR("%{public}s context is NULL.", __func__);
296 return;
297 }
298
299 int ret = RfcommRegisterServer(ctx->scn, ctx->mtu, ctx->eventMask, ctx->callback, ctx->context);
300 ctx->retValue = ret;
301
302 if (ctx->event != NULL) {
303 EventSet(ctx->event);
304 }
305 }
306
307 /**
308 * @brief The function is used for the server to register with RFCOMM and
309 * wait for the client to connect.
310 *
311 * @param scn The server's number.
312 * @param mtu The maximum size of data received at a time.
313 * @param eventMask The collection of events followed by upper layers.
314 * @param callback The callback function used by rfcomm to notify uppers of data or events.
315 * @param context The content passed in from the upper layer.
316 * It will be brought back to the upper layer when callback is called.
317 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
318 * @since 6
319 */
RFCOMM_RegisterServer(uint8_t scn,uint16_t mtu,uint32_t eventMask,RFCOMM_EventCallback callback,void * context)320 int RFCOMM_RegisterServer(uint8_t scn, uint16_t mtu, uint32_t eventMask,
321 RFCOMM_EventCallback callback, void *context)
322 {
323 LOG_INFO("%{public}s", __func__);
324
325 RfcommRegistServerInfo *ctx = malloc(sizeof(RfcommRegistServerInfo));
326 if (ctx == NULL) {
327 return BT_NO_MEMORY;
328 }
329
330 (void)memset_s(ctx, sizeof(RfcommRegistServerInfo), 0x00, sizeof(RfcommRegistServerInfo));
331 ctx->scn = scn;
332 ctx->mtu = mtu;
333 ctx->eventMask = eventMask;
334 ctx->callback = callback;
335 ctx->context = context;
336 ctx->event = EventCreate(true);
337
338 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRegisterServerTsk, ctx);
339 if (ret != BT_SUCCESS) {
340 EventDelete(ctx->event);
341 free(ctx);
342 return ret;
343 }
344
345 EventWait(ctx->event, WAIT_TIME);
346 EventDelete(ctx->event);
347 ret = ctx->retValue;
348
349 free(ctx);
350 return ret;
351 }
352
353 typedef struct {
354 uint16_t handle;
355 } RfcommAcceptConnectionInfo;
356
RfcommAcceptConnectionTsk(void * context)357 static void RfcommAcceptConnectionTsk(void *context)
358 {
359 LOG_INFO("%{public}s", __func__);
360
361 RfcommAcceptConnectionInfo *ctx = context;
362
363 if (ctx == NULL) {
364 LOG_ERROR("%{public}s context is NULL.", __func__);
365 return;
366 }
367
368 RfcommAcceptConnection(ctx->handle);
369
370 free(ctx);
371 }
372
373 /**
374 * @brief The function is used to tell RFCOMM to accept the connection request when the server
375 * receives the connection notification(eventId is RFCOMM_EVENT_CONNECT_INCOMING).
376 * After receiving the response from the upper layer, RFCOMM notifies the client
377 * of the peer device to accept the connection request.
378 *
379 * @param handle The channel(DLC)'s handle number
380 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
381 * @since 6
382 */
RFCOMM_AcceptConnection(uint16_t handle)383 int RFCOMM_AcceptConnection(uint16_t handle)
384 {
385 LOG_INFO("%{public}s handle:%hu", __func__, handle);
386
387 RfcommAcceptConnectionInfo *ctx = malloc(sizeof(RfcommAcceptConnectionInfo));
388 if (ctx == NULL) {
389 return BT_NO_MEMORY;
390 }
391
392 ctx->handle = handle;
393
394 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommAcceptConnectionTsk, ctx);
395 if (ret != BT_SUCCESS) {
396 free(ctx);
397 }
398
399 return ret;
400 }
401
402 typedef struct {
403 uint16_t handle;
404 } RfcommRejectConnectionInfo;
405
RfcommRejectConnectionTsk(void * context)406 static void RfcommRejectConnectionTsk(void *context)
407 {
408 LOG_INFO("%{public}s", __func__);
409
410 RfcommRejectConnectionInfo *ctx = context;
411
412 if (ctx == NULL) {
413 LOG_ERROR("%{public}s context is NULL.", __func__);
414 return;
415 }
416
417 RfcommRejectConnection(ctx->handle);
418
419 free(ctx);
420 }
421
422 /**
423 * @brief This function is used to tell RFCOMM to reject the connection request when the server
424 * receives the connection notification(eventId is RFCOMM_EVENT_CONNECT_INCOMING).
425 * After receiving the response from the upper layer, RFCOMM notifies the client
426 * of the peer device to reject the connection request.
427 *
428 * @param handle The channel(DLC)'s handle number
429 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
430 * @since 6
431 */
RFCOMM_RejectConnection(uint16_t handle)432 int RFCOMM_RejectConnection(uint16_t handle)
433 {
434 LOG_INFO("%{public}s handle:%hu", __func__, handle);
435
436 RfcommRejectConnectionInfo *ctx = malloc(sizeof(RfcommRejectConnectionInfo));
437 if (ctx == NULL) {
438 return BT_NO_MEMORY;
439 }
440
441 ctx->handle = handle;
442
443 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRejectConnectionTsk, ctx);
444 if (ret != BT_SUCCESS) {
445 free(ctx);
446 }
447
448 return ret;
449 }
450
451 typedef struct {
452 uint16_t handle;
453 } RfcommDisconnectChannelInfo;
454
RfcommDisconnectChannelTsk(void * context)455 static void RfcommDisconnectChannelTsk(void *context)
456 {
457 LOG_INFO("%{public}s", __func__);
458
459 RfcommRejectConnectionInfo *ctx = context;
460
461 if (ctx == NULL) {
462 LOG_ERROR("%{public}s context is NULL.", __func__);
463 return;
464 }
465
466 RfcommDisconnectChannel(ctx->handle);
467
468 free(ctx);
469 }
470
471 /**
472 * @brief The function is used to disconnect the specified channel.
473 * RFCOMM_SPEC_V12 #5.2
474 *
475 * @param handle The channel(DLC)'s handle number
476 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
477 * @since 6
478 */
RFCOMM_DisconnectChannel(uint16_t handle)479 int RFCOMM_DisconnectChannel(uint16_t handle)
480 {
481 LOG_INFO("%{public}s handle:%hu", __func__, handle);
482
483 RfcommDisconnectChannelInfo *ctx = malloc(sizeof(RfcommDisconnectChannelInfo));
484 if (ctx == NULL) {
485 return BT_NO_MEMORY;
486 }
487
488 ctx->handle = handle;
489
490 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommDisconnectChannelTsk, ctx);
491 if (ret != BT_SUCCESS) {
492 free(ctx);
493 }
494
495 return ret;
496 }
497
498 typedef struct {
499 uint8_t scn;
500 bool isRemoveCallback;
501 Event *event;
502 } RfcommDeregisterServerInfo;
503
RfcommDeregisterServerTsk(void * context)504 static void RfcommDeregisterServerTsk(void *context)
505 {
506 LOG_INFO("%{public}s", __func__);
507
508 RfcommDeregisterServerInfo *ctx = context;
509
510 if (ctx == NULL) {
511 LOG_ERROR("%{public}s context is NULL.", __func__);
512 return;
513 }
514
515 RfcommDeregisterServer(ctx->scn, ctx->isRemoveCallback);
516
517 if (ctx->event != NULL) {
518 EventSet(ctx->event);
519 }
520 }
521
522 /**
523 * @brief When the server is shut down, call this function to
524 * release the resources about the server held in RFCOMM.
525 *
526 * @param scn The server's number
527 * @param isRemoveCallback true:remove callback,RFCOMM will not notify event to upper layer.otherwise:false.
528 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
529 * @since 6
530 */
RFCOMM_DeregisterServer(uint8_t scn,bool isRemoveCallback)531 int RFCOMM_DeregisterServer(uint8_t scn, bool isRemoveCallback)
532 {
533 LOG_INFO("%{public}s scn:%hhu, isRemoveCallback:%{public}d.", __func__, scn, isRemoveCallback);
534
535 RfcommDeregisterServerInfo *ctx = malloc(sizeof(RfcommDeregisterServerInfo));
536 if (ctx == NULL) {
537 return BT_NO_MEMORY;
538 }
539
540 (void)memset_s(ctx, sizeof(RfcommDeregisterServerInfo), 0x00, sizeof(RfcommDeregisterServerInfo));
541 ctx->scn = scn;
542 ctx->isRemoveCallback = isRemoveCallback;
543 ctx->event = EventCreate(true);
544
545 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommDeregisterServerTsk, ctx);
546 if (ret != BT_SUCCESS) {
547 EventDelete(ctx->event);
548 free(ctx);
549 return ret;
550 }
551
552 EventWait(ctx->event, WAIT_TIME);
553 EventDelete(ctx->event);
554
555 free(ctx);
556 return ret;
557 }
558
559 typedef struct {
560 uint16_t handle;
561 RfcommRemotePortConfig config;
562 } RfcommSetRpnInfo;
563
RfcommSetPortConfigTsk(void * context)564 static void RfcommSetPortConfigTsk(void *context)
565 {
566 LOG_INFO("%{public}s", __func__);
567
568 RfcommSetRpnInfo *ctx = context;
569
570 if (ctx == NULL) {
571 LOG_ERROR("%{public}s context is NULL.", __func__);
572 return;
573 }
574
575 RfcommSetPortConfig(ctx->handle, &ctx->config);
576
577 free(ctx);
578 }
579
580 /**
581 * @brief The function is used for set the remote port communication settings.
582 * The command may be used before a new DLC is opened and shall be used
583 * whenever the port settings change.
584 * RFCOMM_SPEC_V12 #5.5.1
585 *
586 * @param handle The channel(DLC)'s handle number
587 * @param config Remote port negotiation parameters
588 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
589 * @since 6
590 */
RFCOMM_SetPortConfig(uint16_t handle,const RfcommRemotePortConfig * config)591 int RFCOMM_SetPortConfig(uint16_t handle, const RfcommRemotePortConfig *config)
592 {
593 LOG_INFO("%{public}s handle:%hu", __func__, handle);
594
595 RfcommSetRpnInfo *ctx = malloc(sizeof(RfcommSetRpnInfo));
596 if (ctx == NULL) {
597 return BT_NO_MEMORY;
598 }
599
600 (void)memset_s(ctx, sizeof(RfcommSetRpnInfo), 0x00, sizeof(RfcommSetRpnInfo));
601 ctx->handle = handle;
602 (void)memcpy_s(&ctx->config, sizeof(RfcommRemotePortConfig), config, sizeof(RfcommRemotePortConfig));
603
604 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommSetPortConfigTsk, ctx);
605 if (ret != BT_SUCCESS) {
606 free(ctx);
607 }
608
609 return ret;
610 }
611
612 typedef struct {
613 uint16_t handle;
614 } RfcommReqPortConfigInfo;
615
RfcommReqPortConfigTsk(void * context)616 static void RfcommReqPortConfigTsk(void *context)
617 {
618 LOG_INFO("%{public}s", __func__);
619
620 RfcommReqPortConfigInfo *ctx = context;
621
622 if (ctx == NULL) {
623 LOG_ERROR("%{public}s context is NULL.", __func__);
624 return;
625 }
626
627 RfcommReqPortConfig(ctx->handle);
628
629 free(ctx);
630 }
631
632 /**
633 * @brief The function is used to obtain the remote port negotiation information
634 * of the peer device.
635 *
636 * @param handle The channel(DLC)'s handle number
637 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
638 * @since 6
639 */
RFCOMM_ReqPortConfig(uint16_t handle)640 int RFCOMM_ReqPortConfig(uint16_t handle)
641 {
642 LOG_INFO("%{public}s handle:%hu", __func__, handle);
643
644 RfcommReqPortConfigInfo *ctx = malloc(sizeof(RfcommReqPortConfigInfo));
645 if (ctx == NULL) {
646 return BT_NO_MEMORY;
647 }
648
649 ctx->handle = handle;
650
651 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommReqPortConfigTsk, ctx);
652 if (ret != BT_SUCCESS) {
653 free(ctx);
654 }
655
656 return ret;
657 }
658
659 typedef struct {
660 uint16_t handle;
661 RfcommRemoteLineStatus lineStatus;
662 } RfcommSendRlsInfo;
663
RfcommSendRemoteLineStatusTsk(void * context)664 static void RfcommSendRemoteLineStatusTsk(void *context)
665 {
666 LOG_INFO("%{public}s", __func__);
667
668 RfcommSendRlsInfo *ctx = context;
669
670 if (ctx == NULL) {
671 LOG_ERROR("%{public}s context is NULL.", __func__);
672 return;
673 }
674
675 RfcommSendRemoteLineStatus(ctx->handle, &ctx->lineStatus);
676
677 free(ctx);
678 }
679
680 /**
681 * @brief The function is used for indication of remote port line status.
682 * RFCOMM_SPEC_V12 #5.5.2
683 *
684 * @param handle The channel(DLC)'s handle number
685 * @param lineStatus Remote line status
686 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
687 * @since 6
688 */
RFCOMM_SendRemoteLineStatus(uint16_t handle,const RfcommRemoteLineStatus * lineStatus)689 int RFCOMM_SendRemoteLineStatus(uint16_t handle, const RfcommRemoteLineStatus *lineStatus)
690 {
691 LOG_INFO("%{public}s handle:%hu", __func__, handle);
692
693 RfcommSendRlsInfo *ctx = malloc(sizeof(RfcommSendRlsInfo));
694 if (ctx == NULL) {
695 return BT_NO_MEMORY;
696 }
697
698 (void)memset_s(ctx, sizeof(RfcommSendRlsInfo), 0x00, sizeof(RfcommSendRlsInfo));
699 ctx->handle = handle;
700 (void)memcpy_s(&ctx->lineStatus, sizeof(RfcommRemoteLineStatus), lineStatus, sizeof(RfcommRemoteLineStatus));
701
702 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommSendRemoteLineStatusTsk, ctx);
703 if (ret != BT_SUCCESS) {
704 free(ctx);
705 }
706
707 return ret;
708 }
709
710 typedef struct {
711 uint16_t handle;
712 RfcommModemStatus modemStatus;
713 } RfcommSetMscInfo;
714
RfcommSetModemStatusTsk(void * context)715 static void RfcommSetModemStatusTsk(void *context)
716 {
717 LOG_INFO("%{public}s", __func__);
718
719 RfcommSetMscInfo *ctx = context;
720
721 if (ctx == NULL) {
722 LOG_ERROR("%{public}s context is NULL.", __func__);
723 return;
724 }
725
726 RfcommSetModemStatus(ctx->handle, &ctx->modemStatus);
727
728 free(ctx);
729 }
730
731 /**
732 * @brief The function is used to convey the RS-232 control signals and the break signal.
733 * RFCOMM_SPEC_V12 #2.2
734 *
735 * @param handle The channel(DLC)'s handle number
736 * @param modemStatus Control signals and the break signal
737 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
738 * @since 6
739 */
RFCOMM_SetModemStatus(uint16_t handle,const RfcommModemStatus * modemStatus)740 int RFCOMM_SetModemStatus(uint16_t handle, const RfcommModemStatus *modemStatus)
741 {
742 LOG_INFO("%{public}s handle:%hu", __func__, handle);
743
744 RfcommSetMscInfo *ctx = malloc(sizeof(RfcommSetMscInfo));
745 if (ctx == NULL) {
746 return BT_NO_MEMORY;
747 }
748
749 (void)memset_s(ctx, sizeof(RfcommSetMscInfo), 0x00, sizeof(RfcommSetMscInfo));
750 ctx->handle = handle;
751 (void)memcpy_s(&ctx->modemStatus, sizeof(RfcommModemStatus), modemStatus, sizeof(RfcommModemStatus));
752
753 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommSetModemStatusTsk, ctx);
754 if (ret != BT_SUCCESS) {
755 free(ctx);
756 }
757
758 return ret;
759 }
760
761 typedef struct {
762 uint16_t handle;
763 RfcommPortState state;
764 Event *event;
765 int result;
766 } RfcommGetPortStInfo;
767
RfcommGetPortStateTsk(void * context)768 static void RfcommGetPortStateTsk(void *context)
769 {
770 LOG_INFO("%{public}s", __func__);
771
772 RfcommGetPortStInfo *ctx = context;
773
774 if (ctx == NULL) {
775 LOG_ERROR("%{public}s context is NULL.", __func__);
776 return;
777 }
778
779 int ret = RfcommGetPortState(ctx->handle, &ctx->state);
780 ctx->result = ret;
781
782 if (ctx->event != NULL) {
783 EventSet(ctx->event);
784 }
785 }
786
787 /**
788 * @brief This function is used to obtain port related information.
789 * Currently, the amount of data sent and received by the port can be obtained.
790 *
791 * @param handle The channel(DLC)'s handle number
792 * @param state The port's information
793 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
794 * @since 6
795 */
RFCOMM_GetPortState(uint16_t handle,RfcommPortState * state)796 int RFCOMM_GetPortState(uint16_t handle, RfcommPortState *state)
797 {
798 LOG_INFO("%{public}s handle:%hu", __func__, handle);
799
800 RfcommGetPortStInfo *ctx = malloc(sizeof(RfcommGetPortStInfo));
801 if (ctx == NULL) {
802 return BT_NO_MEMORY;
803 }
804
805 (void)memset_s(ctx, sizeof(RfcommGetPortStInfo), 0x00, sizeof(RfcommGetPortStInfo));
806 ctx->handle = handle;
807 ctx->event = EventCreate(true);
808
809 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommGetPortStateTsk, ctx);
810 if (ret != BT_SUCCESS) {
811 EventDelete(ctx->event);
812 free(ctx);
813 return ret;
814 }
815
816 EventWait(ctx->event, WAIT_TIME);
817 EventDelete(ctx->event);
818 (void)memcpy_s(state, sizeof(RfcommPortState), &ctx->state, sizeof(RfcommPortState));
819 ret = ctx->result;
820
821 free(ctx);
822 return ret;
823 }
824
825 /**
826 * @brief This function is used to get the payload packet sent by the peer from RFCOMM.
827 * After the caller finishes using this interface, it creates a packet reference or
828 * reads the payload buffer as needed, and must free the packet obtained from RFCOMM.
829 *
830 * @param handle The channel(DLC)'s handle number
831 * @param pkt The packet point for receiving data
832 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
833 * @since 6
834 */
RFCOMM_Read(uint16_t handle,Packet ** pkt)835 int RFCOMM_Read(uint16_t handle, Packet **pkt)
836 {
837 LOG_INFO("%{public}s handle:%hu", __func__, handle);
838
839 RfcommReadLock();
840 int ret = RfcommRead(handle, pkt);
841 RfcommReadUnlock();
842 return ret;
843 }
844
845 typedef struct {
846 uint16_t handle;
847 Packet *pkt;
848 Event *event;
849 int result;
850 } RfcommWriteInfo;
851
RfcommWriteTsk(void * context)852 static void RfcommWriteTsk(void *context)
853 {
854 LOG_INFO("%{public}s", __func__);
855
856 RfcommWriteInfo *ctx = context;
857
858 if (ctx == NULL) {
859 LOG_ERROR("%{public}s context is NULL.", __func__);
860 return;
861 }
862
863 int ret = RfcommWrite(ctx->handle, ctx->pkt);
864 ctx->result = ret;
865
866 if (ctx->event != NULL) {
867 EventSet(ctx->event);
868 }
869 }
870
871 /**
872 * @brief This function is used to write the data to be transmitted to the opposite end to RFCOMM.
873 *
874 * @param handle The channel(DLC)'s handle number
875 * @param pkt The packet for sending data
876 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
877 * @since 6
878 */
RFCOMM_Write(uint16_t handle,Packet * pkt)879 int RFCOMM_Write(uint16_t handle, Packet *pkt)
880 {
881 LOG_INFO("%{public}s handle:%hu", __func__, handle);
882
883 RfcommWriteInfo *ctx = malloc(sizeof(RfcommWriteInfo));
884 if (ctx == NULL) {
885 return BT_NO_MEMORY;
886 }
887
888 (void)memset_s(ctx, sizeof(RfcommWriteInfo), 0x00, sizeof(RfcommWriteInfo));
889 ctx->handle = handle;
890 ctx->pkt = pkt;
891 ctx->event = EventCreate(true);
892
893 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommWriteTsk, ctx);
894 if (ret != BT_SUCCESS) {
895 EventDelete(ctx->event);
896 free(ctx);
897 return ret;
898 }
899
900 EventWait(ctx->event, WAIT_TIME);
901 EventDelete(ctx->event);
902 ret = ctx->result;
903
904 free(ctx);
905 return ret;
906 }
907
908 typedef struct {
909 uint16_t handle;
910 Packet *pkt;
911 } RfcommSendTestCmdInfo;
912
RfcommSendTestCmdTsk(void * context)913 static void RfcommSendTestCmdTsk(void *context)
914 {
915 LOG_INFO("%{public}s", __func__);
916
917 RfcommSendTestCmdInfo *ctx = context;
918
919 if (ctx == NULL) {
920 LOG_ERROR("%{public}s context is NULL.", __func__);
921 return;
922 }
923
924 RfcommSendTestCmd(ctx->handle, ctx->pkt);
925
926 PacketFree(ctx->pkt);
927 free(ctx);
928 }
929
930 /**
931 * @brief This function is used to send Test Command to the peer.
932 *
933 * @param handle The channel(DLC)'s handle number
934 * @param pkt The packet for sending data
935 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
936 * @since 6
937 */
RFCOMM_SendTestCmd(uint16_t handle,Packet * pkt)938 int RFCOMM_SendTestCmd(uint16_t handle, Packet *pkt)
939 {
940 LOG_INFO("%{public}s handle:%hu", __func__, handle);
941
942 RfcommSendTestCmdInfo *ctx = malloc(sizeof(RfcommSendTestCmdInfo));
943 if (ctx == NULL) {
944 return BT_NO_MEMORY;
945 }
946
947 (void)memset_s(ctx, sizeof(RfcommSendTestCmdInfo), 0x00, sizeof(RfcommSendTestCmdInfo));
948 ctx->handle = handle;
949 ctx->pkt = PacketRefMalloc(pkt);
950
951 int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommSendTestCmdTsk, ctx);
952 if (ret != BT_SUCCESS) {
953 PacketFree(ctx->pkt);
954 free(ctx);
955 }
956
957 return ret;
958 }
959
RFCOMM_Init(int traceLevel)960 static void RFCOMM_Init(int traceLevel)
961 {
962 LOG_INFO("%{public}s", __func__);
963
964 (void)traceLevel;
965
966 return;
967 }
968
RFCOMM_Cleanup()969 static void RFCOMM_Cleanup()
970 {
971 LOG_INFO("%{public}s", __func__);
972
973 return;
974 }
975
976 static Module g_rfcomm = {
977 .name = MODULE_NAME_RFCOMM,
978 .init = RFCOMM_Init,
979 .startup = RFCOMM_Startup,
980 .shutdown = RFCOMM_Shutdown,
981 .cleanup = RFCOMM_Cleanup,
982 .dependencies = {MODULE_NAME_L2CAP, MODULE_NAME_GAP},
983 };
984
985 MODULE_DECL(g_rfcomm)