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