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 bool g_serverNum[MAX_SERVER_COUNT] = {false};
19 
20 /**
21  * @brief This function is used to initialize rfcomm resources and
22  *        register the callback function to L2CAP.
23  *
24  */
RfcommInitialize()25 void RfcommInitialize()
26 {
27     LOG_INFO("%{public}s", __func__);
28 
29     for (uint8_t cnt = 0; cnt < MAX_SERVER_COUNT; cnt++) {
30         g_serverNum[cnt] = false;
31     }
32 
33     // Create list.
34     RfcommCreateSessionList();
35     RfcommCreateChannelList();
36     RfcommCreateServerList();
37 
38     // Register security to GAP.
39     RfcommRegisterSecurity();
40 
41     // Register to L2CAP.
42     RfcommRegisterL2cap();
43 }
44 
45 /**
46  * @brief This function is used to release rfcomm internal resources and
47  *        deregister the callback function to L2CAP.
48  *
49  */
RfcommFinalize()50 void RfcommFinalize()
51 {
52     LOG_INFO("%{public}s", __func__);
53 
54     for (uint8_t cnt = 0; cnt < MAX_SERVER_COUNT; cnt++) {
55         g_serverNum[cnt] = false;
56     }
57 
58     // Deregister from L2CAP.
59     RfcommDeregisterL2cap();
60 
61     // Deregister security from GAP.
62     RfcommDeregisterSecurity();
63 
64     // Free list.
65     RfcommDestroySessionList();
66     RfcommDestroyChannelList();
67     RfcommDestroyServerList();
68 }
69 
70 /**
71  * @brief The function is used to assign server numbers to individual servers.
72  *        Server number is used to register with the RFCOMM service interface, range is 1~30.
73  *        When the return value is 0, it means that there is no available server number.
74  *        This Server number shall be registered in the Service Discovery Database;
75  *        RFCOMM_SPEC_V12 #5.4
76  *
77  * @return Server number.0(unavailable number),1~30(available number)
78  */
RfcommAssignServerNum()79 uint8_t RfcommAssignServerNum()
80 {
81     LOG_INFO("%{public}s", __func__);
82 
83     uint8_t scn = 0;
84 
85     for (uint8_t index = 0; index < MAX_SERVER_COUNT; index++) {
86         if (g_serverNum[index] == true) {
87             continue;
88         }
89         g_serverNum[index] = true;
90         scn = index + 1;
91         break;
92     }
93 
94     return scn;
95 }
96 
97 /**
98  * @brief After close the server, free the server number.
99  *
100  * @param scn Server number.
101  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
102  */
RfcommFreeServerNum(uint8_t scn)103 int RfcommFreeServerNum(uint8_t scn)
104 {
105     LOG_INFO("%{public}s scn:%hhu", __func__, scn);
106 
107     if ((scn < 1) || (scn > MAX_SERVER_COUNT)) {
108         return RFCOMM_ERR_PARAM;
109     }
110 
111     g_serverNum[scn - 1] = false;
112 
113     return RFCOMM_SUCCESS;
114 }
115 
116 /**
117  * @brief The function is used by the client to establish a connection of the channel.
118  *
119  * @param reqInfo   Connection request information.
120  * @param handle    The handle of the channel created by rfcomm
121  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
122  */
RfcommConnectChannel(const RfcommConnectReqInfo * reqInfo,uint16_t * handle)123 int RfcommConnectChannel(const RfcommConnectReqInfo *reqInfo, uint16_t *handle)
124 {
125     LOG_INFO("%{public}s", __func__);
126 
127     // The valid range of server num is 1~30.
128     // If the incoming parameter scn is greater than 30, an exception will be returned.
129     if ((reqInfo->scn == 0) || (reqInfo->scn > MAX_SERVER_COUNT)) {
130         return RFCOMM_ERR_PARAM;
131     }
132 
133     // Find session by BT address.If the session does not exist, create the session.
134     RfcommSessionInfo *session = RfcommGetSessionByAddr(&(reqInfo->addr));
135     if (session == NULL) {
136         // If the session does not exist, create a session.
137         session = RfcommCreateSession(&(reqInfo->addr), 0, 0, true);
138         if (session == NULL) {
139             return RFCOMM_ERR_NO_RESOURCES;
140         }
141     }
142 
143     // Server applications on the noninitiating device are reachable on DLCIs 2,4,6,…,60;
144     // and server applications on the initiating device are reachable on DLCIs 3,5,7,…,61.
145     uint8_t dlci = session->isInitiator ? (reqInfo->scn << 1) : ((reqInfo->scn << 1) + 1);
146 
147     // Determine whether the channel has been created.
148     RfcommChannelInfo *channel = RfcommGetChannelByDlci(session, dlci);
149     if (channel != NULL) {
150         // Channel already exists.
151         *handle = channel->handle;
152         return RFCOMM_ALREADY_EXIST;
153     }
154 
155     RfcommCreateChannelInfo createChannelInfo;
156     createChannelInfo.session = session;
157     createChannelInfo.isServer = false;
158     createChannelInfo.dlci = dlci;
159     createChannelInfo.mtu = reqInfo->mtu;
160     createChannelInfo.eventMask = reqInfo->eventMask;
161     createChannelInfo.callback = reqInfo->callback;
162     createChannelInfo.context = reqInfo->context;
163 
164     // If the channel does not exist, create a channel.
165     channel = RfcommCreateChannel(&createChannelInfo);
166     if (channel == NULL) {
167         return RFCOMM_ERR_NO_RESOURCES;
168     }
169     *handle = channel->handle;
170 
171     return RfcommChannelEvtFsm(channel, EV_CHANNEL_SEND_OPEN_REQ, NULL);
172 }
173 
174 /**
175  * @brief The function is used for the server to register with RFCOMM and
176  *        wait for the client to connect.
177  *
178  * @param scn       The server's number.
179  * @param mtu       The maximum size of data received at a time.
180  * @param eventMask The collection of events followed by upper layers.
181  * @param callback  The callback function used by rfcomm to notify uppers of data or events.
182  * @param context   The content passed in from the upper layer.
183  *                  It will be brought back to the upper layer when callback is called.
184  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
185  */
RfcommRegisterServer(uint8_t scn,uint16_t mtu,uint32_t eventMask,RFCOMM_EventCallback callback,void * context)186 int RfcommRegisterServer(uint8_t scn, uint16_t mtu, uint32_t eventMask,
187                          RFCOMM_EventCallback callback, void *context)
188 {
189     LOG_INFO("%{public}s scn:%hhu", __func__, scn);
190 
191     RfcommServerInfo *server = NULL;
192 
193     // The valid range of server num is 1~30.
194     // If the incoming parameter scn is greater than 30, an exception will be returned.
195     if ((scn == 0) || (scn > MAX_SERVER_COUNT)) {
196         return RFCOMM_ERR_PARAM;
197     }
198 
199     // Determine whether the server has been registered.
200     server = RfcommGetServerByScn(scn);
201     if (server != NULL) {
202         return RFCOMM_ALREADY_EXIST;
203     }
204     // If it is not registered, proceed with the registration process.
205     server = RfcommCreateServer(scn, mtu, eventMask, callback, context);
206     if (server == NULL) {
207         return RFCOMM_ERR_NO_RESOURCES;
208     }
209 
210     return RFCOMM_SUCCESS;
211 }
212 
213 /**
214  * @brief The function is used to tell RFCOMM to accept the connection request when the server
215  *        receives the connection notification(eventId is RFCOMM_EVENT_CONNECT_INCOMING).
216  *        After receiving the response from the upper layer, RFCOMM notifies the client
217  *        of the peer device to accept the connection request.
218  *
219  * @param handle The channel(DLC)'s handle number
220  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
221  */
RfcommAcceptConnection(uint16_t handle)222 int RfcommAcceptConnection(uint16_t handle)
223 {
224     LOG_INFO("%{public}s handle:%hu", __func__, handle);
225 
226     RfcommChannelInfo *channel = RfcommGetChannelByHandle(handle);
227 
228     if (channel == NULL) {
229         return RFCOMM_ERR_PARAM;
230     }
231 
232     return RfcommChannelEvtFsm(channel, EV_CHANNEL_ACCEPT, NULL);
233 }
234 
235 /**
236  * @brief This function is used to tell RFCOMM to reject the connection request when the server
237  *        receives the connection notification(eventId is RFCOMM_EVENT_CONNECT_INCOMING).
238  *        After receiving the response from the upper layer, RFCOMM notifies the client
239  *        of the peer device to reject the connection request.
240  *
241  * @param handle The channel(DLC)'s handle number
242  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
243  */
RfcommRejectConnection(uint16_t handle)244 int RfcommRejectConnection(uint16_t handle)
245 {
246     LOG_INFO("%{public}s handle:%hu", __func__, handle);
247 
248     RfcommChannelInfo *channel = RfcommGetChannelByHandle(handle);
249 
250     if (channel == NULL) {
251         return RFCOMM_ERR_PARAM;
252     }
253 
254     return RfcommChannelEvtFsm(channel, EV_CHANNEL_REJECT, NULL);
255 }
256 
257 /**
258  * @brief The function is used to disconnect the specified channel.
259  *        RFCOMM_SPEC_V12 #5.2
260  *
261  * @param handle The channel(DLC)'s handle number
262  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
263  */
RfcommDisconnectChannel(uint16_t handle)264 int RfcommDisconnectChannel(uint16_t handle)
265 {
266     LOG_INFO("%{public}s handle:%hu", __func__, handle);
267 
268     RfcommChannelInfo *channel = RfcommGetChannelByHandle(handle);
269 
270     if (channel == NULL) {
271         return RFCOMM_ERR_PARAM;
272     }
273 
274     return RfcommChannelEvtFsm(channel, EV_CHANNEL_SEND_CLOSE_REQ, NULL);
275 }
276 
277 /**
278  * @brief When the server is shut down, call this function to
279  *        release the resources about the server held in RFCOMM.
280  *
281  * @param scn The server's number
282  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
283  */
RfcommDeregisterServer(uint8_t scn,bool isRemoveCallback)284 int RfcommDeregisterServer(uint8_t scn, bool isRemoveCallback)
285 {
286     LOG_INFO("%{public}s scn:%hhu", __func__, scn);
287 
288     RfcommServerInfo *server = RfcommGetServerByScn(scn);
289 
290     if (server != NULL) {
291         RfcommRemoveServer(server);
292     }
293 
294     // Remove callback from channel list and disconnect the channel.
295     if (isRemoveCallback) {
296         RfcommRemoveChannelCallback(scn);
297     }
298 
299     return RFCOMM_SUCCESS;
300 }
301 
302 /**
303  * @brief The function is used for set the remote port communication settings.
304  *        The command may be used before a new DLC is opened and shall be used
305  *        whenever the port settings change.
306  *        RFCOMM_SPEC_V12 #5.5.1
307  *
308  * @param handle The channel(DLC)'s handle number
309  * @param config Remote port negotiation parameters
310  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
311  */
RfcommSetPortConfig(uint16_t handle,const RfcommRemotePortConfig * config)312 int RfcommSetPortConfig(uint16_t handle, const RfcommRemotePortConfig *config)
313 {
314     LOG_INFO("%{public}s handle:%hu", __func__, handle);
315 
316     RfcommChannelInfo *channel = RfcommGetChannelByHandle(handle);
317 
318     if (channel == NULL) {
319         return RFCOMM_ERR_PARAM;
320     }
321 
322     return RfcommChannelEvtFsm(channel, EV_CHANNEL_SEND_RPN_CMD, (void *)config);
323 }
324 
325 /**
326  * @brief The function is used to obtain the remote port negotiation information
327  *        of the peer device.
328  *
329  * @param handle The channel(DLC)'s handle number
330  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
331  */
RfcommReqPortConfig(uint16_t handle)332 int RfcommReqPortConfig(uint16_t handle)
333 {
334     LOG_INFO("%{public}s handle:%hu", __func__, handle);
335 
336     RfcommChannelInfo *channel = RfcommGetChannelByHandle(handle);
337 
338     if (channel == NULL) {
339         return RFCOMM_ERR_PARAM;
340     }
341 
342     return RfcommChannelEvtFsm(channel, EV_CHANNEL_SEND_RPN_REQ, NULL);
343 }
344 
345 /**
346  * @brief The function is used for indication of remote port line status.
347  *        RFCOMM_SPEC_V12 #5.5.2
348  *
349  * @param handle     The channel(DLC)'s handle number
350  * @param lineStatus Remote line status
351  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
352  */
RfcommSendRemoteLineStatus(uint16_t handle,const RfcommRemoteLineStatus * lineStatus)353 int RfcommSendRemoteLineStatus(uint16_t handle, const RfcommRemoteLineStatus *lineStatus)
354 {
355     LOG_INFO("%{public}s handle:%hu", __func__, handle);
356 
357     RfcommChannelInfo *channel = RfcommGetChannelByHandle(handle);
358 
359     if (channel == NULL) {
360         return RFCOMM_ERR_PARAM;
361     }
362 
363     return RfcommChannelEvtFsm(channel, EV_CHANNEL_SEND_RLS_REQ, (void *)lineStatus);
364 }
365 
366 /**
367  * @brief The function is used to convey the RS-232 control signals and the break signal.
368  *        RFCOMM_SPEC_V12 #2.2
369  *
370  * @param handle      The channel(DLC)'s handle number
371  * @param modemStatus Control signals and the break signal
372  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
373  */
RfcommSetModemStatus(uint16_t handle,const RfcommModemStatus * modemStatus)374 int RfcommSetModemStatus(uint16_t handle, const RfcommModemStatus *modemStatus)
375 {
376     LOG_INFO("%{public}s handle:%hu", __func__, handle);
377 
378     RfcommChannelInfo *channel = RfcommGetChannelByHandle(handle);
379 
380     if (channel == NULL) {
381         return RFCOMM_ERR_PARAM;
382     }
383 
384     return RfcommChannelEvtFsm(channel, EV_CHANNEL_SEND_MSC_REQ, (void *)modemStatus);
385 }
386 
387 /**
388  * @brief This function is used to obtain port related information.
389  *        Currently, the amount of data sent and received by the port can be obtained.
390  *
391  * @param handle The channel(DLC)'s handle number
392  * @param state  The port's information
393  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
394  */
RfcommGetPortState(uint16_t handle,RfcommPortState * state)395 int RfcommGetPortState(uint16_t handle, RfcommPortState *state)
396 {
397     LOG_INFO("%{public}s handle:%hu", __func__, handle);
398 
399     RfcommChannelInfo *channel = RfcommGetChannelByHandle(handle);
400 
401     if (channel == NULL) {
402         return RFCOMM_ERR_PARAM;
403     }
404 
405     state->receivedBytes = channel->receivedBytes;
406     state->transmittedBytes = channel->transmittedBytes;
407 
408     return RFCOMM_SUCCESS;
409 }
410 
411 /**
412  * @brief This function is used to get the payload packet sent by the peer from RFCOMM.
413  *        After the caller finishes using this interface, it creates a packet reference or
414  *        reads the payload buffer as needed, and must free the packet obtained from RFCOMM.
415  *
416  * @param handle The channel(DLC)'s handle number
417  * @param pkt    The packet point for receiving data
418  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
419  */
RfcommRead(uint16_t handle,Packet ** pkt)420 int RfcommRead(uint16_t handle, Packet **pkt)
421 {
422     LOG_INFO("%{public}s handle:%hu", __func__, handle);
423 
424     ListNode *node = NULL;
425     RfcommChannelInfo *channel = RfcommGetChannelByHandle(handle);
426 
427     if (channel == NULL) {
428         return RFCOMM_ERR_PARAM;
429     }
430     node = ListGetFirstNode(channel->recvQueue);
431     if (node == NULL) {
432         *pkt = NULL;
433         return RFCOMM_NO_DATA;
434     }
435 
436     *pkt = (Packet *)ListGetNodeData(node);
437     // Add received data bytes value.
438     channel->receivedBytes += PacketPayloadSize(*pkt);
439     // Remove first node.
440     ListRemoveFirst(channel->recvQueue);
441 
442     // Local can receive more data, send flow control to peer.
443     RfcommSetFlcToPeer(channel, true);
444 
445     return RFCOMM_SUCCESS;
446 }
447 
448 /**
449  * @brief This function is used to write the data to be transmitted to the opposite end to RFCOMM.
450  *
451  * @param handle The channel(DLC)'s handle number
452  * @param pkt    The packet for sending data
453  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
454  */
RfcommWrite(uint16_t handle,Packet * pkt)455 int RfcommWrite(uint16_t handle, Packet *pkt)
456 {
457     LOG_INFO("%{public}s handle:%hu", __func__, handle);
458 
459     size_t len = PacketPayloadSize(pkt);
460     RfcommChannelInfo *channel = RfcommGetChannelByHandle(handle);
461 
462     if (channel == NULL) {
463         LOG_ERROR("%{public}s:Channel does not exist.", __func__);
464         return RFCOMM_ERR_PARAM;
465     }
466 
467     if (len > channel->peerMtu) {
468         LOG_ERROR("%{public}s:Packet length(%zu) is over MTU.", __func__, len);
469         return RFCOMM_OVERRUN;
470     }
471 
472     return RfcommChannelEvtFsm(channel, EV_CHANNEL_WRITE_DATA, pkt);
473 }
474 
475 /**
476  * @brief This function is used to send Test Command to the peer.
477  *
478  * @param handle The channel(DLC)'s handle number
479  * @param pkt    The packet for sending data
480  * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
481  */
RfcommSendTestCmd(uint16_t handle,Packet * pkt)482 int RfcommSendTestCmd(uint16_t handle, Packet *pkt)
483 {
484     LOG_INFO("%{public}s handle:%hu", __func__, handle);
485 
486     size_t len = PacketPayloadSize(pkt);
487     RfcommChannelInfo *channel = RfcommGetChannelByHandle(handle);
488 
489     if (channel == NULL) {
490         LOG_ERROR("%{public}s:The channel does not exist.", __func__);
491         return RFCOMM_ERR_PARAM;
492     }
493 
494     if (len > channel->peerMtu) {
495         LOG_ERROR("%{public}s:Test cmd packet length(%zu) is over MTU.", __func__, len);
496         return RFCOMM_OVERRUN;
497     }
498 
499     return RfcommSendUihTest(channel->session, true, pkt);
500 }