Home | History | Annotate | Download | only in rfcomm
      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         p_port->tx.queue = NULL;
    244         fixed_queue_free(p_port->rx.queue, NULL);
    245         p_port->rx.queue = NULL;
    246 
    247         if (p_port->keep_port_handle)
    248         {
    249             RFCOMM_TRACE_DEBUG("%s Re-initialize handle: %d", __func__, p_port->inx);
    250 
    251             /* save event mask and callback */
    252             UINT32 mask = p_port->ev_mask;
    253             tPORT_CALLBACK *p_port_cb = p_port->p_callback;
    254             tPORT_STATE user_port_pars = p_port->user_port_pars;
    255 
    256             port_set_defaults(p_port);
    257 
    258             /* restore */
    259             p_port->ev_mask         = mask;
    260             p_port->p_callback      = p_port_cb;
    261             p_port->user_port_pars  = user_port_pars;
    262             p_port->mtu             = p_port->keep_mtu;
    263 
    264             p_port->state           = PORT_STATE_OPENING;
    265             p_port->rfc.p_mcb       = NULL;
    266             if (p_port->is_server)
    267                 p_port->dlci       &= 0xfe;
    268 
    269             p_port->local_ctrl.modem_signal = p_port->default_signal_state;
    270             memcpy (p_port->bd_addr, BT_BD_ANY, BD_ADDR_LEN);
    271         } else {
    272             RFCOMM_TRACE_DEBUG("%s Clean-up handle: %d", __func__, p_port->inx);
    273             alarm_free(p_port->rfc.port_timer);
    274             memset (p_port, 0, sizeof (tPORT));
    275         }
    276     }
    277 }
    278 
    279 /*******************************************************************************
    280 **
    281 ** Function         port_find_mcb
    282 **
    283 ** Description      This function checks if connection exists to device with
    284 **                  the BD_ADDR.
    285 **
    286 *******************************************************************************/
    287 tRFC_MCB *port_find_mcb (BD_ADDR bd_addr)
    288 {
    289     int      i;
    290 
    291     for (i = 0; i < MAX_BD_CONNECTIONS; i++)
    292     {
    293         if ((rfc_cb.port.rfc_mcb[i].state != RFC_MX_STATE_IDLE)
    294          && !memcmp (rfc_cb.port.rfc_mcb[i].bd_addr, bd_addr, BD_ADDR_LEN))
    295         {
    296             /* Multiplexer channel found do not change anything */
    297             RFCOMM_TRACE_DEBUG("port_find_mcb: found  bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
    298                                 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
    299             RFCOMM_TRACE_DEBUG("port_find_mcb: rfc_cb.port.rfc_mcb:index:%d, %p, lcid:%d",
    300                                 i, &rfc_cb.port.rfc_mcb[i], rfc_cb.port.rfc_mcb[i].lcid);
    301             return (&rfc_cb.port.rfc_mcb[i]);
    302         }
    303     }
    304     RFCOMM_TRACE_DEBUG("port_find_mcb: not found, bd_addr:%02x:%02x:%02x:%02x:%02x:%02x",
    305                          bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
    306     return (NULL);
    307 }
    308 
    309 
    310 /*******************************************************************************
    311 **
    312 ** Function         port_find_mcb_dlci_port
    313 **
    314 ** Description      Find port on the multiplexer channel based on DLCI.  If
    315 **                  this port with DLCI not found try to use even DLCI.  This
    316 **                  is for the case when client is establishing connection on
    317 **                  none-initiator MCB.
    318 **
    319 ** Returns          Pointer to the PORT or NULL if not found
    320 **
    321 *******************************************************************************/
    322 tPORT *port_find_mcb_dlci_port (tRFC_MCB *p_mcb, UINT8 dlci)
    323 {
    324     UINT8 inx;
    325 
    326     if (!p_mcb)
    327         return (NULL);
    328 
    329     if (dlci > RFCOMM_MAX_DLCI)
    330         return (NULL);
    331 
    332     inx = p_mcb->port_inx[dlci];
    333     if (inx == 0)
    334     {
    335         RFCOMM_TRACE_DEBUG("port_find_mcb_dlci_port: p_mcb:%p, port_inx[dlci:%d] is 0", p_mcb, dlci);
    336         return (NULL);
    337     }
    338     else
    339         return (&rfc_cb.port.port[inx - 1]);
    340 }
    341 
    342 
    343 /*******************************************************************************
    344 **
    345 ** Function         port_find_dlci_port
    346 **
    347 ** Description      Find port with DLCI not assigned to multiplexer channel
    348 **
    349 ** Returns          Pointer to the PORT or NULL if not found
    350 **
    351 *******************************************************************************/
    352 tPORT *port_find_dlci_port (UINT8 dlci)
    353 {
    354     UINT16 i;
    355     tPORT  *p_port;
    356 
    357     for (i = 0; i < MAX_RFC_PORTS; i++)
    358     {
    359         p_port = &rfc_cb.port.port[i];
    360 
    361         if (p_port->in_use && (p_port->rfc.p_mcb == NULL))
    362         {
    363             if (p_port->dlci == dlci)
    364             {
    365                 return (p_port);
    366             }
    367             else if ((dlci & 0x01) && (p_port->dlci == (dlci - 1)))
    368             {
    369                 p_port->dlci++;
    370                 return (p_port);
    371             }
    372         }
    373     }
    374     return (NULL);
    375 }
    376 
    377 
    378 /*******************************************************************************
    379 **
    380 ** Function         port_find_port
    381 **
    382 ** Description      Find port with DLCI, BD_ADDR
    383 **
    384 ** Returns          Pointer to the PORT or NULL if not found
    385 **
    386 *******************************************************************************/
    387 tPORT *port_find_port (UINT8 dlci, BD_ADDR bd_addr)
    388 {
    389     UINT16 i;
    390     tPORT  *p_port;
    391 
    392     for (i = 0; i < MAX_RFC_PORTS; i++)
    393     {
    394         p_port = &rfc_cb.port.port[i];
    395         if (p_port->in_use
    396          && (p_port->dlci == dlci)
    397          && !memcmp (p_port->bd_addr, bd_addr, BD_ADDR_LEN))
    398         {
    399             return (p_port);
    400         }
    401     }
    402     return (NULL);
    403 }
    404 
    405 
    406 /*******************************************************************************
    407 **
    408 ** Function         port_flow_control_user
    409 **
    410 ** Description      Check the current user flow control and if necessary return
    411 **                  events to be send to the user based on the user's specified
    412 **                  flow control type.
    413 **
    414 ** Returns          event mask to be returned to the application
    415 **
    416 *******************************************************************************/
    417 UINT32 port_flow_control_user (tPORT *p_port)
    418 {
    419     UINT32 event = 0;
    420 
    421     /* Flow control to the user can be caused by flow controlling by the peer */
    422     /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */
    423     /* tx_queue is full */
    424     BOOLEAN fc = p_port->tx.peer_fc
    425               || !p_port->rfc.p_mcb
    426               || !p_port->rfc.p_mcb->peer_ready
    427               || (p_port->tx.queue_size > PORT_TX_HIGH_WM)
    428               || (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM);
    429 
    430     if (p_port->tx.user_fc == fc)
    431         return (0);
    432 
    433     p_port->tx.user_fc = fc;
    434 
    435     if (fc)
    436         event = PORT_EV_FC;
    437     else
    438         event = PORT_EV_FC | PORT_EV_FCS;
    439 
    440     return (event);
    441 }
    442 
    443 
    444 /*******************************************************************************
    445 **
    446 ** Function         port_get_signal_changes
    447 **
    448 ** Description      Check modem signals that has been changed
    449 **
    450 ** Returns          event mask to be returned to the application
    451 **
    452 *******************************************************************************/
    453 UINT32 port_get_signal_changes (tPORT *p_port, UINT8 old_signals, UINT8 signal)
    454 {
    455     UINT8  changed_signals = (signal ^ old_signals);
    456     UINT32 events = 0;
    457 
    458     if (changed_signals & PORT_DTRDSR_ON)
    459     {
    460         events |= PORT_EV_DSR;
    461 
    462         if (signal & PORT_DTRDSR_ON)
    463             events |= PORT_EV_DSRS;
    464     }
    465 
    466     if (changed_signals & PORT_CTSRTS_ON)
    467     {
    468         events |= PORT_EV_CTS;
    469 
    470         if (signal & PORT_CTSRTS_ON)
    471             events |= PORT_EV_CTSS;
    472     }
    473 
    474     if (changed_signals & PORT_RING_ON)
    475         events |= PORT_EV_RING;
    476 
    477     if (changed_signals & PORT_DCD_ON)
    478     {
    479         events |= PORT_EV_RLSD;
    480 
    481         if (signal & PORT_DCD_ON)
    482             events |= PORT_EV_RLSDS;
    483     }
    484 
    485     return (p_port->ev_mask & events);
    486 }
    487 
    488 /*******************************************************************************
    489 **
    490 ** Function         port_flow_control_peer
    491 **
    492 ** Description      Send flow control messages to the peer for both enabling
    493 **                  and disabling flow control, for both credit-based and
    494 **                  TS 07.10 flow control mechanisms.
    495 **
    496 ** Returns          nothing
    497 **
    498 *******************************************************************************/
    499 void port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count)
    500 {
    501     if (!p_port->rfc.p_mcb)
    502         return;
    503 
    504     /* If using credit based flow control */
    505     if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT)
    506     {
    507         /* if want to enable flow from peer */
    508         if (enable)
    509         {
    510             /* update rx credits */
    511             if (count > p_port->credit_rx)
    512             {
    513                 p_port->credit_rx = 0;
    514             }
    515             else
    516             {
    517                 p_port->credit_rx -= count;
    518             }
    519 
    520             /* If credit count is less than low credit watermark, and user */
    521             /* did not force flow control, send a credit update */
    522             /* There might be a special case when we just adjusted rx_max */
    523             if ((p_port->credit_rx <= p_port->credit_rx_low)
    524              && !p_port->rx.user_fc
    525              && (p_port->credit_rx_max > p_port->credit_rx))
    526             {
    527                 rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
    528                                 (UINT8) (p_port->credit_rx_max - p_port->credit_rx));
    529 
    530                 p_port->credit_rx = p_port->credit_rx_max;
    531 
    532                 p_port->rx.peer_fc = FALSE;
    533             }
    534         }
    535         /* else want to disable flow from peer */
    536         else
    537         {
    538             /* if client registered data callback, just do what they want */
    539             if (p_port->p_data_callback || p_port->p_data_co_callback)
    540             {
    541                 p_port->rx.peer_fc = TRUE;
    542             }
    543             /* if queue count reached credit rx max, set peer fc */
    544             else if (fixed_queue_length(p_port->rx.queue) >= p_port->credit_rx_max)
    545             {
    546                 p_port->rx.peer_fc = TRUE;
    547             }
    548         }
    549     }
    550     /* else using TS 07.10 flow control */
    551     else
    552     {
    553         /* if want to enable flow from peer */
    554         if (enable)
    555         {
    556             /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
    557             /* check if it can be resumed now */
    558             if (p_port->rx.peer_fc
    559              && (p_port->rx.queue_size < PORT_RX_LOW_WM)
    560              && (fixed_queue_length(p_port->rx.queue) < PORT_RX_BUF_LOW_WM))
    561             {
    562                 p_port->rx.peer_fc = FALSE;
    563 
    564                 /* If user did not force flow control allow traffic now */
    565                 if (!p_port->rx.user_fc)
    566                     RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, TRUE);
    567             }
    568         }
    569         /* else want to disable flow from peer */
    570         else
    571         {
    572             /* if client registered data callback, just do what they want */
    573             if (p_port->p_data_callback || p_port->p_data_co_callback)
    574             {
    575                 p_port->rx.peer_fc = TRUE;
    576                 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
    577             }
    578             /* Check the size of the rx queue.  If it exceeds certain */
    579             /* level and flow control has not been sent to the peer do it now */
    580             else if ( ((p_port->rx.queue_size > PORT_RX_HIGH_WM)
    581                      || (fixed_queue_length(p_port->rx.queue) > PORT_RX_BUF_HIGH_WM))
    582                      && !p_port->rx.peer_fc)
    583             {
    584                 RFCOMM_TRACE_EVENT ("PORT_DataInd Data reached HW. Sending FC set.");
    585 
    586                 p_port->rx.peer_fc = TRUE;
    587                 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
    588             }
    589         }
    590     }
    591 }
    592 
    593