OSDN Git Service

DO NOT MERGE ANYWHERE Disable 3Mbps packets for AVDT ACL links am: a8bb3ae08b -s...
[android-x86/system-bt.git] / stack / rfcomm / port_utils.c
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  *  Port Emulation entity utilities
22  *
23  ******************************************************************************/
24 #include <string.h>
25
26 #include "osi/include/mutex.h"
27
28 #include "bt_target.h"
29 #include "bt_common.h"
30 #include "btm_int.h"
31 #include "btu.h"
32 #include "l2cdefs.h"
33 #include "port_api.h"
34 #include "port_int.h"
35 #include "rfc_int.h"
36 #include "rfcdefs.h"
37
38 static const tPORT_STATE default_port_pars =
39 {
40     PORT_BAUD_RATE_9600,
41     PORT_8_BITS,
42     PORT_ONESTOPBIT,
43     PORT_PARITY_NO,
44     PORT_ODD_PARITY,
45     PORT_FC_OFF,
46     0,                      /* No rx_char */
47     PORT_XON_DC1,
48     PORT_XOFF_DC3,
49 };
50
51
52
53 /*******************************************************************************
54 **
55 ** Function         port_allocate_port
56 **
57 ** Description      Look through the Port Control Blocks for a free one.  Note
58 **                  that one server can open several ports with the same SCN
59 **                  if it can support simulteneous requests from different
60 **                  clients.
61 **
62 ** Returns          Pointer to the PORT or NULL if not found
63 **
64 *******************************************************************************/
65 tPORT *port_allocate_port (UINT8 dlci, BD_ADDR bd_addr)
66 {
67     tPORT  *p_port = &rfc_cb.port.port[0];
68     UINT8  xx, yy;
69
70     for (xx = 0, yy = rfc_cb.rfc.last_port + 1; xx < MAX_RFC_PORTS; xx++, yy++)
71     {
72         if (yy >= MAX_RFC_PORTS)
73             yy = 0;
74
75         p_port = &rfc_cb.port.port[yy];
76         if (!p_port->in_use)
77         {
78             memset(p_port, 0, sizeof (tPORT));
79
80             p_port->in_use = TRUE;
81             p_port->inx    = yy + 1;
82
83             /* During the open set default state for the port connection */
84             port_set_defaults (p_port);
85
86             p_port->rfc.port_timer = alarm_new("rfcomm_port.port_timer");
87             rfc_cb.rfc.last_port = yy;
88
89             p_port->dlci   = dlci;
90             memcpy (p_port->bd_addr, bd_addr, BD_ADDR_LEN);
91
92             RFCOMM_TRACE_DEBUG("rfc_cb.port.port[%d]:%p allocated, last_port:%d", yy, p_port, rfc_cb.rfc.last_port);
93             RFCOMM_TRACE_DEBUG("port_allocate_port:bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
94                                 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
95             return (p_port);
96         }
97     }
98
99     /* If here, no free PORT found */
100     return (NULL);
101 }
102
103
104 /*******************************************************************************
105 **
106 ** Function         port_set_defaults
107 **
108 ** Description      Set defualt port parameters
109 **
110 **
111 *******************************************************************************/
112 void port_set_defaults (tPORT *p_port)
113 {
114     p_port->ev_mask        = 0;
115     p_port->p_callback     = NULL;
116     p_port->port_ctrl      = 0;
117     p_port->error          = 0;
118     p_port->line_status    = 0;
119     p_port->rx_flag_ev_pending = FALSE;
120     p_port->peer_mtu       = RFCOMM_DEFAULT_MTU;
121
122     p_port->user_port_pars = default_port_pars;
123     p_port->peer_port_pars = default_port_pars;
124
125     p_port->credit_tx      = 0;
126     p_port->credit_rx      = 0;
127
128     memset (&p_port->local_ctrl, 0, sizeof (p_port->local_ctrl));
129     memset (&p_port->peer_ctrl, 0, sizeof (p_port->peer_ctrl));
130     memset (&p_port->rx, 0, sizeof (p_port->rx));
131     memset (&p_port->tx, 0, sizeof (p_port->tx));
132
133     p_port->tx.queue = fixed_queue_new(SIZE_MAX);
134     p_port->rx.queue = fixed_queue_new(SIZE_MAX);
135 }
136
137 /*******************************************************************************
138 **
139 ** Function         port_select_mtu
140 **
141 ** Description      Select MTU which will best serve connection from our
142 **                  point of view.
143 **                  If our device is 1.2 or lower we calculate how many DH5s
144 **                  fit into 1 RFCOMM buffer.
145 **
146 **
147 *******************************************************************************/
148 void port_select_mtu (tPORT *p_port)
149 {
150     UINT16 packet_size;
151
152     /* Will select MTU only if application did not setup something */
153     if (p_port->mtu == 0)
154     {
155         /* find packet size which connection supports */
156         packet_size = btm_get_max_packet_size (p_port->bd_addr);
157         if (packet_size == 0)
158         {
159             /* something is very wrong */
160             RFCOMM_TRACE_WARNING ("port_select_mtu bad packet size");
161             p_port->mtu = RFCOMM_DEFAULT_MTU;
162         }
163         else
164         {
165             /* We try to negotiate MTU that each packet can be split into whole
166             number of max packets.  For example if link is 1.2 max packet size is 339 bytes.
167             At first calculate how many whole packets it is.  MAX L2CAP is 1691 + 4 overhead.
168             1695, that will be 5 Dh5 packets.  Now maximum RFCOMM packet is
169             5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.  Minus RFCOMM 6 bytes header overhead 1685
170
171             For EDR 2.0 packet size is 1027.  So we better send RFCOMM packet as 1 3DH5 packet
172             1 * 1027 = 1027.  Minus 4 bytes L2CAP header 1023.  Minus RFCOMM 6 bytes header overhead 1017 */
173             if ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) >= packet_size)
174             {
175                 p_port->mtu = ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) / packet_size * packet_size) - RFCOMM_DATA_OVERHEAD - L2CAP_PKT_OVERHEAD;
176                 RFCOMM_TRACE_DEBUG ("port_select_mtu selected %d based on connection speed", p_port->mtu);
177             }
178             else
179             {
180                 p_port->mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
181                 RFCOMM_TRACE_DEBUG ("port_select_mtu selected %d based on l2cap PDU size", p_port->mtu);
182             }
183         }
184     }
185     else
186     {
187         RFCOMM_TRACE_DEBUG ("port_select_mtu application selected %d", p_port->mtu);
188     }
189     p_port->credit_rx_max  = (PORT_RX_HIGH_WM / p_port->mtu);
190     if( p_port->credit_rx_max > PORT_RX_BUF_HIGH_WM )
191         p_port->credit_rx_max = PORT_RX_BUF_HIGH_WM;
192     p_port->credit_rx_low  = (PORT_RX_LOW_WM / p_port->mtu);
193     if( p_port->credit_rx_low > PORT_RX_BUF_LOW_WM )
194         p_port->credit_rx_low = PORT_RX_BUF_LOW_WM;
195     p_port->rx_buf_critical = (PORT_RX_CRITICAL_WM / p_port->mtu);
196     if( p_port->rx_buf_critical > PORT_RX_BUF_CRITICAL_WM )
197         p_port->rx_buf_critical = PORT_RX_BUF_CRITICAL_WM;
198     RFCOMM_TRACE_DEBUG ("port_select_mtu credit_rx_max %d, credit_rx_low %d, rx_buf_critical %d",
199                           p_port->credit_rx_max, p_port->credit_rx_low, p_port->rx_buf_critical);
200 }
201
202 /*******************************************************************************
203 **
204 ** Function         port_release_port
205 **
206 ** Description      Release port control block.
207 **
208 ** Returns          Pointer to the PORT or NULL if not found
209 **
210 *******************************************************************************/
211 void port_release_port(tPORT *p_port)
212 {
213     RFCOMM_TRACE_DEBUG("%s p_port: %p state: %d keep_handle: %d", __func__,
214         p_port, p_port->rfc.state, p_port->keep_port_handle);
215
216     mutex_global_lock();
217     BT_HDR *p_buf;
218     while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->rx.queue)) != NULL)
219         osi_free(p_buf);
220     p_port->rx.queue_size = 0;
221
222     while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->tx.queue)) != NULL)
223         osi_free(p_buf);
224     p_port->tx.queue_size = 0;
225     mutex_global_unlock();
226
227     alarm_cancel(p_port->rfc.port_timer);
228
229     p_port->state = PORT_STATE_CLOSED;
230
231     if (p_port->rfc.state == RFC_STATE_CLOSED)
232     {
233         if (p_port->rfc.p_mcb)
234         {
235             p_port->rfc.p_mcb->port_inx[p_port->dlci] = 0;
236
237             /* If there are no more ports opened on this MCB release it */
238             rfc_check_mcb_active(p_port->rfc.p_mcb);
239         }
240
241         rfc_port_timer_stop (p_port);
242         fixed_queue_free(p_port->tx.queue, NULL);
243         fixed_queue_free(p_port->rx.queue, NULL);
244
245         if (p_port->keep_port_handle)
246         {
247             RFCOMM_TRACE_DEBUG("%s Re-initialize handle: %d", __func__, p_port->inx);
248
249             /* save event mask and callback */
250             UINT32 mask = p_port->ev_mask;
251             tPORT_CALLBACK *p_port_cb = p_port->p_callback;
252             tPORT_STATE user_port_pars = p_port->user_port_pars;
253
254             port_set_defaults(p_port);
255
256             /* restore */
257             p_port->ev_mask         = mask;
258             p_port->p_callback      = p_port_cb;
259             p_port->user_port_pars  = user_port_pars;
260             p_port->mtu             = p_port->keep_mtu;
261
262             p_port->state           = PORT_STATE_OPENING;
263             p_port->rfc.p_mcb       = NULL;
264             if (p_port->is_server)
265                 p_port->dlci       &= 0xfe;
266
267             p_port->local_ctrl.modem_signal = p_port->default_signal_state;
268             memcpy (p_port->bd_addr, BT_BD_ANY, BD_ADDR_LEN);
269         } else {
270             RFCOMM_TRACE_DEBUG("%s Clean-up handle: %d", __func__, p_port->inx);
271             alarm_free(p_port->rfc.port_timer);
272             memset (p_port, 0, sizeof (tPORT));
273         }
274     }
275 }
276
277 /*******************************************************************************
278 **
279 ** Function         port_find_mcb
280 **
281 ** Description      This function checks if connection exists to device with
282 **                  the BD_ADDR.
283 **
284 *******************************************************************************/
285 tRFC_MCB *port_find_mcb (BD_ADDR bd_addr)
286 {
287     int      i;
288
289     for (i = 0; i < MAX_BD_CONNECTIONS; i++)
290     {
291         if ((rfc_cb.port.rfc_mcb[i].state != RFC_MX_STATE_IDLE)
292          && !memcmp (rfc_cb.port.rfc_mcb[i].bd_addr, bd_addr, BD_ADDR_LEN))
293         {
294             /* Multiplexer channel found do not change anything */
295             RFCOMM_TRACE_DEBUG("port_find_mcb: found  bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
296                                 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
297             RFCOMM_TRACE_DEBUG("port_find_mcb: rfc_cb.port.rfc_mcb:index:%d, %p, lcid:%d",
298                                 i, &rfc_cb.port.rfc_mcb[i], rfc_cb.port.rfc_mcb[i].lcid);
299             return (&rfc_cb.port.rfc_mcb[i]);
300         }
301     }
302     RFCOMM_TRACE_DEBUG("port_find_mcb: not found, bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
303                          bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
304     return (NULL);
305 }
306
307
308 /*******************************************************************************
309 **
310 ** Function         port_find_mcb_dlci_port
311 **
312 ** Description      Find port on the multiplexer channel based on DLCI.  If
313 **                  this port with DLCI not found try to use even DLCI.  This
314 **                  is for the case when client is establishing connection on
315 **                  none-initiator MCB.
316 **
317 ** Returns          Pointer to the PORT or NULL if not found
318 **
319 *******************************************************************************/
320 tPORT *port_find_mcb_dlci_port (tRFC_MCB *p_mcb, UINT8 dlci)
321 {
322     UINT8 inx;
323
324     if (!p_mcb)
325         return (NULL);
326
327     if (dlci > RFCOMM_MAX_DLCI)
328         return (NULL);
329
330     inx = p_mcb->port_inx[dlci];
331     if (inx == 0)
332     {
333         RFCOMM_TRACE_DEBUG("port_find_mcb_dlci_port: p_mcb:%p, port_inx[dlci:%d] is 0", p_mcb, dlci);
334         return (NULL);
335     }
336     else
337         return (&rfc_cb.port.port[inx - 1]);
338 }
339
340
341 /*******************************************************************************
342 **
343 ** Function         port_find_dlci_port
344 **
345 ** Description      Find port with DLCI not assigned to multiplexer channel
346 **
347 ** Returns          Pointer to the PORT or NULL if not found
348 **
349 *******************************************************************************/
350 tPORT *port_find_dlci_port (UINT8 dlci)
351 {
352     UINT16 i;
353     tPORT  *p_port;
354
355     for (i = 0; i < MAX_RFC_PORTS; i++)
356     {
357         p_port = &rfc_cb.port.port[i];
358
359         if (p_port->in_use && (p_port->rfc.p_mcb == NULL))
360         {
361             if (p_port->dlci == dlci)
362             {
363                 return (p_port);
364             }
365             else if ((dlci & 0x01) && (p_port->dlci == (dlci - 1)))
366             {
367                 p_port->dlci++;
368                 return (p_port);
369             }
370         }
371     }
372     return (NULL);
373 }
374
375
376 /*******************************************************************************
377 **
378 ** Function         port_find_port
379 **
380 ** Description      Find port with DLCI, BD_ADDR
381 **
382 ** Returns          Pointer to the PORT or NULL if not found
383 **
384 *******************************************************************************/
385 tPORT *port_find_port (UINT8 dlci, BD_ADDR bd_addr)
386 {
387     UINT16 i;
388     tPORT  *p_port;
389
390     for (i = 0; i < MAX_RFC_PORTS; i++)
391     {
392         p_port = &rfc_cb.port.port[i];
393         if (p_port->in_use
394          && (p_port->dlci == dlci)
395          && !memcmp (p_port->bd_addr, bd_addr, BD_ADDR_LEN))
396         {
397             return (p_port);
398         }
399     }
400     return (NULL);
401 }
402
403
404 /*******************************************************************************
405 **
406 ** Function         port_flow_control_user
407 **
408 ** Description      Check the current user flow control and if necessary return
409 **                  events to be send to the user based on the user's specified
410 **                  flow control type.
411 **
412 ** Returns          event mask to be returned to the application
413 **
414 *******************************************************************************/
415 UINT32 port_flow_control_user (tPORT *p_port)
416 {
417     UINT32 event = 0;
418
419     /* Flow control to the user can be caused by flow controlling by the peer */
420     /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */
421     /* tx_queue is full */
422     BOOLEAN fc = p_port->tx.peer_fc
423               || !p_port->rfc.p_mcb
424               || !p_port->rfc.p_mcb->peer_ready
425               || (p_port->tx.queue_size > PORT_TX_HIGH_WM)
426               || (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM);
427
428     if (p_port->tx.user_fc == fc)
429         return (0);
430
431     p_port->tx.user_fc = fc;
432
433     if (fc)
434         event = PORT_EV_FC;
435     else
436         event = PORT_EV_FC | PORT_EV_FCS;
437
438     return (event);
439 }
440
441
442 /*******************************************************************************
443 **
444 ** Function         port_get_signal_changes
445 **
446 ** Description      Check modem signals that has been changed
447 **
448 ** Returns          event mask to be returned to the application
449 **
450 *******************************************************************************/
451 UINT32 port_get_signal_changes (tPORT *p_port, UINT8 old_signals, UINT8 signal)
452 {
453     UINT8  changed_signals = (signal ^ old_signals);
454     UINT32 events = 0;
455
456     if (changed_signals & PORT_DTRDSR_ON)
457     {
458         events |= PORT_EV_DSR;
459
460         if (signal & PORT_DTRDSR_ON)
461             events |= PORT_EV_DSRS;
462     }
463
464     if (changed_signals & PORT_CTSRTS_ON)
465     {
466         events |= PORT_EV_CTS;
467
468         if (signal & PORT_CTSRTS_ON)
469             events |= PORT_EV_CTSS;
470     }
471
472     if (changed_signals & PORT_RING_ON)
473         events |= PORT_EV_RING;
474
475     if (changed_signals & PORT_DCD_ON)
476     {
477         events |= PORT_EV_RLSD;
478
479         if (signal & PORT_DCD_ON)
480             events |= PORT_EV_RLSDS;
481     }
482
483     return (p_port->ev_mask & events);
484 }
485
486 /*******************************************************************************
487 **
488 ** Function         port_flow_control_peer
489 **
490 ** Description      Send flow control messages to the peer for both enabling
491 **                  and disabling flow control, for both credit-based and
492 **                  TS 07.10 flow control mechanisms.
493 **
494 ** Returns          nothing
495 **
496 *******************************************************************************/
497 void port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count)
498 {
499     if (!p_port->rfc.p_mcb)
500         return;
501
502     /* If using credit based flow control */
503     if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT)
504     {
505         /* if want to enable flow from peer */
506         if (enable)
507         {
508             /* update rx credits */
509             if (count > p_port->credit_rx)
510             {
511                 p_port->credit_rx = 0;
512             }
513             else
514             {
515                 p_port->credit_rx -= count;
516             }
517
518             /* If credit count is less than low credit watermark, and user */
519             /* did not force flow control, send a credit update */
520             /* There might be a special case when we just adjusted rx_max */
521             if ((p_port->credit_rx <= p_port->credit_rx_low)
522              && !p_port->rx.user_fc
523              && (p_port->credit_rx_max > p_port->credit_rx))
524             {
525                 rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
526                                 (UINT8) (p_port->credit_rx_max - p_port->credit_rx));
527
528                 p_port->credit_rx = p_port->credit_rx_max;
529
530                 p_port->rx.peer_fc = FALSE;
531             }
532         }
533         /* else want to disable flow from peer */
534         else
535         {
536             /* if client registered data callback, just do what they want */
537             if (p_port->p_data_callback || p_port->p_data_co_callback)
538             {
539                 p_port->rx.peer_fc = TRUE;
540             }
541             /* if queue count reached credit rx max, set peer fc */
542             else if (fixed_queue_length(p_port->rx.queue) >= p_port->credit_rx_max)
543             {
544                 p_port->rx.peer_fc = TRUE;
545             }
546         }
547     }
548     /* else using TS 07.10 flow control */
549     else
550     {
551         /* if want to enable flow from peer */
552         if (enable)
553         {
554             /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
555             /* check if it can be resumed now */
556             if (p_port->rx.peer_fc
557              && (p_port->rx.queue_size < PORT_RX_LOW_WM)
558              && (fixed_queue_length(p_port->rx.queue) < PORT_RX_BUF_LOW_WM))
559             {
560                 p_port->rx.peer_fc = FALSE;
561
562                 /* If user did not force flow control allow traffic now */
563                 if (!p_port->rx.user_fc)
564                     RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, TRUE);
565             }
566         }
567         /* else want to disable flow from peer */
568         else
569         {
570             /* if client registered data callback, just do what they want */
571             if (p_port->p_data_callback || p_port->p_data_co_callback)
572             {
573                 p_port->rx.peer_fc = TRUE;
574                 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
575             }
576             /* Check the size of the rx queue.  If it exceeds certain */
577             /* level and flow control has not been sent to the peer do it now */
578             else if ( ((p_port->rx.queue_size > PORT_RX_HIGH_WM)
579                      || (fixed_queue_length(p_port->rx.queue) > PORT_RX_BUF_HIGH_WM))
580                      && !p_port->rx.peer_fc)
581             {
582                 RFCOMM_TRACE_EVENT ("PORT_DataInd Data reached HW. Sending FC set.");
583
584                 p_port->rx.peer_fc = TRUE;
585                 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
586             }
587         }
588     }
589 }
590