/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rfcomm_defs.h"
#include "platform/include/module.h"
#define WAIT_TIME (-1)
static void RfcommInitializeTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
Event *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommInitialize();
EventSet(ctx);
}
/**
* @brief This function is used to initialize rfcomm resources and
* register the callback function to L2CAP.
*
* @since 6
*/
static void RFCOMM_Startup()
{
LOG_INFO("%{public}s", __func__);
Event *ctx = EventCreate(true);
int ret = BTM_CreateProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, BTM_PROCESSING_QUEUE_SIZE_DEFAULT);
if (ret != BT_SUCCESS) {
EventDelete(ctx);
return;
}
ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommInitializeTsk, ctx);
if (ret != BT_SUCCESS) {
EventDelete(ctx);
return;
}
EventWait(ctx, WAIT_TIME);
EventDelete(ctx);
}
static void RfcommFinalizeTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
Event *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommFinalize();
BTM_DeleteProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM);
EventSet(ctx);
}
/**
* @brief This function is used to release rfcomm internal resources and
* deregister the callback function to L2CAP.
*
* @since 6
*/
static void RFCOMM_Shutdown()
{
LOG_INFO("%{public}s", __func__);
Event *ctx = EventCreate(true);
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommFinalizeTsk, ctx);
if (ret != BT_SUCCESS) {
EventDelete(ctx);
return;
}
EventWait(ctx, WAIT_TIME);
EventDelete(ctx);
}
typedef struct {
uint8_t scn;
Event *event;
} RfcommAssignScnInfo;
static void RfcommAssignServerNumTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommAssignScnInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
ctx->scn = RfcommAssignServerNum();
if (ctx->event != NULL) {
EventSet(ctx->event);
}
}
/**
* @brief The function is used to assign server numbers to individual servers.
* Server number is used to register with the RFCOMM service interface, range is 1~30.
* When the return value is 0, it means that there is no available server number.
* This Server number shall be registered in the Service Discovery Database;
* RFCOMM_SPEC_V12 #5.4
*
* @return Server number.0(unavailable number),1~30(available number)
* @since 6
*/
uint8_t RFCOMM_AssignServerNum()
{
LOG_INFO("%{public}s", __func__);
uint8_t scn = 0;
RfcommAssignScnInfo *ctx = malloc(sizeof(RfcommAssignScnInfo));
if (ctx == NULL) {
return scn;
}
(void)memset_s(ctx, sizeof(RfcommAssignScnInfo), 0x00, sizeof(RfcommAssignScnInfo));
ctx->event = EventCreate(true);
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommAssignServerNumTsk, ctx);
if (ret != BT_SUCCESS) {
EventDelete(ctx->event);
free(ctx);
return scn;
}
EventWait(ctx->event, WAIT_TIME);
EventDelete(ctx->event);
scn = ctx->scn;
free(ctx);
return scn;
}
typedef struct {
uint8_t scn;
} RfcommFreeScnInfo;
static void RfcommFreeServerNumTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommFreeScnInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommFreeServerNum(ctx->scn);
free(ctx);
}
/**
* @brief After close the server, free the server number.
*
* @param scn Server number.
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_FreeServerNum(uint8_t scn)
{
LOG_INFO("%{public}s scn:%hhu", __func__, scn);
RfcommFreeScnInfo *ctx = malloc(sizeof(RfcommFreeScnInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
ctx->scn = scn;
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommFreeServerNumTsk, ctx);
if (ret != BT_SUCCESS) {
free(ctx);
}
return ret;
}
typedef struct {
RfcommConnectReqInfo reqInfo;
uint16_t handle;
Event *event;
int result;
} RfcommConnectDlcInfo;
static void RfcommConnectChannelTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
uint16_t handle = 0;
RfcommConnectDlcInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
int ret = RfcommConnectChannel(&ctx->reqInfo, &handle);
ctx->handle = handle;
ctx->result = ret;
if (ctx->event != NULL) {
EventSet(ctx->event);
}
}
/**
* @brief The function is used by the client to establish a connection of the channel
*
* @param reqInfo Connection request information.
* @param handle The handle of the channel created by rfcomm.
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_ConnectChannel(const RfcommConnectReqInfo *reqInfo, uint16_t *handle)
{
LOG_INFO("%{public}s", __func__);
RfcommConnectDlcInfo *ctx = malloc(sizeof(RfcommConnectDlcInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
(void)memset_s(ctx, sizeof(RfcommConnectDlcInfo), 0x00, sizeof(RfcommConnectDlcInfo));
(void)memcpy_s(&ctx->reqInfo, sizeof(RfcommConnectReqInfo), reqInfo, sizeof(RfcommConnectReqInfo));
ctx->event = EventCreate(true);
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommConnectChannelTsk, ctx);
if (ret != BT_SUCCESS) {
EventDelete(ctx->event);
free(ctx);
return ret;
}
EventWait(ctx->event, WAIT_TIME);
EventDelete(ctx->event);
*handle = ctx->handle;
ret = ctx->result;
free(ctx);
return ret;
}
typedef struct {
uint8_t scn;
uint16_t mtu;
uint32_t eventMask;
RFCOMM_EventCallback callback;
void *context;
Event *event;
int retValue;
} RfcommRegistServerInfo;
static void RfcommRegisterServerTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommRegistServerInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
int ret = RfcommRegisterServer(ctx->scn, ctx->mtu, ctx->eventMask, ctx->callback, ctx->context);
ctx->retValue = ret;
if (ctx->event != NULL) {
EventSet(ctx->event);
}
}
/**
* @brief The function is used for the server to register with RFCOMM and
* wait for the client to connect.
*
* @param scn The server's number.
* @param mtu The maximum size of data received at a time.
* @param eventMask The collection of events followed by upper layers.
* @param callback The callback function used by rfcomm to notify uppers of data or events.
* @param context The content passed in from the upper layer.
* It will be brought back to the upper layer when callback is called.
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_RegisterServer(uint8_t scn, uint16_t mtu, uint32_t eventMask,
RFCOMM_EventCallback callback, void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommRegistServerInfo *ctx = malloc(sizeof(RfcommRegistServerInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
(void)memset_s(ctx, sizeof(RfcommRegistServerInfo), 0x00, sizeof(RfcommRegistServerInfo));
ctx->scn = scn;
ctx->mtu = mtu;
ctx->eventMask = eventMask;
ctx->callback = callback;
ctx->context = context;
ctx->event = EventCreate(true);
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRegisterServerTsk, ctx);
if (ret != BT_SUCCESS) {
EventDelete(ctx->event);
free(ctx);
return ret;
}
EventWait(ctx->event, WAIT_TIME);
EventDelete(ctx->event);
ret = ctx->retValue;
free(ctx);
return ret;
}
typedef struct {
uint16_t handle;
} RfcommAcceptConnectionInfo;
static void RfcommAcceptConnectionTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommAcceptConnectionInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommAcceptConnection(ctx->handle);
free(ctx);
}
/**
* @brief The function is used to tell RFCOMM to accept the connection request when the server
* receives the connection notification(eventId is RFCOMM_EVENT_CONNECT_INCOMING).
* After receiving the response from the upper layer, RFCOMM notifies the client
* of the peer device to accept the connection request.
*
* @param handle The channel(DLC)'s handle number
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_AcceptConnection(uint16_t handle)
{
LOG_INFO("%{public}s handle:%hu", __func__, handle);
RfcommAcceptConnectionInfo *ctx = malloc(sizeof(RfcommAcceptConnectionInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
ctx->handle = handle;
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommAcceptConnectionTsk, ctx);
if (ret != BT_SUCCESS) {
free(ctx);
}
return ret;
}
typedef struct {
uint16_t handle;
} RfcommRejectConnectionInfo;
static void RfcommRejectConnectionTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommRejectConnectionInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommRejectConnection(ctx->handle);
free(ctx);
}
/**
* @brief This function is used to tell RFCOMM to reject the connection request when the server
* receives the connection notification(eventId is RFCOMM_EVENT_CONNECT_INCOMING).
* After receiving the response from the upper layer, RFCOMM notifies the client
* of the peer device to reject the connection request.
*
* @param handle The channel(DLC)'s handle number
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_RejectConnection(uint16_t handle)
{
LOG_INFO("%{public}s handle:%hu", __func__, handle);
RfcommRejectConnectionInfo *ctx = malloc(sizeof(RfcommRejectConnectionInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
ctx->handle = handle;
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommRejectConnectionTsk, ctx);
if (ret != BT_SUCCESS) {
free(ctx);
}
return ret;
}
typedef struct {
uint16_t handle;
} RfcommDisconnectChannelInfo;
static void RfcommDisconnectChannelTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommRejectConnectionInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommDisconnectChannel(ctx->handle);
free(ctx);
}
/**
* @brief The function is used to disconnect the specified channel.
* RFCOMM_SPEC_V12 #5.2
*
* @param handle The channel(DLC)'s handle number
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_DisconnectChannel(uint16_t handle)
{
LOG_INFO("%{public}s handle:%hu", __func__, handle);
RfcommDisconnectChannelInfo *ctx = malloc(sizeof(RfcommDisconnectChannelInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
ctx->handle = handle;
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommDisconnectChannelTsk, ctx);
if (ret != BT_SUCCESS) {
free(ctx);
}
return ret;
}
typedef struct {
uint8_t scn;
bool isRemoveCallback;
Event *event;
} RfcommDeregisterServerInfo;
static void RfcommDeregisterServerTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommDeregisterServerInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommDeregisterServer(ctx->scn, ctx->isRemoveCallback);
if (ctx->event != NULL) {
EventSet(ctx->event);
}
}
/**
* @brief When the server is shut down, call this function to
* release the resources about the server held in RFCOMM.
*
* @param scn The server's number
* @param isRemoveCallback true:remove callback,RFCOMM will not notify event to upper layer.otherwise:false.
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_DeregisterServer(uint8_t scn, bool isRemoveCallback)
{
LOG_INFO("%{public}s scn:%hhu, isRemoveCallback:%{public}d.", __func__, scn, isRemoveCallback);
RfcommDeregisterServerInfo *ctx = malloc(sizeof(RfcommDeregisterServerInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
(void)memset_s(ctx, sizeof(RfcommDeregisterServerInfo), 0x00, sizeof(RfcommDeregisterServerInfo));
ctx->scn = scn;
ctx->isRemoveCallback = isRemoveCallback;
ctx->event = EventCreate(true);
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommDeregisterServerTsk, ctx);
if (ret != BT_SUCCESS) {
EventDelete(ctx->event);
free(ctx);
return ret;
}
EventWait(ctx->event, WAIT_TIME);
EventDelete(ctx->event);
free(ctx);
return ret;
}
typedef struct {
uint16_t handle;
RfcommRemotePortConfig config;
} RfcommSetRpnInfo;
static void RfcommSetPortConfigTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommSetRpnInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommSetPortConfig(ctx->handle, &ctx->config);
free(ctx);
}
/**
* @brief The function is used for set the remote port communication settings.
* The command may be used before a new DLC is opened and shall be used
* whenever the port settings change.
* RFCOMM_SPEC_V12 #5.5.1
*
* @param handle The channel(DLC)'s handle number
* @param config Remote port negotiation parameters
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_SetPortConfig(uint16_t handle, const RfcommRemotePortConfig *config)
{
LOG_INFO("%{public}s handle:%hu", __func__, handle);
RfcommSetRpnInfo *ctx = malloc(sizeof(RfcommSetRpnInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
(void)memset_s(ctx, sizeof(RfcommSetRpnInfo), 0x00, sizeof(RfcommSetRpnInfo));
ctx->handle = handle;
(void)memcpy_s(&ctx->config, sizeof(RfcommRemotePortConfig), config, sizeof(RfcommRemotePortConfig));
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommSetPortConfigTsk, ctx);
if (ret != BT_SUCCESS) {
free(ctx);
}
return ret;
}
typedef struct {
uint16_t handle;
} RfcommReqPortConfigInfo;
static void RfcommReqPortConfigTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommReqPortConfigInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommReqPortConfig(ctx->handle);
free(ctx);
}
/**
* @brief The function is used to obtain the remote port negotiation information
* of the peer device.
*
* @param handle The channel(DLC)'s handle number
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_ReqPortConfig(uint16_t handle)
{
LOG_INFO("%{public}s handle:%hu", __func__, handle);
RfcommReqPortConfigInfo *ctx = malloc(sizeof(RfcommReqPortConfigInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
ctx->handle = handle;
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommReqPortConfigTsk, ctx);
if (ret != BT_SUCCESS) {
free(ctx);
}
return ret;
}
typedef struct {
uint16_t handle;
RfcommRemoteLineStatus lineStatus;
} RfcommSendRlsInfo;
static void RfcommSendRemoteLineStatusTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommSendRlsInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommSendRemoteLineStatus(ctx->handle, &ctx->lineStatus);
free(ctx);
}
/**
* @brief The function is used for indication of remote port line status.
* RFCOMM_SPEC_V12 #5.5.2
*
* @param handle The channel(DLC)'s handle number
* @param lineStatus Remote line status
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_SendRemoteLineStatus(uint16_t handle, const RfcommRemoteLineStatus *lineStatus)
{
LOG_INFO("%{public}s handle:%hu", __func__, handle);
RfcommSendRlsInfo *ctx = malloc(sizeof(RfcommSendRlsInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
(void)memset_s(ctx, sizeof(RfcommSendRlsInfo), 0x00, sizeof(RfcommSendRlsInfo));
ctx->handle = handle;
(void)memcpy_s(&ctx->lineStatus, sizeof(RfcommRemoteLineStatus), lineStatus, sizeof(RfcommRemoteLineStatus));
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommSendRemoteLineStatusTsk, ctx);
if (ret != BT_SUCCESS) {
free(ctx);
}
return ret;
}
typedef struct {
uint16_t handle;
RfcommModemStatus modemStatus;
} RfcommSetMscInfo;
static void RfcommSetModemStatusTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommSetMscInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommSetModemStatus(ctx->handle, &ctx->modemStatus);
free(ctx);
}
/**
* @brief The function is used to convey the RS-232 control signals and the break signal.
* RFCOMM_SPEC_V12 #2.2
*
* @param handle The channel(DLC)'s handle number
* @param modemStatus Control signals and the break signal
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_SetModemStatus(uint16_t handle, const RfcommModemStatus *modemStatus)
{
LOG_INFO("%{public}s handle:%hu", __func__, handle);
RfcommSetMscInfo *ctx = malloc(sizeof(RfcommSetMscInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
(void)memset_s(ctx, sizeof(RfcommSetMscInfo), 0x00, sizeof(RfcommSetMscInfo));
ctx->handle = handle;
(void)memcpy_s(&ctx->modemStatus, sizeof(RfcommModemStatus), modemStatus, sizeof(RfcommModemStatus));
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommSetModemStatusTsk, ctx);
if (ret != BT_SUCCESS) {
free(ctx);
}
return ret;
}
typedef struct {
uint16_t handle;
RfcommPortState state;
Event *event;
int result;
} RfcommGetPortStInfo;
static void RfcommGetPortStateTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommGetPortStInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
int ret = RfcommGetPortState(ctx->handle, &ctx->state);
ctx->result = ret;
if (ctx->event != NULL) {
EventSet(ctx->event);
}
}
/**
* @brief This function is used to obtain port related information.
* Currently, the amount of data sent and received by the port can be obtained.
*
* @param handle The channel(DLC)'s handle number
* @param state The port's information
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_GetPortState(uint16_t handle, RfcommPortState *state)
{
LOG_INFO("%{public}s handle:%hu", __func__, handle);
RfcommGetPortStInfo *ctx = malloc(sizeof(RfcommGetPortStInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
(void)memset_s(ctx, sizeof(RfcommGetPortStInfo), 0x00, sizeof(RfcommGetPortStInfo));
ctx->handle = handle;
ctx->event = EventCreate(true);
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommGetPortStateTsk, ctx);
if (ret != BT_SUCCESS) {
EventDelete(ctx->event);
free(ctx);
return ret;
}
EventWait(ctx->event, WAIT_TIME);
EventDelete(ctx->event);
(void)memcpy_s(state, sizeof(RfcommPortState), &ctx->state, sizeof(RfcommPortState));
ret = ctx->result;
free(ctx);
return ret;
}
/**
* @brief This function is used to get the payload packet sent by the peer from RFCOMM.
* After the caller finishes using this interface, it creates a packet reference or
* reads the payload buffer as needed, and must free the packet obtained from RFCOMM.
*
* @param handle The channel(DLC)'s handle number
* @param pkt The packet point for receiving data
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_Read(uint16_t handle, Packet **pkt)
{
LOG_INFO("%{public}s handle:%hu", __func__, handle);
RfcommReadLock();
int ret = RfcommRead(handle, pkt);
RfcommReadUnlock();
return ret;
}
typedef struct {
uint16_t handle;
Packet *pkt;
Event *event;
int result;
} RfcommWriteInfo;
static void RfcommWriteTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommWriteInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
int ret = RfcommWrite(ctx->handle, ctx->pkt);
ctx->result = ret;
if (ctx->event != NULL) {
EventSet(ctx->event);
}
}
/**
* @brief This function is used to write the data to be transmitted to the opposite end to RFCOMM.
*
* @param handle The channel(DLC)'s handle number
* @param pkt The packet for sending data
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_Write(uint16_t handle, Packet *pkt)
{
LOG_INFO("%{public}s handle:%hu", __func__, handle);
RfcommWriteInfo *ctx = malloc(sizeof(RfcommWriteInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
(void)memset_s(ctx, sizeof(RfcommWriteInfo), 0x00, sizeof(RfcommWriteInfo));
ctx->handle = handle;
ctx->pkt = pkt;
ctx->event = EventCreate(true);
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommWriteTsk, ctx);
if (ret != BT_SUCCESS) {
EventDelete(ctx->event);
free(ctx);
return ret;
}
EventWait(ctx->event, WAIT_TIME);
EventDelete(ctx->event);
ret = ctx->result;
free(ctx);
return ret;
}
typedef struct {
uint16_t handle;
Packet *pkt;
} RfcommSendTestCmdInfo;
static void RfcommSendTestCmdTsk(void *context)
{
LOG_INFO("%{public}s", __func__);
RfcommSendTestCmdInfo *ctx = context;
if (ctx == NULL) {
LOG_ERROR("%{public}s context is NULL.", __func__);
return;
}
RfcommSendTestCmd(ctx->handle, ctx->pkt);
PacketFree(ctx->pkt);
free(ctx);
}
/**
* @brief This function is used to send Test Command to the peer.
*
* @param handle The channel(DLC)'s handle number
* @param pkt The packet for sending data
* @return Returns RFCOMM_SUCCESS if the operation is successful, otherwise the operation fails.
* @since 6
*/
int RFCOMM_SendTestCmd(uint16_t handle, Packet *pkt)
{
LOG_INFO("%{public}s handle:%hu", __func__, handle);
RfcommSendTestCmdInfo *ctx = malloc(sizeof(RfcommSendTestCmdInfo));
if (ctx == NULL) {
return BT_NO_MEMORY;
}
(void)memset_s(ctx, sizeof(RfcommSendTestCmdInfo), 0x00, sizeof(RfcommSendTestCmdInfo));
ctx->handle = handle;
ctx->pkt = PacketRefMalloc(pkt);
int ret = BTM_RunTaskInProcessingQueue(PROCESSING_QUEUE_ID_RFCOMM, RfcommSendTestCmdTsk, ctx);
if (ret != BT_SUCCESS) {
PacketFree(ctx->pkt);
free(ctx);
}
return ret;
}
static void RFCOMM_Init(int traceLevel)
{
LOG_INFO("%{public}s", __func__);
(void)traceLevel;
return;
}
static void RFCOMM_Cleanup()
{
LOG_INFO("%{public}s", __func__);
return;
}
static Module g_rfcomm = {
.name = MODULE_NAME_RFCOMM,
.init = RFCOMM_Init,
.startup = RFCOMM_Startup,
.shutdown = RFCOMM_Shutdown,
.cleanup = RFCOMM_Cleanup,
.dependencies = {MODULE_NAME_L2CAP, MODULE_NAME_GAP},
};
MODULE_DECL(g_rfcomm)