• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 1999-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This file contains state machine and action routines for a port of the
22  *  RFCOMM unit
23  *
24  ******************************************************************************/
25 #include <string.h>
26 #include "bt_target.h"
27 #include "bt_common.h"
28 #include "rfcdefs.h"
29 #include "btm_api.h"
30 #include "btm_int.h"
31 #include "port_api.h"
32 #include "port_int.h"
33 #include "rfc_int.h"
34 #include "bt_utils.h"
35 
36 /********************************************************************************/
37 /*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
38 /********************************************************************************/
39 static void rfc_port_sm_state_closed (tPORT *p_port, UINT16 event, void *p_data);
40 static void rfc_port_sm_sabme_wait_ua (tPORT *p_port, UINT16 event, void *p_data);
41 static void rfc_port_sm_opened (tPORT *p_port, UINT16 event, void *p_data);
42 static void rfc_port_sm_orig_wait_sec_check (tPORT *p_port, UINT16 event, void *p_data);
43 static void rfc_port_sm_term_wait_sec_check (tPORT *p_port, UINT16 event, void *p_data);
44 static void rfc_port_sm_disc_wait_ua (tPORT *p_port, UINT16 event, void *p_data);
45 
46 static void rfc_port_uplink_data (tPORT *p_port, BT_HDR *p_buf);
47 
48 static void rfc_set_port_state(tPORT_STATE *port_pars, MX_FRAME *p_frame);
49 
50 
51 /*******************************************************************************
52 **
53 ** Function         rfc_port_sm_execute
54 **
55 ** Description      This function sends port events through the state
56 **                  machine.
57 **
58 ** Returns          void
59 **
60 *******************************************************************************/
rfc_port_sm_execute(tPORT * p_port,UINT16 event,void * p_data)61 void rfc_port_sm_execute (tPORT *p_port, UINT16 event, void *p_data)
62 {
63     if (!p_port)
64     {
65         RFCOMM_TRACE_WARNING ("NULL port event %d", event);
66         return;
67     }
68 
69     switch (p_port->rfc.state)
70     {
71     case RFC_STATE_CLOSED:
72         rfc_port_sm_state_closed (p_port, event, p_data);
73         break;
74 
75     case RFC_STATE_SABME_WAIT_UA:
76         rfc_port_sm_sabme_wait_ua (p_port, event, p_data);
77         break;
78 
79     case RFC_STATE_ORIG_WAIT_SEC_CHECK:
80         rfc_port_sm_orig_wait_sec_check (p_port, event, p_data);
81         break;
82 
83     case RFC_STATE_TERM_WAIT_SEC_CHECK:
84         rfc_port_sm_term_wait_sec_check (p_port, event, p_data);
85         break;
86 
87     case RFC_STATE_OPENED:
88         rfc_port_sm_opened (p_port, event, p_data);
89         break;
90 
91     case RFC_STATE_DISC_WAIT_UA:
92         rfc_port_sm_disc_wait_ua (p_port, event, p_data);
93         break;
94     }
95 }
96 
97 
98 /*******************************************************************************
99 **
100 ** Function         rfc_port_sm_state_closed
101 **
102 ** Description      This function handles events when the port is in
103 **                  CLOSED state. This state exists when port is
104 **                  being initially established.
105 **
106 ** Returns          void
107 **
108 *******************************************************************************/
rfc_port_sm_state_closed(tPORT * p_port,UINT16 event,void * p_data)109 void rfc_port_sm_state_closed (tPORT *p_port, UINT16 event, void *p_data)
110 {
111     switch (event)
112     {
113     case RFC_EVENT_OPEN:
114         p_port->rfc.state = RFC_STATE_ORIG_WAIT_SEC_CHECK;
115         btm_sec_mx_access_request (p_port->rfc.p_mcb->bd_addr, BT_PSM_RFCOMM, TRUE,
116                                    BTM_SEC_PROTO_RFCOMM, (UINT32)(p_port->dlci / 2),
117                                    &rfc_sec_check_complete, p_port);
118         return;
119 
120     case RFC_EVENT_CLOSE:
121         break;
122 
123     case RFC_EVENT_CLEAR:
124         return;
125 
126     case RFC_EVENT_DATA:
127         osi_free(p_data);
128         break;
129 
130     case RFC_EVENT_SABME:
131         /* make sure the multiplexer disconnect timer is not running (reconnect case) */
132         rfc_timer_stop(p_port->rfc.p_mcb );
133 
134         /* Open will be continued after security checks are passed */
135         p_port->rfc.state = RFC_STATE_TERM_WAIT_SEC_CHECK;
136         btm_sec_mx_access_request (p_port->rfc.p_mcb->bd_addr, BT_PSM_RFCOMM, FALSE,
137                                    BTM_SEC_PROTO_RFCOMM, (UINT32)(p_port->dlci / 2),
138                                    &rfc_sec_check_complete, p_port);
139         return;
140 
141     case RFC_EVENT_UA:
142         return;
143 
144     case RFC_EVENT_DM:
145         rfc_port_closed (p_port);
146         return;
147 
148     case RFC_EVENT_UIH:
149         osi_free(p_data);
150         rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, FALSE);
151         return;
152 
153     case RFC_EVENT_DISC:
154         rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, FALSE);
155         return;
156 
157     case RFC_EVENT_TIMEOUT:
158         Port_TimeOutCloseMux( p_port->rfc.p_mcb ) ;
159         RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event);
160         return;
161     }
162 
163     RFCOMM_TRACE_WARNING ("Port state closed Event ignored %d", event);
164     return;
165 }
166 
167 /*******************************************************************************
168 **
169 ** Function         rfc_port_sm_sabme_wait_ua
170 **
171 ** Description      This function handles events when SABME on the DLC was
172 **                  sent and SM is waiting for UA or DM.
173 **
174 ** Returns          void
175 **
176 *******************************************************************************/
rfc_port_sm_sabme_wait_ua(tPORT * p_port,UINT16 event,void * p_data)177 void rfc_port_sm_sabme_wait_ua (tPORT *p_port, UINT16 event, void *p_data)
178 {
179     switch (event)
180     {
181     case RFC_EVENT_OPEN:
182     case RFC_EVENT_ESTABLISH_RSP:
183         RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event);
184         return;
185 
186     case RFC_EVENT_CLOSE:
187         rfc_port_timer_start (p_port, RFC_DISC_TIMEOUT);
188         rfc_send_disc (p_port->rfc.p_mcb, p_port->dlci);
189         p_port->rfc.expected_rsp = 0;
190         p_port->rfc.state = RFC_STATE_DISC_WAIT_UA;
191         return;
192 
193     case RFC_EVENT_CLEAR:
194         rfc_port_closed (p_port);
195         return;
196 
197     case RFC_EVENT_DATA:
198         osi_free(p_data);
199         break;
200 
201     case RFC_EVENT_UA:
202         rfc_port_timer_stop (p_port);
203         p_port->rfc.state = RFC_STATE_OPENED;
204         PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_SUCCESS);
205         return;
206 
207     case RFC_EVENT_DM:
208         p_port->rfc.p_mcb->is_disc_initiator = TRUE;
209         PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR);
210         rfc_port_closed (p_port);
211         return;
212 
213     case RFC_EVENT_DISC:
214         rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);
215         PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR);
216         rfc_port_closed (p_port);
217         return;
218 
219     case RFC_EVENT_SABME:
220         /* Continue to wait for the UA the SABME this side sent */
221         rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);
222         return;
223 
224     case RFC_EVENT_UIH:
225         osi_free(p_data);
226         return;
227 
228     case RFC_EVENT_TIMEOUT:
229         p_port->rfc.state = RFC_STATE_CLOSED;
230         PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR);
231         return;
232     }
233     RFCOMM_TRACE_WARNING ("Port state sabme_wait_ua Event ignored %d", event);
234 }
235 
236 
237 /*******************************************************************************
238 **
239 ** Function         rfc_port_sm_term_wait_sec_check
240 **
241 ** Description      This function handles events for the port in the
242 **                  WAIT_SEC_CHECK state.  SABME has been received from the
243 **                  peer and Security Manager verifes BD_ADDR, before we can
244 **                  send ESTABLISH_IND to the Port entity
245 **
246 ** Returns          void
247 **
248 *******************************************************************************/
rfc_port_sm_term_wait_sec_check(tPORT * p_port,UINT16 event,void * p_data)249 void rfc_port_sm_term_wait_sec_check (tPORT *p_port, UINT16 event, void *p_data)
250 {
251     switch (event)
252     {
253     case RFC_EVENT_SEC_COMPLETE:
254         if (*((UINT8 *)p_data) != BTM_SUCCESS)
255         {
256             /* Authentication/authorization failed.  If link is still  */
257             /* up send DM and check if we need to start inactive timer */
258             if (p_port->rfc.p_mcb)
259             {
260                 rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, TRUE);
261                 p_port->rfc.p_mcb->is_disc_initiator = TRUE;
262                 port_rfc_closed (p_port, PORT_SEC_FAILED);
263             }
264         }
265         else
266         {
267             PORT_DlcEstablishInd (p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu);
268         }
269         return;
270 
271     case RFC_EVENT_OPEN:
272     case RFC_EVENT_CLOSE:
273         RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event);
274         return;
275 
276     case RFC_EVENT_CLEAR:
277         btm_sec_abort_access_req (p_port->rfc.p_mcb->bd_addr);
278         rfc_port_closed (p_port);
279         return;
280 
281     case RFC_EVENT_DATA:
282         RFCOMM_TRACE_ERROR ("Port error state Term Wait Sec event Data");
283         osi_free(p_data);
284         return;
285 
286     case RFC_EVENT_SABME:
287         /* Ignore SABME retransmission if client dares to do so */
288         return;
289 
290     case RFC_EVENT_DISC:
291         btm_sec_abort_access_req (p_port->rfc.p_mcb->bd_addr);
292         p_port->rfc.state = RFC_STATE_CLOSED;
293         rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);
294 
295         PORT_DlcReleaseInd (p_port->rfc.p_mcb, p_port->dlci);
296         return;
297 
298     case RFC_EVENT_UIH:
299         osi_free(p_data);
300         return;
301 
302     case RFC_EVENT_ESTABLISH_RSP:
303         if (*((UINT8 *)p_data) != RFCOMM_SUCCESS)
304         {
305             if (p_port->rfc.p_mcb)
306                 rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, TRUE);
307         }
308         else
309         {
310             rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);
311             p_port->rfc.state = RFC_STATE_OPENED;
312         }
313         return;
314     }
315     RFCOMM_TRACE_WARNING ("Port state term_wait_sec_check Event ignored %d", event);
316 }
317 
318 
319 /*******************************************************************************
320 **
321 ** Function         rfc_port_sm_orig_wait_sec_check
322 **
323 ** Description      This function handles events for the port in the
324 **                  ORIG_WAIT_SEC_CHECK state.  RFCOMM is waiting for Security
325 **                  manager to finish before sending SABME to the peer
326 **
327 ** Returns          void
328 **
329 *******************************************************************************/
rfc_port_sm_orig_wait_sec_check(tPORT * p_port,UINT16 event,void * p_data)330 void rfc_port_sm_orig_wait_sec_check (tPORT *p_port, UINT16 event, void *p_data)
331 {
332     switch (event)
333     {
334     case RFC_EVENT_SEC_COMPLETE:
335         if (*((UINT8 *)p_data) != BTM_SUCCESS)
336         {
337             p_port->rfc.p_mcb->is_disc_initiator = TRUE;
338             PORT_DlcEstablishCnf (p_port->rfc.p_mcb, p_port->dlci, 0, RFCOMM_SECURITY_ERR);
339             rfc_port_closed (p_port);
340             return;
341         }
342         rfc_send_sabme (p_port->rfc.p_mcb, p_port->dlci);
343         rfc_port_timer_start (p_port, RFC_PORT_T1_TIMEOUT);
344         p_port->rfc.state = RFC_STATE_SABME_WAIT_UA;
345         return;
346 
347     case RFC_EVENT_OPEN:
348     case RFC_EVENT_SABME:       /* Peer should not use the same dlci */
349         RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event);
350         return;
351 
352     case RFC_EVENT_CLOSE:
353         btm_sec_abort_access_req (p_port->rfc.p_mcb->bd_addr);
354         rfc_port_closed (p_port);
355         return;
356 
357     case RFC_EVENT_DATA:
358         RFCOMM_TRACE_ERROR ("Port error state Orig Wait Sec event Data");
359         osi_free(p_data);
360         return;
361 
362     case RFC_EVENT_UIH:
363         osi_free(p_data);
364         return;
365     }
366     RFCOMM_TRACE_WARNING ("Port state orig_wait_sec_check Event ignored %d", event);
367 }
368 
369 
370 /*******************************************************************************
371 **
372 ** Function         rfc_port_sm_opened
373 **
374 ** Description      This function handles events for the port in the OPENED
375 **                  state
376 **
377 ** Returns          void
378 **
379 *******************************************************************************/
rfc_port_sm_opened(tPORT * p_port,UINT16 event,void * p_data)380 void rfc_port_sm_opened (tPORT *p_port, UINT16 event, void *p_data)
381 {
382     switch (event)
383     {
384     case RFC_EVENT_OPEN:
385         RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event);
386         return;
387 
388     case RFC_EVENT_CLOSE:
389         rfc_port_timer_start (p_port, RFC_DISC_TIMEOUT);
390         rfc_send_disc (p_port->rfc.p_mcb, p_port->dlci);
391         p_port->rfc.expected_rsp = 0;
392         p_port->rfc.state = RFC_STATE_DISC_WAIT_UA;
393         return;
394 
395     case RFC_EVENT_CLEAR:
396         rfc_port_closed (p_port);
397         return;
398 
399     case RFC_EVENT_DATA:
400         /* Send credits in the frame.  Pass them in the layer specific member of the hdr. */
401         /* There might be an initial case when we reduced rx_max and credit_rx is still */
402         /* bigger.  Make sure that we do not send 255 */
403         if ((p_port->rfc.p_mcb->flow == PORT_FC_CREDIT)
404          && (((BT_HDR *)p_data)->len < p_port->peer_mtu)
405          && (!p_port->rx.user_fc)
406          && (p_port->credit_rx_max > p_port->credit_rx))
407         {
408             ((BT_HDR *)p_data)->layer_specific = (UINT8) (p_port->credit_rx_max - p_port->credit_rx);
409             p_port->credit_rx = p_port->credit_rx_max;
410         }
411         else
412         {
413             ((BT_HDR *)p_data)->layer_specific = 0;
414         }
415         rfc_send_buf_uih (p_port->rfc.p_mcb, p_port->dlci, (BT_HDR *)p_data);
416         rfc_dec_credit (p_port);
417         return;
418 
419     case RFC_EVENT_UA:
420         return;
421 
422     case RFC_EVENT_SABME:
423         rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);
424         return;
425 
426     case RFC_EVENT_DM:
427         PORT_DlcReleaseInd (p_port->rfc.p_mcb, p_port->dlci);
428         rfc_port_closed (p_port);
429         return;
430 
431     case RFC_EVENT_DISC:
432         p_port->rfc.state = RFC_STATE_CLOSED;
433         rfc_send_ua (p_port->rfc.p_mcb, p_port->dlci);
434         if(! fixed_queue_is_empty(p_port->rx.queue))
435         {
436             /* give a chance to upper stack to close port properly */
437             RFCOMM_TRACE_DEBUG("port queue is not empty");
438             rfc_port_timer_start (p_port, RFC_DISC_TIMEOUT);
439         }
440         else
441             PORT_DlcReleaseInd (p_port->rfc.p_mcb, p_port->dlci);
442         return;
443 
444     case RFC_EVENT_UIH:
445         rfc_port_uplink_data (p_port, (BT_HDR *)p_data);
446         return;
447 
448     case RFC_EVENT_TIMEOUT:
449         Port_TimeOutCloseMux( p_port->rfc.p_mcb ) ;
450         RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event);
451         return;
452     }
453     RFCOMM_TRACE_WARNING ("Port state opened Event ignored %d", event);
454 }
455 
456 
457 /*******************************************************************************
458 **
459 ** Function         rfc_port_sm_disc_wait_ua
460 **
461 ** Description      This function handles events when DISC on the DLC was
462 **                  sent and SM is waiting for UA or DM.
463 **
464 ** Returns          void
465 **
466 *******************************************************************************/
rfc_port_sm_disc_wait_ua(tPORT * p_port,UINT16 event,void * p_data)467 void rfc_port_sm_disc_wait_ua (tPORT *p_port, UINT16 event, void *p_data)
468 {
469     switch (event)
470     {
471     case RFC_EVENT_OPEN:
472     case RFC_EVENT_ESTABLISH_RSP:
473         RFCOMM_TRACE_ERROR ("Port error state %d event %d", p_port->rfc.state, event);
474         return;
475 
476     case RFC_EVENT_CLEAR:
477         rfc_port_closed (p_port);
478         return;
479 
480     case RFC_EVENT_DATA:
481         osi_free(p_data);
482         return;
483 
484     case RFC_EVENT_UA:
485         p_port->rfc.p_mcb->is_disc_initiator = TRUE;
486         /* Case falls through */
487 
488    case RFC_EVENT_DM:
489         rfc_port_closed (p_port);
490         return;
491 
492     case RFC_EVENT_SABME:
493         rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, TRUE);
494         return;
495 
496     case RFC_EVENT_DISC:
497         rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, TRUE);
498         return;
499 
500     case RFC_EVENT_UIH:
501         osi_free(p_data);
502         rfc_send_dm (p_port->rfc.p_mcb, p_port->dlci, FALSE);
503         return;
504 
505     case RFC_EVENT_TIMEOUT:
506         rfc_port_closed (p_port);
507         return;
508     }
509 
510     RFCOMM_TRACE_WARNING ("Port state disc_wait_ua Event ignored %d", event);
511 }
512 
513 
514 /*******************************************************************************
515 **
516 ** Function         rfc_port_uplink_data
517 **
518 ** Description      This function handles uplink information data frame.
519 **
520 *******************************************************************************/
rfc_port_uplink_data(tPORT * p_port,BT_HDR * p_buf)521 void rfc_port_uplink_data (tPORT *p_port, BT_HDR *p_buf)
522 {
523     PORT_DataInd (p_port->rfc.p_mcb, p_port->dlci, p_buf);
524 }
525 
526 
527 /*******************************************************************************
528 **
529 ** Function         rfc_process_pn
530 **
531 ** Description      This function handles DLC parameter negotiation frame.
532 **                  Record MTU and pass indication to the upper layer.
533 **
534 *******************************************************************************/
rfc_process_pn(tRFC_MCB * p_mcb,BOOLEAN is_command,MX_FRAME * p_frame)535 void rfc_process_pn (tRFC_MCB *p_mcb, BOOLEAN is_command, MX_FRAME *p_frame)
536 {
537     tPORT *p_port;
538     UINT8 dlci = p_frame->dlci;
539 
540     if (is_command)
541     {
542         /* Ignore if Multiplexer is being shut down */
543         if (p_mcb->state != RFC_MX_STATE_DISC_WAIT_UA)
544         {
545             PORT_ParNegInd (p_mcb, dlci, p_frame->u.pn.mtu,
546                         p_frame->u.pn.conv_layer, p_frame->u.pn.k);
547         }
548         else
549         {
550             rfc_send_dm(p_mcb, dlci, FALSE);
551             RFCOMM_TRACE_WARNING("***** MX PN while disconnecting *****");
552         }
553 
554         return;
555     }
556     /* If we are not awaiting response just ignore it */
557     p_port = port_find_mcb_dlci_port (p_mcb, dlci);
558     if ((p_port == NULL) || !(p_port->rfc.expected_rsp & RFC_RSP_PN))
559         return;
560 
561     p_port->rfc.expected_rsp &= ~RFC_RSP_PN;
562 
563     rfc_port_timer_stop (p_port);
564 
565     PORT_ParNegCnf (p_mcb, dlci, p_frame->u.pn.mtu,
566                     p_frame->u.pn.conv_layer, p_frame->u.pn.k);
567 }
568 
569 
570 /*******************************************************************************
571 **
572 ** Function         rfc_process_rpn
573 **
574 ** Description      This function handles Remote DLC parameter negotiation
575 **                  command/response.  Pass command to the user.
576 **
577 *******************************************************************************/
rfc_process_rpn(tRFC_MCB * p_mcb,BOOLEAN is_command,BOOLEAN is_request,MX_FRAME * p_frame)578 void rfc_process_rpn (tRFC_MCB *p_mcb, BOOLEAN is_command,
579                       BOOLEAN is_request, MX_FRAME *p_frame)
580 {
581     tPORT_STATE port_pars;
582     tPORT       *p_port;
583 
584     if ((p_port = port_find_mcb_dlci_port (p_mcb, p_frame->dlci)) == NULL)
585     {
586         /* This is the first command on the port */
587         if (is_command)
588         {
589 
590             memset(&port_pars, 0, sizeof(tPORT_STATE));
591             rfc_set_port_state(&port_pars, p_frame);
592 
593             PORT_PortNegInd(p_mcb, p_frame->dlci, &port_pars, p_frame->u.rpn.param_mask);
594         }
595         return;
596     }
597 
598     if (is_command && is_request)
599     {
600         /* This is the special situation when peer just request local pars */
601         port_pars = p_port->peer_port_pars;
602         rfc_send_rpn (p_mcb, p_frame->dlci, FALSE, &p_port->peer_port_pars, 0);
603         return;
604     }
605 
606     port_pars = p_port->peer_port_pars;
607 
608     rfc_set_port_state(&port_pars, p_frame);
609 
610     if (is_command)
611     {
612         PORT_PortNegInd (p_mcb, p_frame->dlci, &port_pars, p_frame->u.rpn.param_mask);
613         return;
614     }
615 
616     /* If we are not awaiting response just ignore it */
617     p_port = port_find_mcb_dlci_port (p_mcb, p_frame->dlci);
618     if ((p_port == NULL) || !(p_port->rfc.expected_rsp & (RFC_RSP_RPN | RFC_RSP_RPN_REPLY)))
619         return;
620 
621     /* If we sent a request for port parameters to the peer he is replying with */
622     /* mask 0. */
623     rfc_port_timer_stop (p_port);
624 
625     if (p_port->rfc.expected_rsp & RFC_RSP_RPN_REPLY)
626     {
627         p_port->rfc.expected_rsp &= ~RFC_RSP_RPN_REPLY;
628 
629         p_port->peer_port_pars = port_pars;
630 
631         if ((port_pars.fc_type == (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT))
632          || (port_pars.fc_type == (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT)))
633         {
634             /* This is satisfactory port parameters.  Set mask as it was Ok */
635             p_frame->u.rpn.param_mask = RFCOMM_RPN_PM_MASK;
636         }
637         else
638         {
639             /* Current peer parameters are not good, try to fix them */
640             p_port->peer_port_pars.fc_type = (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT);
641 
642             p_port->rfc.expected_rsp |= RFC_RSP_RPN;
643             rfc_send_rpn (p_mcb, p_frame->dlci, TRUE, &p_port->peer_port_pars,
644                           RFCOMM_RPN_PM_RTR_ON_INPUT | RFCOMM_RPN_PM_RTR_ON_OUTPUT);
645             rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
646             return;
647         }
648     }
649     else
650         p_port->rfc.expected_rsp &= ~RFC_RSP_RPN;
651 
652     /* Check if all suggested parameters were accepted */
653     if (((p_frame->u.rpn.param_mask & (RFCOMM_RPN_PM_RTR_ON_INPUT | RFCOMM_RPN_PM_RTR_ON_OUTPUT)) ==
654         (RFCOMM_RPN_PM_RTR_ON_INPUT | RFCOMM_RPN_PM_RTR_ON_OUTPUT))
655      || ((p_frame->u.rpn.param_mask & (RFCOMM_RPN_PM_RTC_ON_INPUT | RFCOMM_RPN_PM_RTC_ON_OUTPUT)) ==
656         (RFCOMM_RPN_PM_RTC_ON_INPUT | RFCOMM_RPN_PM_RTC_ON_OUTPUT)))
657     {
658         PORT_PortNegCnf (p_mcb, p_port->dlci, &port_pars, RFCOMM_SUCCESS);
659         return;
660     }
661 
662     /* If we were proposing RTR flow control try RTC flow control */
663     /* If we were proposing RTC flow control try no flow control */
664     /* otherwise drop the connection */
665     if (p_port->peer_port_pars.fc_type == (RFCOMM_FC_RTR_ON_INPUT | RFCOMM_FC_RTR_ON_OUTPUT))
666     {
667         /* Current peer parameters are not good, try to fix them */
668         p_port->peer_port_pars.fc_type = (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT);
669 
670         p_port->rfc.expected_rsp |= RFC_RSP_RPN;
671 
672         rfc_send_rpn (p_mcb, p_frame->dlci, TRUE, &p_port->peer_port_pars,
673                       RFCOMM_RPN_PM_RTC_ON_INPUT | RFCOMM_RPN_PM_RTC_ON_OUTPUT);
674         rfc_port_timer_start (p_port, RFC_T2_TIMEOUT) ;
675         return;
676     }
677 
678     /* Other side does not support flow control */
679     if (p_port->peer_port_pars.fc_type == (RFCOMM_FC_RTC_ON_INPUT | RFCOMM_FC_RTC_ON_OUTPUT))
680     {
681         p_port->peer_port_pars.fc_type = RFCOMM_FC_OFF;
682         PORT_PortNegCnf (p_mcb, p_port->dlci, &port_pars, RFCOMM_SUCCESS);
683     }
684 }
685 
686 
687 /*******************************************************************************
688 **
689 ** Function         rfc_process_msc
690 **
691 ** Description      This function handles Modem Status Command.
692 **                  Pass command to the user.
693 **
694 *******************************************************************************/
rfc_process_msc(tRFC_MCB * p_mcb,BOOLEAN is_command,MX_FRAME * p_frame)695 void rfc_process_msc (tRFC_MCB *p_mcb, BOOLEAN is_command, MX_FRAME *p_frame)
696 {
697     tPORT_CTRL pars;
698     tPORT      *p_port;
699     UINT8      modem_signals = p_frame->u.msc.signals;
700     BOOLEAN    new_peer_fc = FALSE;
701 
702     p_port = port_find_mcb_dlci_port (p_mcb, p_frame->dlci);
703     if (p_port == NULL)
704         return;
705 
706     pars.modem_signal = 0;
707 
708     if (modem_signals & RFCOMM_MSC_RTC)
709         pars.modem_signal |= MODEM_SIGNAL_DTRDSR;
710 
711     if (modem_signals & RFCOMM_MSC_RTR)
712         pars.modem_signal |= MODEM_SIGNAL_RTSCTS;
713 
714     if (modem_signals & RFCOMM_MSC_IC)
715         pars.modem_signal |= MODEM_SIGNAL_RI;
716 
717     if (modem_signals & RFCOMM_MSC_DV)
718         pars.modem_signal |= MODEM_SIGNAL_DCD;
719 
720     pars.fc = ((modem_signals & RFCOMM_MSC_FC) == RFCOMM_MSC_FC);
721 
722     pars.break_signal     = (p_frame->u.msc.break_present) ?
723                              p_frame->u.msc.break_duration : 0;
724     pars.discard_buffers  = 0;
725     pars.break_signal_seq = RFCOMM_CTRL_BREAK_IN_SEQ;   /* this is default */
726 
727     /* Check if this command is passed only to indicate flow control */
728     if (is_command)
729     {
730         rfc_send_msc (p_mcb, p_frame->dlci, FALSE, &pars);
731 
732         if (p_port->rfc.p_mcb->flow != PORT_FC_CREDIT)
733         {
734             /* Spec 1.1 indicates that only FC bit is used for flow control */
735             p_port->peer_ctrl.fc = new_peer_fc = pars.fc;
736 
737             if (new_peer_fc != p_port->tx.peer_fc)
738                 PORT_FlowInd (p_mcb, p_frame->dlci, (BOOLEAN)!new_peer_fc);
739         }
740 
741         PORT_ControlInd (p_mcb, p_frame->dlci, &pars);
742 
743         return;
744     }
745 
746     /* If we are not awaiting response just ignore it */
747     if (!(p_port->rfc.expected_rsp & RFC_RSP_MSC))
748         return;
749 
750     p_port->rfc.expected_rsp &= ~RFC_RSP_MSC;
751 
752     rfc_port_timer_stop (p_port);
753 
754     PORT_ControlCnf (p_port->rfc.p_mcb, p_port->dlci, &pars);
755 }
756 
757 
758 /*******************************************************************************
759 **
760 ** Function         rfc_process_rls
761 **
762 ** Description      This function handles Remote Line Status command.
763 **                  Pass command to the user.
764 **
765 *******************************************************************************/
rfc_process_rls(tRFC_MCB * p_mcb,BOOLEAN is_command,MX_FRAME * p_frame)766 void rfc_process_rls (tRFC_MCB *p_mcb, BOOLEAN is_command, MX_FRAME *p_frame)
767 {
768     tPORT *p_port;
769 
770     if (is_command)
771     {
772         PORT_LineStatusInd (p_mcb, p_frame->dlci, p_frame->u.rls.line_status);
773         rfc_send_rls (p_mcb, p_frame->dlci, FALSE, p_frame->u.rls.line_status);
774     }
775     else
776     {
777         p_port = port_find_mcb_dlci_port (p_mcb, p_frame->dlci);
778 
779         /* If we are not awaiting response just ignore it */
780         if (!p_port || !(p_port->rfc.expected_rsp & RFC_RSP_RLS))
781             return;
782 
783         p_port->rfc.expected_rsp &= ~RFC_RSP_RLS;
784 
785         rfc_port_timer_stop (p_port);
786     }
787 }
788 
789 
790 /*******************************************************************************
791 **
792 ** Function         rfc_process_nsc
793 **
794 ** Description      This function handles None Supported Command frame.
795 **
796 *******************************************************************************/
rfc_process_nsc(tRFC_MCB * p_mcb,MX_FRAME * p_frame)797 void rfc_process_nsc (tRFC_MCB *p_mcb, MX_FRAME *p_frame)
798 {
799     UNUSED(p_mcb);
800     UNUSED(p_frame);
801 }
802 
803 
804 /*******************************************************************************
805 **
806 ** Function         rfc_process_test
807 **
808 ** Description      This function handles Test frame.  If this is a command
809 **                  reply to it.  Otherwise pass response to the user.
810 **
811 *******************************************************************************/
rfc_process_test_rsp(tRFC_MCB * p_mcb,BT_HDR * p_buf)812 void rfc_process_test_rsp(tRFC_MCB *p_mcb, BT_HDR *p_buf)
813 {
814     UNUSED(p_mcb);
815     osi_free(p_buf);
816 }
817 
818 /*******************************************************************************
819 **
820 ** Function         rfc_process_fcon
821 **
822 ** Description      This function handles FCON frame.  The peer entity is able
823 **                  to receive new information
824 **
825 *******************************************************************************/
rfc_process_fcon(tRFC_MCB * p_mcb,BOOLEAN is_command)826 void rfc_process_fcon (tRFC_MCB *p_mcb, BOOLEAN is_command)
827 {
828     if (is_command)
829     {
830         rfc_cb.rfc.peer_rx_disabled = FALSE;
831 
832         rfc_send_fcon (p_mcb, FALSE);
833 
834         if (!p_mcb->l2cap_congested)
835             PORT_FlowInd (p_mcb, 0, TRUE);
836     }
837 }
838 
839 /*******************************************************************************
840 **
841 ** Function         rfc_process_fcoff
842 **
843 ** Description      This function handles FCOFF frame.  The peer entity is unable
844 **                  to receive new information
845 **
846 *******************************************************************************/
rfc_process_fcoff(tRFC_MCB * p_mcb,BOOLEAN is_command)847 void rfc_process_fcoff (tRFC_MCB *p_mcb, BOOLEAN is_command)
848 {
849     if (is_command)
850     {
851         rfc_cb.rfc.peer_rx_disabled = TRUE;
852 
853         if (!p_mcb->l2cap_congested)
854             PORT_FlowInd (p_mcb, 0, FALSE);
855 
856         rfc_send_fcoff (p_mcb, FALSE);
857     }
858 }
859 
860 
861 /*******************************************************************************
862 **
863 ** Function         rfc_process_l2cap_congestion
864 **
865 ** Description      This function handles L2CAP congestion messages
866 **
867 *******************************************************************************/
rfc_process_l2cap_congestion(tRFC_MCB * p_mcb,BOOLEAN is_congested)868 void rfc_process_l2cap_congestion (tRFC_MCB *p_mcb, BOOLEAN is_congested)
869 {
870     p_mcb->l2cap_congested = is_congested;
871 
872     if (!is_congested)
873     {
874         rfc_check_send_cmd(p_mcb, NULL);
875     }
876 
877     if (!rfc_cb.rfc.peer_rx_disabled)
878     {
879         if (!is_congested)
880             PORT_FlowInd (p_mcb, 0, TRUE);
881         else
882             PORT_FlowInd (p_mcb, 0, FALSE);
883     }
884 }
885 
886 /*******************************************************************************
887 **
888 ** Function         rfc_set_port_pars
889 **
890 ** Description      This function sets the tPORT_STATE structure given a p_frame.
891 **
892 *******************************************************************************/
893 
rfc_set_port_state(tPORT_STATE * port_pars,MX_FRAME * p_frame)894 void rfc_set_port_state(tPORT_STATE *port_pars, MX_FRAME *p_frame)
895 {
896     if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_BIT_RATE)
897         port_pars->baud_rate   = p_frame->u.rpn.baud_rate;
898     if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_DATA_BITS)
899         port_pars->byte_size   = p_frame->u.rpn.byte_size;
900     if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_STOP_BITS)
901         port_pars->stop_bits   = p_frame->u.rpn.stop_bits;
902     if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_PARITY)
903         port_pars->parity      = p_frame->u.rpn.parity;
904     if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_PARITY_TYPE)
905         port_pars->parity_type = p_frame->u.rpn.parity_type;
906     if (p_frame->u.rpn.param_mask & (RFCOMM_RPN_PM_XONXOFF_ON_INPUT |
907                                      RFCOMM_RPN_PM_XONXOFF_ON_OUTPUT |
908                                      RFCOMM_RPN_PM_RTR_ON_INPUT |
909                                      RFCOMM_RPN_PM_RTR_ON_OUTPUT |
910                                      RFCOMM_RPN_PM_RTC_ON_INPUT |
911                                      RFCOMM_RPN_PM_RTC_ON_OUTPUT))
912         port_pars->fc_type     = p_frame->u.rpn.fc_type;
913     if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_XON_CHAR)
914         port_pars->xon_char    = p_frame->u.rpn.xon_char;
915     if (p_frame->u.rpn.param_mask & RFCOMM_RPN_PM_XOFF_CHAR)
916         port_pars->xoff_char   = p_frame->u.rpn.xoff_char;
917 }
918 
919