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