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 module contains functions for port emulation entity and RFCOMM
22 * communications
23 *
24 ******************************************************************************/
25 #include <string.h>
26
27 #include "osi/include/mutex.h"
28
29 #include "bt_common.h"
30 #include "bt_target.h"
31 #include "bt_utils.h"
32 #include "btm_api.h"
33 #include "btm_int.h"
34 #include "port_api.h"
35 #include "port_int.h"
36 #include "rfc_int.h"
37 #include "rfcdefs.h"
38
39 /*
40 ** Local function definitions
41 */
42 UINT32 port_rfc_send_tx_data (tPORT *p_port);
43 void port_rfc_closed (tPORT *p_port, UINT8 res);
44 void port_get_credits (tPORT *p_port, UINT8 k);
45
46
47 /*******************************************************************************
48 **
49 ** Function port_open_continue
50 **
51 ** Description This function is called after security manager completes
52 ** required security checks.
53 **
54 ** Returns void
55 **
56 *******************************************************************************/
port_open_continue(tPORT * p_port)57 int port_open_continue (tPORT *p_port)
58 {
59 tRFC_MCB *p_mcb;
60
61 RFCOMM_TRACE_EVENT ("port_open_continue, p_port:%p", p_port);
62
63 /* Check if multiplexer channel has already been established */
64 if ((p_mcb = rfc_alloc_multiplexer_channel (p_port->bd_addr, TRUE)) == NULL)
65 {
66 RFCOMM_TRACE_WARNING ("port_open_continue no mx channel");
67 port_release_port (p_port);
68 return (PORT_NO_RESOURCES);
69 }
70
71 p_port->rfc.p_mcb = p_mcb;
72
73 p_mcb->port_inx[p_port->dlci] = p_port->inx;
74
75 /* Connection is up and we know local and remote features, select MTU */
76 port_select_mtu (p_port);
77
78 if (p_mcb->state == RFC_MX_STATE_CONNECTED)
79 {
80 RFCOMM_ParNegReq (p_mcb, p_port->dlci, p_port->mtu);
81 }
82 else if ((p_mcb->state == RFC_MX_STATE_IDLE)
83 ||(p_mcb->state == RFC_MX_STATE_DISC_WAIT_UA))
84 {
85 /* In RFC_MX_STATE_IDLE state, MX state machine will create connection */
86 /* In RFC_MX_STATE_DISC_WAIT_UA state, MX state machine will recreate connection */
87 /* after disconnecting is completed */
88 RFCOMM_StartReq (p_mcb);
89 }
90 else
91 {
92 /* MX state machine ignores RFC_MX_EVENT_START_REQ in these states */
93 /* When it enters RFC_MX_STATE_CONNECTED, it will check any openning ports */
94 RFCOMM_TRACE_DEBUG ("port_open_continue: mx state(%d) mx channel is openning", p_mcb->state);
95 }
96 return (PORT_SUCCESS);
97 }
98
99
100 /*******************************************************************************
101 **
102 ** Function port_start_control
103 **
104 ** Description This function is called in the BTU_TASK context to
105 ** send control information
106 **
107 ** Returns void
108 **
109 *******************************************************************************/
port_start_control(tPORT * p_port)110 void port_start_control (tPORT *p_port)
111 {
112 tRFC_MCB *p_mcb = p_port->rfc.p_mcb;
113
114 if (p_mcb == NULL)
115 return;
116
117 RFCOMM_ControlReq (p_mcb, p_port->dlci, &p_port->local_ctrl);
118 }
119
120
121 /*******************************************************************************
122 **
123 ** Function port_start_par_neg
124 **
125 ** Description This function is called in the BTU_TASK context to
126 ** send configuration information
127 **
128 ** Returns void
129 **
130 *******************************************************************************/
port_start_par_neg(tPORT * p_port)131 void port_start_par_neg (tPORT *p_port)
132 {
133 tRFC_MCB *p_mcb = p_port->rfc.p_mcb;
134
135 if (p_mcb == NULL)
136 return;
137
138 RFCOMM_PortNegReq (p_mcb, p_port->dlci, &p_port->user_port_pars);
139 }
140
141
142 /*******************************************************************************
143 **
144 ** Function port_start_close
145 **
146 ** Description This function is called in the BTU_TASK context to
147 ** release DLC
148 **
149 ** Returns void
150 **
151 *******************************************************************************/
port_start_close(tPORT * p_port)152 void port_start_close (tPORT *p_port)
153 {
154 tRFC_MCB *p_mcb = p_port->rfc.p_mcb;
155 UINT8 old_signals;
156 UINT32 events = 0;
157
158 /* At first indicate to the user that signals on the connection were dropped */
159 p_port->line_status |= LINE_STATUS_FAILED;
160 old_signals = p_port->peer_ctrl.modem_signal;
161
162 p_port->peer_ctrl.modem_signal &= ~(PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON);
163
164 events |= port_get_signal_changes (p_port, old_signals, p_port->peer_ctrl.modem_signal);
165
166 if(p_port->ev_mask & PORT_EV_CONNECT_ERR)
167 events |= PORT_EV_CONNECT_ERR;
168
169 if(p_port->ev_mask & PORT_EV_ERR)
170 events |= PORT_EV_ERR;
171
172 if ((p_port->p_callback != NULL) && events)
173 p_port->p_callback (events, p_port->inx);
174
175
176 /* Check if RFCOMM side has been closed while the message was queued */
177 if ((p_mcb == NULL) || (p_port->rfc.state == RFC_STATE_CLOSED))
178 {
179 /* Call management callback function before calling port_release_port() to clear tPort */
180 if (p_port->p_mgmt_callback)
181 p_port->p_mgmt_callback (PORT_CLOSED, p_port->inx);
182
183 port_release_port (p_port);
184 }
185 else
186 {
187 RFCOMM_DlcReleaseReq (p_mcb, p_port->dlci);
188 }
189 }
190
191
192 /*******************************************************************************
193 **
194 ** Function PORT_StartCnf
195 **
196 ** Description This function is called from the RFCOMM layer when
197 ** establishing of the multiplexer channel is completed.
198 ** Continue establishing of the connection for all ports that
199 ** are in the OPENING state
200 **
201 *******************************************************************************/
PORT_StartCnf(tRFC_MCB * p_mcb,UINT16 result)202 void PORT_StartCnf (tRFC_MCB *p_mcb, UINT16 result)
203 {
204 tPORT *p_port;
205 int i;
206 BOOLEAN no_ports_up = TRUE;
207
208 RFCOMM_TRACE_EVENT ("PORT_StartCnf result:%d", result);
209
210 p_port = &rfc_cb.port.port[0];
211 for (i = 0; i < MAX_RFC_PORTS; i++, p_port++)
212 {
213 if (p_port->rfc.p_mcb == p_mcb)
214 {
215 no_ports_up = FALSE;
216
217 if (result == RFCOMM_SUCCESS)
218 RFCOMM_ParNegReq (p_mcb, p_port->dlci, p_port->mtu);
219 else
220 {
221 RFCOMM_TRACE_WARNING ("PORT_StartCnf failed result:%d", result);
222
223 /* Warning: result is also set to 4 when l2cap connection
224 fails due to l2cap connect cnf (no_resources) */
225 if( result == HCI_ERR_PAGE_TIMEOUT )
226 p_port->error = PORT_PAGE_TIMEOUT;
227 else
228 p_port->error = PORT_START_FAILED;
229
230 rfc_release_multiplexer_channel (p_mcb);
231
232 /* Send event to the application */
233 if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECT_ERR))
234 (p_port->p_callback)(PORT_EV_CONNECT_ERR, p_port->inx);
235
236 if (p_port->p_mgmt_callback)
237 p_port->p_mgmt_callback (PORT_START_FAILED, p_port->inx);
238
239 port_release_port (p_port);
240 }
241 }
242 }
243
244 /* There can be a situation when after starting connection, user closes the */
245 /* port, we can catch it here to close multiplexor channel */
246 if (no_ports_up)
247 {
248 rfc_check_mcb_active (p_mcb);
249 }
250 }
251
252
253 /*******************************************************************************
254 **
255 ** Function PORT_StartInd
256 **
257 ** Description This function is called from the RFCOMM layer when
258 ** some peer device wants to establish a multiplexer
259 ** connection. Check if there are any ports open with this
260 ** or not assigned multiplexer.
261 **
262 *******************************************************************************/
PORT_StartInd(tRFC_MCB * p_mcb)263 void PORT_StartInd (tRFC_MCB *p_mcb)
264 {
265 tPORT *p_port;
266 int i;
267
268 RFCOMM_TRACE_EVENT ("PORT_StartInd");
269
270 p_port = &rfc_cb.port.port[0];
271 for (i = 0; i < MAX_RFC_PORTS; i++, p_port++)
272 {
273 if ((p_port->rfc.p_mcb == NULL)
274 || (p_port->rfc.p_mcb == p_mcb))
275 {
276 RFCOMM_TRACE_DEBUG("PORT_StartInd, RFCOMM_StartRsp RFCOMM_SUCCESS: p_mcb:%p", p_mcb);
277 RFCOMM_StartRsp (p_mcb, RFCOMM_SUCCESS);
278 return;
279 }
280 }
281 RFCOMM_StartRsp (p_mcb, RFCOMM_ERROR);
282 }
283
284
285 /*******************************************************************************
286 **
287 ** Function PORT_ParNegInd
288 **
289 ** Description This function is called from the RFCOMM layer to change
290 ** DLCI parameters (currently only MTU is negotiated).
291 ** If can not find the port do not accept the request.
292 ** Otherwise save the MTU size supported by the peer.
293 **
294 *******************************************************************************/
PORT_ParNegInd(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu,UINT8 cl,UINT8 k)295 void PORT_ParNegInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT8 cl, UINT8 k)
296 {
297 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
298 UINT8 our_cl;
299 UINT8 our_k;
300
301 RFCOMM_TRACE_EVENT ("PORT_ParNegInd dlci:%d mtu:%d", dlci, mtu);
302
303 if (!p_port)
304 {
305 /* This can be a first request for this port */
306 p_port = port_find_dlci_port (dlci);
307 if (!p_port)
308 {
309 /* If the port cannot be opened, send a DM. Per Errata 1205 */
310 rfc_send_dm(p_mcb, dlci, FALSE);
311 /* check if this is the last port open, some headsets have
312 problem, they don't disconnect if we send DM */
313 rfc_check_mcb_active( p_mcb );
314 RFCOMM_TRACE_EVENT( "PORT_ParNegInd: port not found" );
315 return;
316 }
317 p_mcb->port_inx[dlci] = p_port->inx;
318 }
319
320 memcpy (p_port->bd_addr, p_mcb->bd_addr, BD_ADDR_LEN);
321
322 /* Connection is up and we know local and remote features, select MTU */
323 port_select_mtu (p_port);
324
325 p_port->rfc.p_mcb = p_mcb;
326 p_port->mtu = (p_port->mtu < mtu) ? p_port->mtu : mtu;
327 p_port->peer_mtu = p_port->mtu;
328
329 /* Negotiate the flow control mechanism. If flow control mechanism for */
330 /* mux has not been set yet, set it now. If either we or peer wants TS 07.10, */
331 /* use that. Otherwise both must want credit based, so use that. If flow is */
332 /* already defined for this mux, we respond with that value. */
333 if (p_mcb->flow == PORT_FC_UNDEFINED)
334 {
335 if ((PORT_FC_DEFAULT == PORT_FC_TS710) || (cl == RFCOMM_PN_CONV_LAYER_TYPE_1))
336 {
337 p_mcb->flow = PORT_FC_TS710;
338 }
339 else
340 {
341 p_mcb->flow = PORT_FC_CREDIT;
342 }
343 }
344
345 /* Regardless of our flow control mechanism, if the PN cl is zero, we must */
346 /* respond with zero. "A responding implementation must set this field to 14 */
347 /* if (and only if) the PN request was 15." This could happen if a PN is sent */
348 /* after the DLCI is already established-- the PN in that case must have cl = 0. */
349 /* See RFCOMM spec 5.5.3 */
350 if (cl == RFCOMM_PN_CONV_LAYER_TYPE_1)
351 {
352 our_cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
353 our_k = 0;
354 }
355 else if (p_mcb->flow == PORT_FC_CREDIT)
356 {
357 /* get credits */
358 port_get_credits (p_port, k);
359
360 /* Set convergence layer and number of credits (k) */
361 our_cl = RFCOMM_PN_CONV_LAYER_CBFC_R;
362 our_k = (p_port->credit_rx_max < RFCOMM_K_MAX) ? p_port->credit_rx_max : RFCOMM_K_MAX;
363 p_port->credit_rx = our_k;
364 }
365 else
366 {
367 /* must not be using credit based flow control; use TS 7.10 */
368 our_cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
369 our_k = 0;
370 }
371 RFCOMM_ParNegRsp (p_mcb, dlci, p_port->mtu, our_cl, our_k);
372 }
373
374
375 /*******************************************************************************
376 **
377 ** Function PORT_ParNegCnf
378 **
379 ** Description This function is called from the RFCOMM layer to change
380 ** DLCI parameters (currently only MTU is negotiated).
381 ** Save the MTU size supported by the peer.
382 ** If the confirmation is received during the port opening
383 ** procedure send EstablishRequest to continue.
384 **
385 *******************************************************************************/
PORT_ParNegCnf(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu,UINT8 cl,UINT8 k)386 void PORT_ParNegCnf (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT8 cl, UINT8 k)
387 {
388 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
389
390 RFCOMM_TRACE_EVENT ("PORT_ParNegCnf dlci:%d mtu:%d cl: %d k: %d", dlci, mtu, cl, k);
391
392 if (!p_port)
393 return;
394
395 /* Flow control mechanism not set yet. Negotiate flow control mechanism. */
396 if (p_mcb->flow == PORT_FC_UNDEFINED)
397 {
398 /* Our stack is configured for TS07.10 and they responded with credit-based. */
399 /* This is illegal-- negotiation fails. */
400 if ((PORT_FC_DEFAULT == PORT_FC_TS710) && (cl == RFCOMM_PN_CONV_LAYER_CBFC_R))
401 {
402 rfc_send_disc (p_mcb, p_port->dlci);
403 rfc_port_closed (p_port);
404 return;
405 }
406 /* Our stack is configured for credit-based and they responded with credit-based. */
407 else if (cl == RFCOMM_PN_CONV_LAYER_CBFC_R)
408 {
409 p_mcb->flow = PORT_FC_CREDIT;
410 }
411 /* They responded with any other value. Treat this as negotiation to TS07.10. */
412 else
413 {
414 p_mcb->flow = PORT_FC_TS710;
415 }
416 }
417 /* If mux flow control mechanism set, we honor that setting regardless of */
418 /* the CL value in their response. This allows us to gracefully accept any */
419 /* illegal PN negotiation scenarios. */
420
421 p_port->mtu = (p_port->mtu < mtu) ? p_port->mtu : mtu;
422 p_port->peer_mtu = p_port->mtu;
423
424 if (p_mcb->flow == PORT_FC_CREDIT)
425 {
426 port_get_credits (p_port, k);
427 }
428
429 if (p_port->state == PORT_STATE_OPENING)
430 RFCOMM_DlcEstablishReq (p_mcb, p_port->dlci, p_port->mtu);
431 }
432
433
434 /*******************************************************************************
435 **
436 ** Function PORT_DlcEstablishInd
437 **
438 ** Description This function is called from the RFCOMM layer when peer
439 ** device wants to establish a new DLC. If this is not the
440 ** first message in the establishment procedure port_handle
441 ** has a handle to the port control block otherwise the control
442 ** block should be found based on the muliplexer channel and
443 ** dlci. The block should be allocated allocated before
444 ** meaning that application already made open.
445 **
446 *******************************************************************************/
PORT_DlcEstablishInd(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu)447 void PORT_DlcEstablishInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu)
448 {
449 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
450
451 RFCOMM_TRACE_DEBUG ("PORT_DlcEstablishInd p_mcb:%p, dlci:%d mtu:%di, p_port:%p", p_mcb, dlci, mtu, p_port);
452 RFCOMM_TRACE_DEBUG ("PORT_DlcEstablishInd p_mcb addr:%02x:%02x:%02x:%02x:%02x:%02x",
453 p_mcb->bd_addr[0], p_mcb->bd_addr[1], p_mcb->bd_addr[2],
454 p_mcb->bd_addr[3], p_mcb->bd_addr[4], p_mcb->bd_addr[5]);
455
456 if (!p_port)
457 {
458 /* This can be a first request for this port */
459 p_port = port_find_dlci_port (dlci);
460 if (!p_port)
461 {
462 RFCOMM_DlcEstablishRsp (p_mcb, dlci, 0, RFCOMM_ERROR);
463 return;
464 }
465 p_mcb->port_inx[dlci] = p_port->inx;
466 }
467
468 /* If L2CAP's mtu less then RFCOMM's take it */
469 if (mtu && (mtu < p_port->peer_mtu))
470 p_port->peer_mtu = mtu;
471
472 /* If there was an inactivity timer running for MCB stop it */
473 rfc_timer_stop (p_mcb);
474
475 RFCOMM_DlcEstablishRsp (p_mcb, dlci, p_port->mtu, RFCOMM_SUCCESS);
476
477 /* This is the server side. If application wants to know when connection */
478 /* is established, thats the place */
479 if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECTED))
480 (p_port->p_callback)(PORT_EV_CONNECTED, p_port->inx);
481
482 if (p_port->p_mgmt_callback)
483 p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx);
484
485 p_port->state = PORT_STATE_OPENED;
486 }
487
488
489 /*******************************************************************************
490 **
491 ** Function PORT_DlcEstablishCnf
492 **
493 ** Description This function is called from the RFCOMM layer when peer
494 ** acknowledges establish procedure (SABME/UA). Send reply
495 ** to the user and set state to OPENED if result was
496 ** successfull.
497 **
498 *******************************************************************************/
PORT_DlcEstablishCnf(tRFC_MCB * p_mcb,UINT8 dlci,UINT16 mtu,UINT16 result)499 void PORT_DlcEstablishCnf (tRFC_MCB *p_mcb, UINT8 dlci, UINT16 mtu, UINT16 result)
500 {
501 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
502
503 RFCOMM_TRACE_EVENT ("PORT_DlcEstablishCnf dlci:%d mtu:%d result:%d", dlci, mtu, result);
504
505 if (!p_port)
506 return;
507
508 if (result != RFCOMM_SUCCESS)
509 {
510 p_port->error = PORT_START_FAILED;
511 port_rfc_closed (p_port, PORT_START_FAILED);
512 return;
513 }
514
515 /* If L2CAP's mtu less then RFCOMM's take it */
516 if (mtu && (mtu < p_port->peer_mtu))
517 p_port->peer_mtu = mtu;
518
519 /* If there was an inactivity timer running for MCB stop it */
520 rfc_timer_stop (p_mcb);
521
522 if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECTED))
523 (p_port->p_callback)(PORT_EV_CONNECTED, p_port->inx);
524
525 if (p_port->p_mgmt_callback)
526 p_port->p_mgmt_callback (PORT_SUCCESS, p_port->inx);
527
528 p_port->state = PORT_STATE_OPENED;
529
530 /* RPN is required only if we want to tell DTE how the port should be opened */
531 if ((p_port->uuid == UUID_SERVCLASS_DIALUP_NETWORKING)
532 || (p_port->uuid == UUID_SERVCLASS_FAX))
533 RFCOMM_PortNegReq (p_port->rfc.p_mcb, p_port->dlci, NULL);
534 else
535 RFCOMM_ControlReq (p_port->rfc.p_mcb, p_port->dlci, &p_port->local_ctrl);
536 }
537
538
539 /*******************************************************************************
540 **
541 ** Function PORT_PortNegInd
542 **
543 ** Description This function is called from the RFCOMM layer when peer
544 ** device wants to set parameters of the port. As per the spec
545 ** this message has to be sent before the first data packet
546 ** and can be sent before establish. The block should be
547 ** allocated before meaning that application already made open.
548 **
549 *******************************************************************************/
PORT_PortNegInd(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_STATE * p_pars,UINT16 param_mask)550 void PORT_PortNegInd (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_STATE *p_pars,
551 UINT16 param_mask)
552 {
553 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
554
555 RFCOMM_TRACE_EVENT ("PORT_PortNegInd");
556
557 if (!p_port)
558 {
559 /* This can be a first request for this port */
560 p_port = port_find_dlci_port (dlci);
561 if (!p_port)
562 {
563 RFCOMM_PortNegRsp (p_mcb, dlci, p_pars, 0);
564 return;
565 }
566 p_mcb->port_inx[dlci] = p_port->inx;
567 }
568
569 /* Check if the flow control is acceptable on local side */
570 p_port->peer_port_pars = *p_pars;
571 RFCOMM_PortNegRsp (p_mcb, dlci, p_pars, param_mask);
572 }
573
574
575 /*******************************************************************************
576 **
577 ** Function PORT_PortNegCnf
578 **
579 ** Description This function is called from the RFCOMM layer to change
580 ** state for the port. Propagate change to the user.
581 **
582 *******************************************************************************/
PORT_PortNegCnf(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_STATE * p_pars,UINT16 result)583 void PORT_PortNegCnf (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_STATE *p_pars, UINT16 result)
584 {
585 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
586 UNUSED(p_pars);
587
588 RFCOMM_TRACE_EVENT ("PORT_PortNegCnf");
589
590 if (!p_port)
591 {
592 RFCOMM_TRACE_WARNING ("PORT_PortNegCnf no port");
593 return;
594 }
595 /* Port negotiation failed. Drop the connection */
596 if (result != RFCOMM_SUCCESS)
597 {
598 p_port->error = PORT_PORT_NEG_FAILED;
599
600 RFCOMM_DlcReleaseReq (p_mcb, p_port->dlci);
601
602 port_rfc_closed (p_port, PORT_PORT_NEG_FAILED);
603 return;
604 }
605
606 if (!(p_port->port_ctrl & PORT_CTRL_REQ_SENT))
607 {
608 RFCOMM_ControlReq (p_port->rfc.p_mcb, p_port->dlci, &p_port->local_ctrl);
609 }
610 else
611 {
612 RFCOMM_TRACE_WARNING ("PORT_PortNegCnf Control Already sent");
613 }
614 }
615
616
617 /*******************************************************************************
618 **
619 ** Function PORT_ControlInd
620 **
621 ** Description This function is called from the RFCOMM layer on the modem
622 ** signal change. Propagate change to the user.
623 **
624 *******************************************************************************/
PORT_ControlInd(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_CTRL * p_pars)625 void PORT_ControlInd (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_CTRL *p_pars)
626 {
627 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
628 UINT32 event;
629 UINT8 old_signals;
630
631 RFCOMM_TRACE_EVENT ("PORT_ControlInd");
632
633 if (!p_port)
634 return;
635
636 old_signals = p_port->peer_ctrl.modem_signal;
637
638 event = port_get_signal_changes (p_port, old_signals, p_pars->modem_signal);
639
640 p_port->peer_ctrl = *p_pars;
641
642 if (!(p_port->port_ctrl & PORT_CTRL_REQ_SENT))
643 RFCOMM_ControlReq (p_port->rfc.p_mcb, p_port->dlci, &p_port->local_ctrl);
644 else
645 {
646 /* If this is the first time we received control RFCOMM is connected */
647 if (!(p_port->port_ctrl & PORT_CTRL_IND_RECEIVED))
648 {
649 event |= (PORT_EV_CONNECTED & p_port->ev_mask);
650 }
651
652 if (p_port->port_ctrl & PORT_CTRL_REQ_CONFIRMED)
653 {
654 event |= port_rfc_send_tx_data(p_port);
655 }
656 }
657
658 p_port->port_ctrl |= (PORT_CTRL_IND_RECEIVED | PORT_CTRL_IND_RESPONDED);
659
660 if (p_pars->break_signal)
661 event |= (PORT_EV_BREAK & p_port->ev_mask);
662
663 /* execute call back function only if the application is registered for events */
664 if (event && p_port->p_callback)
665 (p_port->p_callback)(event, p_port->inx);
666
667 RFCOMM_TRACE_EVENT ("PORT_ControlInd DTR_DSR : %d, RTS_CTS : %d, RI : %d, DCD : %d",
668 ((p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_DTRDSR) ? 1 : 0),
669 ((p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_RTSCTS) ? 1 : 0),
670 ((p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_RI) ? 1 : 0),
671 ((p_port->peer_ctrl.modem_signal & MODEM_SIGNAL_DCD) ? 1 : 0));
672
673 }
674
675
676 /*******************************************************************************
677 **
678 ** Function PORT_ControlCnf
679 **
680 ** Description This function is called from the RFCOMM layer when
681 ** peer acknowleges change of the modem signals.
682 **
683 *******************************************************************************/
PORT_ControlCnf(tRFC_MCB * p_mcb,UINT8 dlci,tPORT_CTRL * p_pars)684 void PORT_ControlCnf (tRFC_MCB *p_mcb, UINT8 dlci, tPORT_CTRL *p_pars)
685 {
686 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
687 UINT32 event = 0;
688 UNUSED(p_pars);
689
690 RFCOMM_TRACE_EVENT ("PORT_ControlCnf");
691
692 if (!p_port)
693 return;
694
695 if (!(p_port->port_ctrl & PORT_CTRL_REQ_CONFIRMED))
696 {
697 p_port->port_ctrl |= PORT_CTRL_REQ_CONFIRMED;
698
699 if (p_port->port_ctrl & PORT_CTRL_IND_RECEIVED)
700 event = (p_port->ev_mask & PORT_EV_CONNECTED);
701 }
702
703 if (p_port->port_ctrl & PORT_CTRL_IND_RECEIVED)
704 {
705 event |= port_rfc_send_tx_data(p_port);
706 }
707
708 /* execute call back function only if the application is registered for events */
709 if (event && p_port->p_callback)
710 (p_port->p_callback)(event, p_port->inx);
711 }
712
713
714 /*******************************************************************************
715 **
716 ** Function PORT_LineStatusInd
717 **
718 ** Description This function is called from the RFCOMM layer when
719 ** peer indicates change in the line status
720 **
721 *******************************************************************************/
PORT_LineStatusInd(tRFC_MCB * p_mcb,UINT8 dlci,UINT8 line_status)722 void PORT_LineStatusInd (tRFC_MCB *p_mcb, UINT8 dlci, UINT8 line_status)
723 {
724 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
725 UINT32 event = 0;
726
727 RFCOMM_TRACE_EVENT ("PORT_LineStatusInd");
728
729 if (!p_port)
730 return;
731
732 p_port->line_status |= line_status;
733
734 if (line_status & PORT_ERR_OVERRUN)
735 event |= PORT_EV_OVERRUN;
736
737 if (line_status & PORT_ERR_BREAK)
738 event |= PORT_EV_BREAK;
739
740 if (line_status & ~(PORT_ERR_OVERRUN | PORT_ERR_BREAK))
741 event |= PORT_EV_ERR;
742
743 if ((p_port->p_callback != NULL) && (p_port->ev_mask & event))
744 p_port->p_callback ((p_port->ev_mask & event), p_port->inx);
745 }
746
747
748 /*******************************************************************************
749 **
750 ** Function PORT_DlcReleaseInd
751 **
752 ** Description This function is called from the RFCOMM layer when
753 ** DLC connection is released.
754 **
755 *******************************************************************************/
PORT_DlcReleaseInd(tRFC_MCB * p_mcb,UINT8 dlci)756 void PORT_DlcReleaseInd (tRFC_MCB *p_mcb, UINT8 dlci)
757 {
758 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
759
760 RFCOMM_TRACE_EVENT ("PORT_DlcReleaseInd");
761
762 if (!p_port)
763 return;
764
765 port_rfc_closed (p_port, PORT_CLOSED);
766 }
767
768
769 /*******************************************************************************
770 **
771 ** Function PORT_CloseInd
772 **
773 ** Description This function is called from the RFCOMM layer when
774 ** multiplexer connection is released.
775 **
776 *******************************************************************************/
PORT_CloseInd(tRFC_MCB * p_mcb)777 void PORT_CloseInd (tRFC_MCB *p_mcb)
778 {
779 tPORT *p_port;
780 int i;
781
782 RFCOMM_TRACE_EVENT ("PORT_CloseInd");
783
784 p_port = &rfc_cb.port.port[0];
785 for (i = 0; i < MAX_RFC_PORTS; i++, p_port++)
786 {
787 if (p_port->rfc.p_mcb == p_mcb)
788 {
789 port_rfc_closed (p_port, PORT_PEER_CONNECTION_FAILED);
790 }
791 }
792 rfc_release_multiplexer_channel (p_mcb);
793 }
794
795 /*******************************************************************************
796 **
797 ** Function Port_TimeOutCloseMux
798 **
799 ** Description This function is called when RFCOMM timesout on a command
800 ** as a result multiplexer connection is closed.
801 **
802 *******************************************************************************/
Port_TimeOutCloseMux(tRFC_MCB * p_mcb)803 void Port_TimeOutCloseMux (tRFC_MCB *p_mcb)
804 {
805 tPORT *p_port;
806 int i;
807
808 RFCOMM_TRACE_EVENT ("Port_TimeOutCloseMux");
809
810 p_port = &rfc_cb.port.port[0];
811 for (i = 0; i < MAX_RFC_PORTS; i++, p_port++)
812 {
813 if (p_port->rfc.p_mcb == p_mcb)
814 {
815 port_rfc_closed (p_port, PORT_PEER_TIMEOUT);
816 }
817 }
818 }
819
820
821 /*******************************************************************************
822 **
823 ** Function PORT_DataInd
824 **
825 ** Description This function is called from the RFCOMM layer when data
826 ** buffer is received from the peer.
827 **
828 *******************************************************************************/
PORT_DataInd(tRFC_MCB * p_mcb,UINT8 dlci,BT_HDR * p_buf)829 void PORT_DataInd (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf)
830 {
831 tPORT *p_port = port_find_mcb_dlci_port (p_mcb, dlci);
832 UINT8 rx_char1;
833 UINT32 events = 0;
834 UINT8 *p;
835 int i;
836
837 RFCOMM_TRACE_EVENT("PORT_DataInd with data length %d, p_mcb:%p,p_port:%p,dlci:%d",
838 p_buf->len, p_mcb, p_port, dlci);
839 if (!p_port)
840 {
841 osi_free(p_buf);
842 return;
843 }
844 /* If client registered callout callback with flow control we can just deliver receive data */
845 if (p_port->p_data_co_callback)
846 {
847 /* Another packet is delivered to user. Send credits to peer if required */
848
849 if(p_port->p_data_co_callback(p_port->inx, (UINT8*)p_buf, -1, DATA_CO_CALLBACK_TYPE_INCOMING))
850 port_flow_control_peer(p_port, TRUE, 1);
851 else port_flow_control_peer(p_port, FALSE, 0);
852 //osi_free(p_buf);
853 return;
854 }
855 else RFCOMM_TRACE_ERROR("PORT_DataInd, p_port:%p, p_data_co_callback is null", p_port);
856 /* If client registered callback we can just deliver receive data */
857 if (p_port->p_data_callback)
858 {
859 /* Another packet is delivered to user. Send credits to peer if required */
860 port_flow_control_peer(p_port, TRUE, 1);
861
862 p_port->p_data_callback (p_port->inx, (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len);
863 osi_free(p_buf);
864 return;
865 }
866
867 /* Check if rx queue exceeds the limit */
868 if ((p_port->rx.queue_size + p_buf->len > PORT_RX_CRITICAL_WM)
869 || (fixed_queue_length(p_port->rx.queue) + 1 > p_port->rx_buf_critical))
870 {
871 RFCOMM_TRACE_EVENT ("PORT_DataInd. Buffer over run. Dropping the buffer");
872 osi_free(p_buf);
873
874 RFCOMM_LineStatusReq (p_mcb, dlci, LINE_STATUS_OVERRUN);
875 return;
876 }
877
878 /* If user registered to receive notification when a particular byte is */
879 /* received we mast check all received bytes */
880 if (((rx_char1 = p_port->user_port_pars.rx_char1) != 0)
881 && (p_port->ev_mask & PORT_EV_RXFLAG))
882 {
883 for (i = 0, p = (UINT8 *)(p_buf + 1) + p_buf->offset; i < p_buf->len; i++)
884 {
885 if (*p++ == rx_char1)
886 {
887 events |= PORT_EV_RXFLAG;
888 break;
889 }
890 }
891 }
892
893 mutex_global_lock();
894
895 fixed_queue_enqueue(p_port->rx.queue, p_buf);
896 p_port->rx.queue_size += p_buf->len;
897
898 mutex_global_unlock();
899
900 /* perform flow control procedures if necessary */
901 port_flow_control_peer(p_port, FALSE, 0);
902
903 /* If user indicated flow control can not deliver any notifications to him */
904 if (p_port->rx.user_fc)
905 {
906 if (events & PORT_EV_RXFLAG)
907 p_port->rx_flag_ev_pending = TRUE;
908
909 return;
910 }
911
912 events |= PORT_EV_RXCHAR;
913
914 /* Mask out all events that are not of interest to user */
915 events &= p_port->ev_mask;
916
917 if (p_port->p_callback && events)
918 p_port->p_callback (events, p_port->inx);
919 }
920
921
922 /*******************************************************************************
923 **
924 ** Function PORT_FlowInd
925 **
926 ** Description This function is called from the RFCOMM layer on the flow
927 ** control signal change. Propagate change to the user.
928 **
929 *******************************************************************************/
PORT_FlowInd(tRFC_MCB * p_mcb,UINT8 dlci,BOOLEAN enable_data)930 void PORT_FlowInd (tRFC_MCB *p_mcb, UINT8 dlci, BOOLEAN enable_data)
931 {
932 tPORT *p_port = (tPORT *)NULL;
933 UINT32 events = 0;
934 int i;
935
936 RFCOMM_TRACE_EVENT ("PORT_FlowInd fc:%d", enable_data);
937
938 if (dlci == 0)
939 {
940 p_mcb->peer_ready = enable_data;
941 }
942 else
943 {
944 if ((p_port = port_find_mcb_dlci_port (p_mcb, dlci)) == NULL)
945 return;
946
947 p_port->tx.peer_fc = !enable_data;
948 }
949
950 for (i = 0; i < MAX_RFC_PORTS; i++)
951 {
952 /* If DLCI is 0 event applies to all ports */
953 if (dlci == 0)
954 {
955 p_port = &rfc_cb.port.port[i];
956 if (!p_port->in_use
957 || (p_port->rfc.p_mcb != p_mcb)
958 || (p_port->rfc.state != RFC_STATE_OPENED))
959 continue;
960 }
961 events = 0;
962
963 /* Check if flow of data is still enabled */
964 events |= port_flow_control_user (p_port);
965
966 /* Check if data can be sent and send it */
967 events |= port_rfc_send_tx_data (p_port);
968
969 /* Mask out all events that are not of interest to user */
970 events &= p_port->ev_mask;
971
972 /* Send event to the application */
973 if (p_port->p_callback && events)
974 (p_port->p_callback)(events, p_port->inx);
975
976 /* If DLCI is not 0 event applies to one port only */
977 if (dlci != 0)
978 break;
979 }
980 }
981
982
983 /*******************************************************************************
984 **
985 ** Function port_rfc_send_tx_data
986 **
987 ** Description This function is when forward data can be sent to the peer
988 **
989 *******************************************************************************/
port_rfc_send_tx_data(tPORT * p_port)990 UINT32 port_rfc_send_tx_data (tPORT *p_port)
991 {
992 UINT32 events = 0;
993 BT_HDR *p_buf;
994
995 /* if there is data to be sent */
996 if (p_port->tx.queue_size > 0)
997 {
998 /* while the rfcomm peer is not flow controlling us, and peer is ready */
999 while (!p_port->tx.peer_fc && p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready)
1000 {
1001 /* get data from tx queue and send it */
1002 mutex_global_lock();
1003
1004 if ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->tx.queue)) != NULL)
1005 {
1006 p_port->tx.queue_size -= p_buf->len;
1007
1008 mutex_global_unlock();
1009
1010 RFCOMM_TRACE_DEBUG ("Sending RFCOMM_DataReq tx.queue_size=%d", p_port->tx.queue_size);
1011
1012 RFCOMM_DataReq (p_port->rfc.p_mcb, p_port->dlci, p_buf);
1013
1014 events |= PORT_EV_TXCHAR;
1015
1016 if (p_port->tx.queue_size == 0)
1017 {
1018 events |= PORT_EV_TXEMPTY;
1019 break;
1020 }
1021 }
1022 /* queue is empty-- all data sent */
1023 else
1024 {
1025 mutex_global_unlock();
1026
1027 events |= PORT_EV_TXEMPTY;
1028 break;
1029 }
1030 }
1031 /* If we flow controlled user based on the queue size enable data again */
1032 events |= port_flow_control_user (p_port);
1033 }
1034 return (events & p_port->ev_mask);
1035 }
1036
1037
1038 /*******************************************************************************
1039 **
1040 ** Function port_rfc_closed
1041 **
1042 ** Description This function when RFCOMM side of port is closed
1043 **
1044 *******************************************************************************/
port_rfc_closed(tPORT * p_port,UINT8 res)1045 void port_rfc_closed (tPORT *p_port, UINT8 res)
1046 {
1047 UINT8 old_signals;
1048 UINT32 events = 0;
1049 tRFC_MCB *p_mcb = p_port->rfc.p_mcb;
1050
1051 if ((p_port->state == PORT_STATE_OPENING) && (p_port->is_server))
1052 {
1053 /* The servr side has not been informed that connection is up, ignore */
1054 RFCOMM_TRACE_EVENT ("port_rfc_closed in OPENING state ignored");
1055
1056 rfc_port_timer_stop (p_port);
1057 p_port->rfc.state = RFC_STATE_CLOSED;
1058
1059 if (p_mcb)
1060 {
1061 p_mcb->port_inx[p_port->dlci] = 0;
1062
1063 /* If there are no more ports opened on this MCB release it */
1064 rfc_check_mcb_active (p_mcb);
1065 p_port->rfc.p_mcb = NULL;
1066 }
1067
1068 /* Need to restore DLCI to listening state
1069 * if the server was on the initiating RFC
1070 */
1071 p_port->dlci &= 0xfe;
1072
1073 return;
1074 }
1075
1076 if ((p_port->state != PORT_STATE_CLOSING) && (p_port->state != PORT_STATE_CLOSED))
1077 {
1078 p_port->line_status |= LINE_STATUS_FAILED;
1079
1080 old_signals = p_port->peer_ctrl.modem_signal;
1081
1082 p_port->peer_ctrl.modem_signal &= ~(PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON);
1083
1084 events |= port_get_signal_changes (p_port, old_signals, p_port->peer_ctrl.modem_signal);
1085
1086 if(p_port->ev_mask & PORT_EV_CONNECT_ERR)
1087 events |= PORT_EV_CONNECT_ERR;
1088 }
1089 RFCOMM_TRACE_EVENT ("port_rfc_closed state:%d sending events:%x", p_port->state, events);
1090
1091 if ((p_port->p_callback != NULL) && events)
1092 p_port->p_callback (events, p_port->inx);
1093
1094 if (p_port->p_mgmt_callback)
1095 p_port->p_mgmt_callback (res, p_port->inx);
1096
1097 p_port->rfc.state = RFC_STATE_CLOSED;
1098
1099 RFCOMM_TRACE_WARNING ("%s RFCOMM connection in state %d closed: %s (res: %d)",
1100 __func__, p_port->state, PORT_GetResultString(res), res);
1101
1102 port_release_port (p_port);
1103 }
1104
1105
1106 /*******************************************************************************
1107 **
1108 ** Function port_get_credits
1109 **
1110 ** Description Set initial values for credits.
1111 ** Adjust max number of rx credits based on negotiated MTU.
1112 ** Check max allowed num of bytes, max allowed num buffers,
1113 ** should be less then 255
1114 **
1115 *******************************************************************************/
port_get_credits(tPORT * p_port,UINT8 k)1116 void port_get_credits (tPORT *p_port, UINT8 k)
1117 {
1118 p_port->credit_tx = k;
1119 if (p_port->credit_tx == 0)
1120 p_port->tx.peer_fc = TRUE;
1121 }
1122