1 /*
2 * Copyright (C) 2021-2022 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 typedef int (*SessionActionFunc)(RfcommSessionInfo *session, const void *data);
19 typedef struct {
20 RfcommSessionEvent eventId;
21 SessionActionFunc fn;
22 } RfcommSessionEvtAction;
23
24 static int RfcommOpenSession(RfcommSessionInfo *session, const void *data);
25 static int RfcommCloseSession(RfcommSessionInfo *session, const void *data);
26 static int RfcommRecvSessionSecurityRslt(RfcommSessionInfo *session, const void *data);
27 static int RfcommRecvConnectReq(RfcommSessionInfo *session, const void *data);
28 static int RfcommRecvReqConnectRslt(RfcommSessionInfo *session, const void *data);
29 static int RfcommRecvConnectRsp(RfcommSessionInfo *session, const void *data);
30 static int RfcommRecvConfigReq(RfcommSessionInfo *session, const void *data);
31 static int RfcommRecvConfigRsp(RfcommSessionInfo *session, const void *data);
32 static int RfcommRecvDisconnectReq(RfcommSessionInfo *session, const void *data);
33 static int RfcommRecvSabm0(RfcommSessionInfo *session, const void *data);
34 static int RfcommRecvDisc0(RfcommSessionInfo *session, const void *data);
35 static int RfcommRecvUa0(RfcommSessionInfo *session, const void *data);
36 static int RfcommRecvDm0(RfcommSessionInfo *session, const void *data);
37 static int RfcommRecvFconReq(RfcommSessionInfo *session, const void *data);
38 static int RfcommRecvFconRsp(RfcommSessionInfo *session, const void *data);
39 static int RfcommRecvFcoffReq(RfcommSessionInfo *session, const void *data);
40 static int RfcommRecvFcoffRsp(RfcommSessionInfo *session, const void *data);
41 static int RfcommRecvTestReq(RfcommSessionInfo *session, const void *data);
42 static int RfcommRecvTestRsp(RfcommSessionInfo *session, const void *data);
43 static int RfcommRecvNsc(RfcommSessionInfo *session, const void *data);
44 static int RfcommRecvLinkLoss(RfcommSessionInfo *session, const void *data);
45 static int RfcommRecvTimeOut(RfcommSessionInfo *session, const void *data);
46 static int RfcommRestartSession(RfcommSessionInfo *session);
47 static int RfcommAcceptPeerConnectReq(RfcommSessionInfo *session);
48
49 static RfcommSessionEvtAction g_sessionEvtActTbl[EV_SESSION_EV_MAX] = {
50 {EV_SESSION_SEND_OPEN_REQ, RfcommOpenSession},
51 {EV_SESSION_SEND_CLOSE_REQ, RfcommCloseSession},
52 {EV_SESSION_RECV_SECURITY_RESULT, RfcommRecvSessionSecurityRslt},
53 {EV_SESSION_RECV_REQ_CONNECT_RESULT, RfcommRecvReqConnectRslt},
54 {EV_SESSION_RECV_CONNECT_REQ, RfcommRecvConnectReq},
55 {EV_SESSION_RECV_CONNECT_RSP, RfcommRecvConnectRsp},
56 {EV_SESSION_RECV_CONFIG_REQ, RfcommRecvConfigReq},
57 {EV_SESSION_RECV_CONFIG_RSP, RfcommRecvConfigRsp},
58 {EV_SESSION_RECV_DISCONNECT_REQ, RfcommRecvDisconnectReq},
59 {EV_SESSION_RECV_SABM0, RfcommRecvSabm0},
60 {EV_SESSION_RECV_DISC0, RfcommRecvDisc0},
61 {EV_SESSION_RECV_UA0, RfcommRecvUa0},
62 {EV_SESSION_RECV_DM0, RfcommRecvDm0},
63 {EV_SESSION_RECV_FCON_REQ, RfcommRecvFconReq},
64 {EV_SESSION_RECV_FCON_RSP, RfcommRecvFconRsp},
65 {EV_SESSION_RECV_FCOFF_REQ, RfcommRecvFcoffReq},
66 {EV_SESSION_RECV_FCOFF_RSP, RfcommRecvFcoffRsp},
67 {EV_SESSION_RECV_TEST_REQ, RfcommRecvTestReq},
68 {EV_SESSION_RECV_TEST_RSP, RfcommRecvTestRsp},
69 {EV_SESSION_RECV_NSC, RfcommRecvNsc},
70 {EV_SESSION_RECV_LINK_LOSS, RfcommRecvLinkLoss},
71 {EV_SESSION_TIMEOUT, RfcommRecvTimeOut}
72 };
73
74 /**
75 * @brief State machine for handling events related to session.
76 *
77 * @param session The pointer of the session in the session list.
78 * @param event The event id.
79 * @param data Data related to the event.
80 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
81 */
RfcommSessionEvtFsm(RfcommSessionInfo * session,RfcommSessionEvent event,const void * data)82 int RfcommSessionEvtFsm(RfcommSessionInfo *session, RfcommSessionEvent event, const void *data)
83 {
84 LOG_INFO("%{public}s", __func__);
85
86 int ret = 0;
87
88 for (int cnt = 0; cnt < EV_SESSION_EV_MAX; cnt++) {
89 if (g_sessionEvtActTbl[cnt].eventId == event) {
90 ret = g_sessionEvtActTbl[cnt].fn(session, data);
91 break;
92 }
93 }
94
95 return ret;
96 }
97
98 /**
99 * @brief Processing after receiving connect session request.
100 *
101 * @param session The pointer of the session in the session list.
102 * @param data Data related to the event.
103 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
104 */
RfcommOpenSession(RfcommSessionInfo * session,const void * data)105 int RfcommOpenSession(RfcommSessionInfo *session, const void *data)
106 {
107 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
108
109 if (data == NULL) {
110 return RFCOMM_ERR_PARAM;
111 }
112
113 int ret = 0;
114 uint8_t scn = *(uint8_t *)data;
115
116 switch (session->sessionState) {
117 case ST_SESSION_CLOSED:
118 session->sessionState = ST_SESSION_INITIATOR_WAIT_SECURITY_RESULT;
119 ret = RfcommCheckSessionSecurity(session, scn, false);
120 break;
121 case ST_SESSION_DISC0_REQ_WAIT_UA0:
122 // fall-through
123 case ST_SESSION_CLOSING:
124 // If a connection request is received during the closing process,
125 // the status is set to ST_SESSION_WAIT_RESTART, and after the UA response is received,
126 // the reconnection process is performed.
127 session->sessionState = ST_SESSION_WAIT_RESTART;
128 break;
129 default:
130 break;
131 }
132
133 return ret;
134 }
135
RfcommRecvReqConnectRslt(RfcommSessionInfo * session,const void * data)136 int RfcommRecvReqConnectRslt(RfcommSessionInfo *session, const void *data)
137 {
138 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
139
140 if (data == NULL) {
141 return RFCOMM_ERR_PARAM;
142 }
143
144 RfcommReqConnectRslt connectRslt;
145 (void)memcpy_s(&connectRslt, sizeof(RfcommReqConnectRslt), data, sizeof(RfcommReqConnectRslt));
146
147 if (session->sessionState != ST_SESSION_WAIT_CONNECT_REQ_RESULT) {
148 return RFCOMM_SUCCESS;
149 }
150
151 LOG_INFO("%{public}s pendingL2capId :%hu.", __func__, session->pendingL2capId);
152 if (session->pendingL2capId != 0) {
153 RfcommStopSessionTimer(session);
154 if ((connectRslt.result == RFCOMM_SUCCESS) && (connectRslt.lcid != 0)) {
155 RfcommSendDisconnectReq(connectRslt.lcid);
156 }
157 // Accept peer's connection request.
158 return RfcommAcceptPeerConnectReq(session);
159 }
160
161 if ((connectRslt.result != RFCOMM_SUCCESS) || (connectRslt.lcid == 0)) {
162 // Notify all channels on the session that connection failed.
163 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
164 // Remove all channels on session.
165 RfcommRemoveAllChannelOnSession(session);
166 // Destroy session from session list.
167 RfcommRemoveSession(session);
168 } else {
169 session->l2capId = connectRslt.lcid;
170 session->sessionState = ST_SESSION_WAIT_CONNECT_RSP;
171 }
172
173 return RFCOMM_SUCCESS;
174 }
175
176 /**
177 * @brief Processing after receiving connect response from L2CAP.
178 *
179 * @param session The pointer of the session in the session list.
180 * @param data Data related to the event.
181 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
182 */
RfcommRecvConnectRsp(RfcommSessionInfo * session,const void * data)183 int RfcommRecvConnectRsp(RfcommSessionInfo *session, const void *data)
184 {
185 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
186
187 if (data == NULL) {
188 return RFCOMM_ERR_PARAM;
189 }
190
191 uint16_t result = *(uint16_t *)data;
192 L2capConfigInfo config;
193 (void)memset_s(&config, sizeof(config), 0, sizeof(config));
194
195 if (session->sessionState != ST_SESSION_WAIT_CONNECT_RSP) {
196 LOG_DEBUG("%{public}s:Session state is not WAIT_CONNECT_RSP.", __func__);
197 return RFCOMM_FAILED;
198 }
199
200 LOG_INFO("%{public}s pendingL2capId:%hu.", __func__, session->pendingL2capId);
201 if (result != L2CAP_CONNECTION_SUCCESSFUL) {
202 if (session->pendingL2capId != 0) {
203 RfcommStopSessionTimer(session);
204 // Accept peer's connection request.
205 return RfcommAcceptPeerConnectReq(session);
206 }
207 // Notify all channels on the session that connection failed.
208 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
209 // Remove all channels on session.
210 RfcommRemoveAllChannelOnSession(session);
211 // Destroy session.
212 RfcommRemoveSession(session);
213
214 return RFCOMM_SUCCESS;
215 }
216
217 if (session->pendingL2capId != 0) {
218 RfcommStopSessionTimer(session);
219 RfcommSendConnectRsp(session->pendingL2capId, session->pendingId, L2CAP_NO_RESOURCES_AVAILABLE, 0);
220 session->pendingL2capId = 0;
221 session->pendingId = 0;
222 }
223
224 config.rfc.mode = 0; // Basic mode
225 config.flushTimeout = 0xFFFF;
226 config.mtu = session->l2capLocalMtu;
227 config.fcs = 0x01;
228
229 session->sessionState = ST_SESSION_INITIATOR_WAIT_CONFIG_REQ_AND_RSP;
230
231 return RfcommSendConfigReq(session->l2capId, &config);
232 }
233
234 /**
235 * @brief Processing after receiving config response from L2CAP.
236 *
237 * @param session The pointer of the session in the session list.
238 * @param data Data related to the event.
239 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
240 */
RfcommRecvConfigRsp(RfcommSessionInfo * session,const void * data)241 int RfcommRecvConfigRsp(RfcommSessionInfo *session, const void *data)
242 {
243 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
244
245 if (data == NULL) {
246 return RFCOMM_ERR_PARAM;
247 }
248
249 int ret = 0;
250 RfcommConfigRspInfo *configResult = (RfcommConfigRspInfo *)data;
251
252 if (configResult->result != L2CAP_SUCCESS) {
253 RfcommSendDisconnectReq(session->l2capId);
254 // Notify all channels on the session that connection failed.
255 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
256 // Remove all channels on session.
257 RfcommRemoveAllChannelOnSession(session);
258 // Destroy session.
259 RfcommRemoveSession(session);
260
261 return RFCOMM_SUCCESS;
262 }
263
264 switch (session->sessionState) {
265 case ST_SESSION_INITIATOR_WAIT_CONFIG_REQ_AND_RSP:
266 session->sessionState = ST_SESSION_INITIATOR_WAIT_CONFIG_REQ;
267 break;
268 case ST_SESSION_INITIATOR_WAIT_CONFIG_RSP:
269 ret = RfcommSendSabm(session, CONTROL_DLCI);
270 session->sessionState = ST_SESSION_SABM0_REQ_WAIT_UA0;
271 RfcommStartSessionTimer(session, T1_SABM_DISC);
272 break;
273 case ST_SESSION_RESPONDER_WAIT_CONFIG_REQ_AND_RSP:
274 session->sessionState = ST_SESSION_RESPONDER_WAIT_CONFIG_REQ;
275 break;
276 case ST_SESSION_RESPONDER_WAIT_CONFIG_RSP:
277 session->sessionState = ST_SESSION_WAIT_SABM0;
278 break;
279 default:
280 break;
281 }
282
283 return ret;
284 }
285
286 /**
287 * @brief Processing after receiving config request from L2CAP.
288 *
289 * @param session The pointer of the session in the session list.
290 * @param data Data related to the event.
291 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
292 */
RfcommRecvConfigReq(RfcommSessionInfo * session,const void * data)293 int RfcommRecvConfigReq(RfcommSessionInfo *session, const void *data)
294 {
295 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
296
297 if (data == NULL) {
298 return RFCOMM_ERR_PARAM;
299 }
300
301 RfcommConfigReqInfo reqInfo;
302 (void)memcpy_s(&reqInfo, sizeof(RfcommConfigReqInfo), (RfcommConfigReqInfo *)data, sizeof(RfcommConfigReqInfo));
303
304 session->l2capPeerMtu = reqInfo.cfg.mtu;
305
306 if (reqInfo.cfg.rfc.mode != 0) {
307 LOG_DEBUG("%{public}s mode is not basic mode, reconfig.", __func__);
308
309 (void)memset_s(&reqInfo.cfg, sizeof(L2capConfigInfo), 0x00, sizeof(L2capConfigInfo));
310 reqInfo.cfg.rfc.mode = 0;
311 reqInfo.cfg.flushTimeout = 0xFFFF;
312 reqInfo.cfg.fcs = 0x01;
313 reqInfo.cfg.mtu = session->l2capPeerMtu;
314
315 return RfcommSendConfigRsp(session->l2capId, reqInfo.id, &reqInfo.cfg, L2CAP_UNACCEPTABLE_PARAMETERS);
316 }
317
318 int ret = RfcommSendConfigRsp(session->l2capId, reqInfo.id, &reqInfo.cfg, 0);
319
320 switch (session->sessionState) {
321 case ST_SESSION_INITIATOR_WAIT_CONFIG_REQ_AND_RSP:
322 session->sessionState = ST_SESSION_INITIATOR_WAIT_CONFIG_RSP;
323 break;
324 case ST_SESSION_INITIATOR_WAIT_CONFIG_REQ:
325 ret = RfcommSendSabm(session, CONTROL_DLCI);
326 session->sessionState = ST_SESSION_SABM0_REQ_WAIT_UA0;
327 RfcommStartSessionTimer(session, T1_SABM_DISC);
328 break;
329 case ST_SESSION_RESPONDER_WAIT_CONFIG_REQ_AND_RSP:
330 session->sessionState = ST_SESSION_RESPONDER_WAIT_CONFIG_RSP;
331 break;
332 case ST_SESSION_RESPONDER_WAIT_CONFIG_REQ:
333 session->sessionState = ST_SESSION_WAIT_SABM0;
334 break;
335 default:
336 break;
337 }
338 return ret;
339 }
340
341 /**
342 * @brief Processing after receiving UA(DLCI0) response from peer.
343 *
344 * @param session The pointer of the session in the session list.
345 * @param data Data related to the event.
346 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
347 */
RfcommRecvUa0(RfcommSessionInfo * session,const void * data)348 int RfcommRecvUa0(RfcommSessionInfo *session, const void *data)
349 {
350 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
351
352 (void)data;
353 int ret = 0;
354
355 switch (session->sessionState) {
356 case ST_SESSION_SABM0_REQ_WAIT_UA0:
357 session->sessionState = ST_SESSION_CONNECTED;
358 // Stop timer.
359 RfcommStopSessionTimer(session);
360 // After the session is successfully connected,
361 // connect all links under the session.
362 RfcommOpenAllChannelOnSession(session);
363 break;
364 case ST_SESSION_DISC0_REQ_WAIT_UA0:
365 // Stop timer.
366 RfcommStopSessionTimer(session);
367 // L2CAP disconnect.
368 ret = RfcommSendDisconnectReq(session->l2capId);
369 // Remove all channels on session.
370 RfcommRemoveAllChannelOnSession(session);
371 // Destroy session.
372 RfcommRemoveSession(session);
373 break;
374 case ST_SESSION_WAIT_RESTART:
375 // Stop timer.
376 RfcommStopSessionTimer(session);
377 // L2CAP disconnect.
378 RfcommSendDisconnectReq(session->l2capId);
379 // Restart the session, init the session information first.
380 ret = RfcommRestartSession(session);
381 break;
382 default:
383 break;
384 }
385 return ret;
386 }
387
388 /**
389 * @brief Processing after receiving connect request from L2CAP.
390 *
391 * @param session The pointer of the session in the session list.
392 * @param data Data related to the event.
393 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
394 */
RfcommRecvConnectReq(RfcommSessionInfo * session,const void * data)395 int RfcommRecvConnectReq(RfcommSessionInfo *session, const void *data)
396 {
397 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
398
399 if (data == NULL) {
400 return RFCOMM_ERR_PARAM;
401 }
402
403 int ret = 0;
404 RfcommRecvConnectedInfo connectedInfo;
405 (void)memcpy_s(&connectedInfo, sizeof(RfcommRecvConnectedInfo), data, sizeof(RfcommRecvConnectedInfo));
406
407 switch (session->sessionState) {
408 case ST_SESSION_INITIATOR_WAIT_SECURITY_RESULT:
409 session->id = connectedInfo.id;
410 session->l2capId = connectedInfo.lcid;
411 session->isInitiator = false;
412 RfcommUpdateChannelDirectionBit(session, false);
413 // fall-through
414 case ST_SESSION_CLOSED:
415 session->sessionState = ST_SESSION_RESPONDER_WAIT_SECURITY_RESULT;
416 ret = RfcommCheckSessionSecurity(session, 0, true);
417 break;
418 case ST_SESSION_WAIT_CONNECT_REQ_RESULT:
419 // fall-through
420 case ST_SESSION_WAIT_CONNECT_RSP:
421 session->pendingL2capId = connectedInfo.lcid;
422 session->pendingId = connectedInfo.id;
423 uint32_t randomNum = RandomGenerate();
424 uint8_t timer = randomNum % RFCOMM_NUM_TEN;
425 RfcommStartSessionTimer(session, timer);
426 break;
427 default:
428 ret = RfcommSendConnectRsp(session->l2capId, session->id, L2CAP_NO_RESOURCES_AVAILABLE, 0);
429 break;
430 }
431
432 return ret;
433 }
434
435 /**
436 * @brief Processing after receiving SABM(DLCI0) request from peer.
437 *
438 * @param session The pointer of the session in the session list.
439 * @param data Data related to the event.
440 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
441 */
RfcommRecvSabm0(RfcommSessionInfo * session,const void * data)442 int RfcommRecvSabm0(RfcommSessionInfo *session, const void *data)
443 {
444 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
445
446 (void)data;
447
448 if (session->sessionState != ST_SESSION_WAIT_SABM0) {
449 LOG_DEBUG("%{public}s:Session state is not WAIT_SABM0.", __func__);
450 return RFCOMM_FAILED;
451 }
452
453 int ret = RfcommSendUa(session, CONTROL_DLCI);
454 session->sessionState = ST_SESSION_CONNECTED;
455 // After the session is successfully connected,
456 // connect all links under the session.
457 RfcommOpenAllChannelOnSession(session);
458 return ret;
459 }
460
461 /**
462 * @brief Processing after receiving DISC(DLCI0) request from peer.
463 *
464 * @param session The pointer of the session in the session list.
465 * @param data Data related to the event.
466 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
467 */
RfcommRecvDisc0(RfcommSessionInfo * session,const void * data)468 int RfcommRecvDisc0(RfcommSessionInfo *session, const void *data)
469 {
470 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
471
472 (void)data;
473 int ret;
474 bool sessionValid = false;
475
476 switch (session->sessionState) {
477 case ST_SESSION_SABM0_REQ_WAIT_UA0:
478 session->sessionState = ST_SESSION_CLOSING;
479 ret = RfcommSendUa(session, CONTROL_DLCI);
480 // Notify all channels on the session that connection failed.
481 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
482 // Remove all channels on session.
483 RfcommRemoveAllChannelOnSession(session);
484 break;
485 case ST_SESSION_DISC0_REQ_WAIT_UA0:
486 ret = RfcommSendUa(session, CONTROL_DLCI);
487 break;
488 case ST_SESSION_CONNECTED:
489 session->sessionState = ST_SESSION_CLOSING;
490 ret = RfcommSendUa(session, CONTROL_DLCI);
491 // Delete all channels on the session(except the channel to be connected).
492 RfcommRemoveInvalidChannelOnSession(session);
493 // Check if the session is valid.
494 sessionValid = RfcommCheckSessionValid(session);
495 if (sessionValid) {
496 // If there are channels to be connected, set RESTART of session's state.
497 session->sessionState = ST_SESSION_WAIT_RESTART;
498 RfcommResetAllChannelOnSession(session);
499 }
500 break;
501 default:
502 ret = RfcommSendDm(session, CONTROL_DLCI, true);
503 break;
504 }
505
506 return ret;
507 }
508
509 /**
510 * @brief Processing after receiving link loss notification from L2CAP.
511 *
512 * @param session The pointer of the session in the session list.
513 * @param data Data related to the event.
514 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
515 */
RfcommRecvLinkLoss(RfcommSessionInfo * session,const void * data)516 int RfcommRecvLinkLoss(RfcommSessionInfo *session, const void *data)
517 {
518 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
519
520 if (data == NULL) {
521 return RFCOMM_ERR_PARAM;
522 }
523
524 uint8_t reason = *(uint8_t *)data;
525
526 if (reason == L2CAP_STATE_COLLISION) {
527 LOG_DEBUG("%{public}s Connect request error.Retry!", __func__);
528 return RfcommRestartSession(session);
529 }
530
531 switch (session->sessionState) {
532 case ST_SESSION_CONNECTED:
533 // Notify all channels on the session that disconnection.
534 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_DISCONNECTED);
535 break;
536 default:
537 // Stop timer.
538 RfcommStopSessionTimer(session);
539 // Notify all channels on the session that connection failed.
540 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
541 break;
542 }
543 // Remove all channels on session.
544 RfcommRemoveAllChannelOnSession(session);
545 // Destroy session.
546 RfcommRemoveSession(session);
547
548 return RFCOMM_SUCCESS;
549 }
550
551 /**
552 * @brief Processing after receiving the request to disconnect session from L2CAP.
553 *
554 * @param session The pointer of the session in the session list.
555 * @param data Data related to the event.
556 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
557 */
RfcommRecvDisconnectReq(RfcommSessionInfo * session,const void * data)558 int RfcommRecvDisconnectReq(RfcommSessionInfo *session, const void *data)
559 {
560 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
561
562 (void)data;
563
564 if (session->sessionState == ST_SESSION_WAIT_RESTART) {
565 // Restart the session, init the session information first.
566 return RfcommRestartSession(session);
567 }
568
569 // Notify all channels on the session that disconnection.
570 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_DISCONNECTED);
571 // Remove all channels on session.
572 RfcommRemoveAllChannelOnSession(session);
573 // Destroy session.
574 RfcommRemoveSession(session);
575
576 return RFCOMM_SUCCESS;
577 }
578
579 /**
580 * @brief The processing after receiving the request to close the session.
581 * When all channels on the session are disconnected, perform this process.
582 *
583 * @param session The pointer of the session in the session list.
584 * @param data Data related to the event.
585 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
586 */
RfcommCloseSession(RfcommSessionInfo * session,const void * data)587 int RfcommCloseSession(RfcommSessionInfo *session, const void *data)
588 {
589 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
590
591 (void)data;
592 int ret = 0;
593
594 switch (session->sessionState) {
595 case ST_SESSION_WAIT_CONNECT_RSP:
596 // fall-through
597 case ST_SESSION_INITIATOR_WAIT_CONFIG_REQ_AND_RSP:
598 // fall-through
599 case ST_SESSION_INITIATOR_WAIT_CONFIG_REQ:
600 // fall-through
601 case ST_SESSION_INITIATOR_WAIT_CONFIG_RSP:
602 // fall-through
603 case ST_SESSION_SABM0_REQ_WAIT_UA0:
604 // Stop timer.
605 RfcommStopSessionTimer(session);
606 ret = RfcommSendDisconnectReq(session->l2capId);
607 // Remove all channels on session.
608 RfcommRemoveAllChannelOnSession(session);
609 // Destroy session.
610 RfcommRemoveSession(session);
611 break;
612 case ST_SESSION_CONNECTED:
613 ret = RfcommSendDisc(session, CONTROL_DLCI);
614 session->sessionState = ST_SESSION_DISC0_REQ_WAIT_UA0;
615 RfcommStartSessionTimer(session, T1_SABM_DISC);
616 break;
617 default:
618 break;
619 }
620 return ret;
621 }
622
623 /**
624 * @brief The processing after receiving the DM(DLCI0) response from peer.
625 *
626 * @param session The pointer of the session in the session list.
627 * @param data Data related to the event.
628 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
629 */
RfcommRecvDm0(RfcommSessionInfo * session,const void * data)630 int RfcommRecvDm0(RfcommSessionInfo *session, const void *data)
631 {
632 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
633
634 (void)data;
635 int ret = 0;
636
637 switch (session->sessionState) {
638 case ST_SESSION_SABM0_REQ_WAIT_UA0:
639 // Stop timer.
640 RfcommStopSessionTimer(session);
641 ret = RfcommSendDisconnectReq(session->l2capId);
642 // Notify all channels on the session that connection failed.
643 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
644 break;
645 case ST_SESSION_DISC0_REQ_WAIT_UA0:
646 // Stop timer.
647 RfcommStopSessionTimer(session);
648 ret = RfcommSendDisconnectReq(session->l2capId);
649 break;
650 case ST_SESSION_WAIT_RESTART:
651 // Stop timer.
652 RfcommStopSessionTimer(session);
653 // L2CAP disconnect.
654 RfcommSendDisconnectReq(session->l2capId);
655 // Restart the session, init the session information first.
656 return RfcommRestartSession(session);
657 default:
658 break;
659 }
660
661 // Remove all channels on session.
662 RfcommRemoveAllChannelOnSession(session);
663 // Destroy session.
664 RfcommRemoveSession(session);
665
666 return ret;
667 }
668
669 /**
670 * @brief The processing after receiving timeout notification.
671 *
672 * @param session The pointer of the session in the session list.
673 * @param data Data related to the event.
674 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
675 */
RfcommRecvTimeOut(RfcommSessionInfo * session,const void * data)676 int RfcommRecvTimeOut(RfcommSessionInfo *session, const void *data)
677 {
678 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
679
680 (void)data;
681 int ret = 0;
682
683 switch (session->sessionState) {
684 case ST_SESSION_SABM0_REQ_WAIT_UA0:
685 ret = RfcommSendDisconnectReq(session->l2capId);
686 // Notify all channels on the session that connection failed.
687 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
688 // Remove all channels on session.
689 RfcommRemoveAllChannelOnSession(session);
690 // Destroy session.
691 RfcommRemoveSession(session);
692 break;
693 case ST_SESSION_WAIT_SABM0:
694 break;
695 case ST_SESSION_DISC0_REQ_WAIT_UA0:
696 ret = RfcommSendDisconnectReq(session->l2capId);
697 // Remove all channels on session.
698 RfcommRemoveAllChannelOnSession(session);
699 // Destroy session.
700 RfcommRemoveSession(session);
701 break;
702 case ST_SESSION_WAIT_RESTART:
703 // L2CAP disconnect.
704 RfcommSendDisconnectReq(session->l2capId);
705 // Restart the session, init the session information first.
706 ret = RfcommRestartSession(session);
707 break;
708 case ST_SESSION_CONNECTED:
709 // Notify all channels that DLC is disconnected.
710 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_DISCONNECTED);
711 // Remove all channels on session.
712 RfcommRemoveAllChannelOnSession(session);
713 // The default action performed on timeouts is to close down the multiplexer session.
714 ret = RfcommSendDisc(session, CONTROL_DLCI);
715 session->sessionState = ST_SESSION_DISC0_REQ_WAIT_UA0;
716 RfcommStartSessionTimer(session, T1_SABM_DISC);
717 break;
718 case ST_SESSION_WAIT_CONNECT_RSP:
719 if (session->pendingL2capId != 0) {
720 // L2CAP disconnect.
721 RfcommSendDisconnectReq(session->l2capId);
722 // Accept peer's connection request.
723 ret = RfcommAcceptPeerConnectReq(session);
724 }
725 break;
726 default:
727 break;
728 }
729
730 return ret;
731 }
732
733 /**
734 * @brief The processing after receiving FCON request from peer.
735 *
736 * @param session The pointer of the session in the session list.
737 * @param data Data related to the event.
738 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
739 */
RfcommRecvFconReq(RfcommSessionInfo * session,const void * data)740 int RfcommRecvFconReq(RfcommSessionInfo *session, const void *data)
741 {
742 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
743
744 (void)data;
745
746 if (session->sessionState != ST_SESSION_CONNECTED) {
747 LOG_DEBUG("%{public}s:Session state is not connected.", __func__);
748 return RfcommSendDm(session, CONTROL_DLCI, false);
749 }
750 // Send FCon response.
751 int ret = RfcommSendUihFcon(session, false);
752
753 // When credit based flow control is being used on a session,
754 // the FCon and FCoff multiplexer control commands shall not be used.
755 if (session->fcType == FC_TYPE_CREDIT) {
756 LOG_DEBUG("%{public}s:Credit based fc is used, ignore FC-bit.", __func__);
757 return ret;
758 }
759 // Set the flow control status, and send buffered data on all channels.
760 if (session->peerSessionFc) {
761 session->peerSessionFc = false;
762 RfcommSendAllCachePktOnSession(session);
763 }
764
765 return ret;
766 }
767
768 /**
769 * @brief The processing after receiving FCON response from peer.
770 *
771 * @param session The pointer of the session in the session list.
772 * @param data Data related to the event.
773 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
774 */
RfcommRecvFconRsp(RfcommSessionInfo * session,const void * data)775 int RfcommRecvFconRsp(RfcommSessionInfo *session, const void *data)
776 {
777 LOG_INFO("%{public}s", __func__);
778
779 (void)session;
780 (void)data;
781
782 return RFCOMM_SUCCESS;
783 }
784
785 /**
786 * @brief The processing after receiving FCOFF request from peer.
787 *
788 * @param session The pointer of the session in the session list.
789 * @param data Data related to the event.
790 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
791 */
RfcommRecvFcoffReq(RfcommSessionInfo * session,const void * data)792 int RfcommRecvFcoffReq(RfcommSessionInfo *session, const void *data)
793 {
794 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
795
796 (void)data;
797
798 if (session->sessionState != ST_SESSION_CONNECTED) {
799 LOG_DEBUG("%{public}s:Session state is not connected.", __func__);
800 return RfcommSendDm(session, CONTROL_DLCI, false);
801 }
802
803 // Send FCon response.
804 int ret = RfcommSendUihFcoff(session, false);
805
806 // When credit based flow control is being used on a session,
807 // the FCon and FCoff multiplexer control commands shall not be used.
808 if (session->fcType == FC_TYPE_CREDIT) {
809 LOG_DEBUG("%{public}s:Credit based fc is used, ignore FC-bit.", __func__);
810 return ret;
811 }
812 // Set the flow control status.
813 session->peerSessionFc = true;
814
815 return ret;
816 }
817
818 /**
819 * @brief The processing after receiving FCOFF response from peer.
820 *
821 * @param session The pointer of the session in the session list.
822 * @param data Data related to the event.
823 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
824 */
RfcommRecvFcoffRsp(RfcommSessionInfo * session,const void * data)825 int RfcommRecvFcoffRsp(RfcommSessionInfo *session, const void *data)
826 {
827 LOG_INFO("%{public}s", __func__);
828
829 (void)session;
830 (void)data;
831
832 return RFCOMM_SUCCESS;
833 }
834
835 /**
836 * @brief The processing after receiving test request from peer.
837 *
838 * @param session The pointer of the session in the session list.
839 * @param data Data related to the event.
840 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
841 */
RfcommRecvTestReq(RfcommSessionInfo * session,const void * data)842 int RfcommRecvTestReq(RfcommSessionInfo *session, const void *data)
843 {
844 LOG_INFO("%{public}s", __func__);
845
846 if (data == NULL) {
847 return RFCOMM_ERR_PARAM;
848 }
849
850 RfcommUihInfo info;
851 (void)memcpy_s(&info, sizeof(RfcommUihInfo), data, sizeof(RfcommUihInfo));
852
853 return RfcommSendUihTest(session, false, info.test.pkt);
854 }
855
856 /**
857 * @brief The processing after receiving test response from peer.
858 *
859 * @param session The pointer of the session in the session list.
860 * @param data Data related to the event.
861 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
862 */
RfcommRecvTestRsp(RfcommSessionInfo * session,const void * data)863 int RfcommRecvTestRsp(RfcommSessionInfo *session, const void *data)
864 {
865 LOG_INFO("%{public}s", __func__);
866
867 (void)session;
868 (void)data;
869
870 return RFCOMM_SUCCESS;
871 }
872
873 /**
874 * @brief The processing after receiving NSC response from peer.
875 *
876 * @param session The pointer of the session in the session list.
877 * @param data Data related to the event.
878 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
879 */
RfcommRecvNsc(RfcommSessionInfo * session,const void * data)880 int RfcommRecvNsc(RfcommSessionInfo *session, const void *data)
881 {
882 LOG_INFO("%{public}s", __func__);
883
884 if (data == NULL) {
885 return RFCOMM_ERR_PARAM;
886 }
887
888 RfcommUihInfo info;
889 (void)memcpy_s(&info, sizeof(RfcommUihInfo), data, sizeof(RfcommUihInfo));
890
891 LOG_DEBUG("%{public}s:ea is %hhu.", __func__, info.nsc.ea);
892 LOG_DEBUG("%{public}s:cr is %hhu.", __func__, info.nsc.cr);
893 LOG_DEBUG("%{public}s:type is %hhu.", __func__, info.nsc.type);
894
895 return RFCOMM_SUCCESS;
896 }
897
898 /**
899 * @brief The processing after receiving the result of session's security.
900 *
901 * @param session The pointer of the session in the session list.
902 * @param data Data related to the event.
903 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
904 */
RfcommRecvSessionSecurityRslt(RfcommSessionInfo * session,const void * data)905 int RfcommRecvSessionSecurityRslt(RfcommSessionInfo *session, const void *data)
906 {
907 LOG_INFO("%{public}s session state is:%{public}d.", __func__, session->sessionState);
908
909 if (data == NULL) {
910 return RFCOMM_ERR_PARAM;
911 }
912
913 int ret = 0;
914 RfcommSessionSecurityRslt securityRslt;
915 L2capConfigInfo config;
916 (void)memset_s(&config, sizeof(config), 0, sizeof(config));
917 (void)memcpy_s(&securityRslt, sizeof(RfcommSessionSecurityRslt), data, sizeof(RfcommSessionSecurityRslt));
918
919 switch (session->sessionState) {
920 case ST_SESSION_INITIATOR_WAIT_SECURITY_RESULT:
921 if (securityRslt.direction != OUTGOING) {
922 LOG_ERROR("%{public}s Direction is error:%{public}d.", __func__, securityRslt.direction);
923 break;
924 }
925 if (securityRslt.result != GAP_SUCCESS) {
926 // Notify all channels on the session that connection failed.
927 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
928 // Remove all channels on session.
929 RfcommRemoveAllChannelOnSession(session);
930 // Destroy session from session list.
931 RfcommRemoveSession(session);
932 break;
933 }
934 session->sessionState = ST_SESSION_WAIT_CONNECT_REQ_RESULT;
935 ret = RfcommSendConnectReq(&(session->btAddr));
936 break;
937 case ST_SESSION_RESPONDER_WAIT_SECURITY_RESULT:
938 if (securityRslt.direction != INCOMING) {
939 LOG_ERROR("%{public}s Direction is error:%{public}d.", __func__, securityRslt.direction);
940 break;
941 }
942 if (securityRslt.result != GAP_SUCCESS) {
943 RfcommSendConnectRsp(session->l2capId, session->id, L2CAP_NO_RESOURCES_AVAILABLE, 0);
944 // Notify all channels on the session that connection failed.
945 RfcommNotifyAllChannelEvtOnSession(session, RFCOMM_CHANNEL_EV_CONNECT_FAIL);
946 // Remove all channels on session.
947 RfcommRemoveAllChannelOnSession(session);
948 // Destroy session.
949 RfcommRemoveSession(session);
950 break;
951 }
952 RfcommSendConnectRsp(session->l2capId, session->id, 0, 0);
953
954 config.rfc.mode = 0; // Basic mode
955 config.flushTimeout = 0xFFFF;
956 config.mtu = session->l2capLocalMtu;
957 config.fcs = 0x01;
958
959 session->sessionState = ST_SESSION_RESPONDER_WAIT_CONFIG_REQ_AND_RSP;
960 ret = RfcommSendConfigReq(session->l2capId, &config);
961 break;
962 default:
963 break;
964 }
965 return ret;
966 }
967
968 /**
969 * @brief Restart the session.When a connection request is received during the disconnection process,
970 * the connection is recreated after disconnection.
971 *
972 * @param session The pointer of the session in the session list.
973 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
974 */
RfcommRestartSession(RfcommSessionInfo * session)975 int RfcommRestartSession(RfcommSessionInfo *session)
976 {
977 LOG_INFO("%{public}s", __func__);
978
979 RfcommResetSessionInfo(session);
980 session->isInitiator = true;
981 RfcommUpdateChannelDirectionBit(session, true);
982 // Start to reopen the session.
983 session->sessionState = ST_SESSION_INITIATOR_WAIT_SECURITY_RESULT;
984 RfcommChannelInfo *channel = RfcommGetFirstChannelOnSession(session);
985 if (channel == NULL) {
986 LOG_ERROR("%{public}s No channel on the session.", __func__);
987 return RFCOMM_SUCCESS;
988 }
989
990 return RfcommCheckSessionSecurity(session, channel->scn, false);
991 }
992
993 /**
994 * @brief Accept the connection request from the peer device.
995 *
996 * @param session The pointer of the session in the session list.
997 * @return Returns <b>RFCOMM_SUCCESS</b> if the operation is successful, otherwise the operation fails.
998 */
RfcommAcceptPeerConnectReq(RfcommSessionInfo * session)999 int RfcommAcceptPeerConnectReq(RfcommSessionInfo *session)
1000 {
1001 LOG_INFO("%{public}s", __func__);
1002
1003 session->l2capId = session->pendingL2capId;
1004 session->id = session->pendingId;
1005 session->isInitiator = false;
1006 RfcommUpdateChannelDirectionBit(session, false);
1007 session->pendingL2capId = 0;
1008 session->pendingId = 0;
1009
1010 session->sessionState = ST_SESSION_RESPONDER_WAIT_SECURITY_RESULT;
1011 return RfcommCheckSessionSecurity(session, 0, true);
1012 }