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 }