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 #include <cutils/log.h>
     37 #define info(fmt, ...)  ALOGI ("%s: " fmt,__FUNCTION__,  ## __VA_ARGS__)
     38 #define debug(fmt, ...) ALOGD ("%s: " fmt,__FUNCTION__,  ## __VA_ARGS__)
     39 #define error(fmt, ...) ALOGE ("## ERROR : %s: " fmt "##",__FUNCTION__,  ## __VA_ARGS__)
     40 #define asrt(s) if(!(s)) ALOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__)
     41 
     42 
     43 static const tPORT_STATE default_port_pars =
     44 {
     45     PORT_BAUD_RATE_9600,
     46     PORT_8_BITS,
     47     PORT_ONESTOPBIT,
     48     PORT_PARITY_NO,
     49     PORT_ODD_PARITY,
     50     PORT_FC_OFF,
     51     0,                      /* No rx_char */
     52     PORT_XON_DC1,
     53     PORT_XOFF_DC3,
     54 };
     55 
     56 
     57 
     58 /*******************************************************************************
     59 **
     60 ** Function         port_allocate_port
     61 **
     62 ** Description      Look through the Port Control Blocks for a free one.  Note
     63 **                  that one server can open several ports with the same SCN
     64 **                  if it can support simulteneous requests from different
     65 **                  clients.
     66 **
     67 ** Returns          Pointer to the PORT or NULL if not found
     68 **
     69 *******************************************************************************/
     70 tPORT *port_allocate_port (UINT8 dlci, BD_ADDR bd_addr)
     71 {
     72     tPORT  *p_port = &rfc_cb.port.port[0];
     73     UINT8  xx, yy;
     74 
     75     for (xx = 0, yy = rfc_cb.rfc.last_port + 1; xx < MAX_RFC_PORTS; xx++, yy++)
     76     {
     77         if (yy >= MAX_RFC_PORTS)
     78             yy = 0;
     79 
     80         p_port = &rfc_cb.port.port[yy];
     81         if (!p_port->in_use)
     82         {
     83             memset (p_port, 0, sizeof (tPORT));
     84 
     85             p_port->in_use = TRUE;
     86             p_port->inx    = yy + 1;
     87 
     88             p_port->dlci   = dlci;
     89             memcpy (p_port->bd_addr, bd_addr, BD_ADDR_LEN);
     90 
     91             /* During the open set default state for the port connection */
     92             port_set_defaults (p_port);
     93 
     94             rfc_cb.rfc.last_port = yy;
     95             debug("rfc_cb.port.port[%d] allocated, last_port:%d", yy, rfc_cb.rfc.last_port);
     96             return (p_port);
     97         }
     98     }
     99 
    100     /* If here, no free PORT found */
    101     return (NULL);
    102 }
    103 
    104 
    105 /*******************************************************************************
    106 **
    107 ** Function         port_set_defaults
    108 **
    109 ** Description      Set defualt port parameters
    110 **
    111 **
    112 *******************************************************************************/
    113 void port_set_defaults (tPORT *p_port)
    114 {
    115     p_port->ev_mask        = 0;
    116     p_port->p_callback     = NULL;
    117     p_port->port_ctrl      = 0;
    118     p_port->error          = 0;
    119     p_port->line_status    = 0;
    120     p_port->rx_flag_ev_pending = FALSE;
    121     p_port->peer_mtu       = RFCOMM_DEFAULT_MTU;
    122 
    123     p_port->user_port_pars = default_port_pars;
    124     p_port->peer_port_pars = default_port_pars;
    125 
    126     p_port->credit_tx      = 0;
    127     p_port->credit_rx      = 0;
    128 /*  p_port->credit_rx_max  = PORT_CREDIT_RX_MAX;            Determined later */
    129 /*  p_port->credit_rx_low  = PORT_CREDIT_RX_LOW;            Determined later */
    130 
    131     memset (&p_port->local_ctrl, 0, sizeof (p_port->local_ctrl));
    132     memset (&p_port->peer_ctrl, 0, sizeof (p_port->peer_ctrl));
    133     memset (&p_port->rx, 0, sizeof (p_port->rx));
    134     memset (&p_port->tx, 0, sizeof (p_port->tx));
    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_WARNING0 ("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_DEBUG1 ("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_DEBUG1 ("port_select_mtu selected %d based on l2cap PDU size", p_port->mtu);
    182             }
    183         }
    184     }
    185     else
    186     {
    187         RFCOMM_TRACE_DEBUG1 ("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_DEBUG3 ("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 **
    205 ** Function         port_release_port
    206 **
    207 ** Description      Release port infor control block.
    208 **
    209 ** Returns          Pointer to the PORT or NULL if not found
    210 **
    211 *******************************************************************************/
    212 void port_release_port (tPORT *p_port)
    213 {
    214     BT_HDR *p_buf;
    215     UINT32 mask;
    216     tPORT_CALLBACK *p_port_cb;
    217     tPORT_STATE user_port_pars;
    218 
    219     PORT_SCHEDULE_LOCK;
    220     debug("port_release_port, p_port:%p", p_port);
    221     while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->rx.queue)) != NULL)
    222         GKI_freebuf (p_buf);
    223 
    224     p_port->rx.queue_size = 0;
    225 
    226     while ((p_buf = (BT_HDR *)GKI_dequeue (&p_port->tx.queue)) != NULL)
    227         GKI_freebuf (p_buf);
    228 
    229     p_port->tx.queue_size = 0;
    230 
    231     PORT_SCHEDULE_UNLOCK;
    232 
    233     p_port->state = PORT_STATE_CLOSED;
    234 
    235     if (p_port->rfc.state == RFC_STATE_CLOSED)
    236     {
    237         RFCOMM_TRACE_DEBUG0 ("rfc_port_closed DONE");
    238         if (p_port->rfc.p_mcb)
    239         {
    240             p_port->rfc.p_mcb->port_inx[p_port->dlci] = 0;
    241 
    242             /* If there are no more ports opened on this MCB release it */
    243             rfc_check_mcb_active (p_port->rfc.p_mcb);
    244         }
    245         rfc_port_timer_stop (p_port);
    246 
    247         if( p_port->keep_port_handle )
    248         {
    249             RFCOMM_TRACE_DEBUG1 ("port_release_port:Initialize handle:%d", p_port->inx);
    250             /* save event mask and callback */
    251             mask = p_port->ev_mask;
    252             p_port_cb = p_port->p_callback;
    253             user_port_pars = p_port->user_port_pars;
    254 
    255             port_set_defaults(p_port);
    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         }
    270         else
    271         {
    272             RFCOMM_TRACE_DEBUG1 ("port_release_port:Clean-up handle:%d", p_port->inx);
    273             memset (p_port, 0, sizeof (tPORT));
    274         }
    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             return (&rfc_cb.port.rfc_mcb[i]);
    298         }
    299     }
    300     return (NULL);
    301 }
    302 
    303 
    304 /*******************************************************************************
    305 **
    306 ** Function         port_find_mcb_dlci_port
    307 **
    308 ** Description      Find port on the multiplexer channel based on DLCI.  If
    309 **                  this port with DLCI not found try to use even DLCI.  This
    310 **                  is for the case when client is establishing connection on
    311 **                  none-initiator MCB.
    312 **
    313 ** Returns          Pointer to the PORT or NULL if not found
    314 **
    315 *******************************************************************************/
    316 tPORT *port_find_mcb_dlci_port (tRFC_MCB *p_mcb, UINT8 dlci)
    317 {
    318     UINT8 inx;
    319 
    320     if (!p_mcb)
    321         return (NULL);
    322 
    323     if (dlci > RFCOMM_MAX_DLCI)
    324         return (NULL);
    325 
    326     inx = p_mcb->port_inx[dlci];
    327     if (inx == 0)
    328         return (NULL);
    329     else
    330         return (&rfc_cb.port.port[inx - 1]);
    331 }
    332 
    333 
    334 /*******************************************************************************
    335 **
    336 ** Function         port_find_dlci_port
    337 **
    338 ** Description      Find port with DLCI not assigned to multiplexer channel
    339 **
    340 ** Returns          Pointer to the PORT or NULL if not found
    341 **
    342 *******************************************************************************/
    343 tPORT *port_find_dlci_port (UINT8 dlci)
    344 {
    345     UINT16 i;
    346     tPORT  *p_port;
    347 
    348     for (i = 0; i < MAX_RFC_PORTS; i++)
    349     {
    350         p_port = &rfc_cb.port.port[i];
    351         if (p_port->in_use && (p_port->rfc.p_mcb == NULL))
    352         {
    353             if (p_port->dlci == dlci)
    354             {
    355                 return (p_port);
    356             }
    357             else if ((dlci & 0x01) && (p_port->dlci == (dlci - 1)))
    358             {
    359                 p_port->dlci++;
    360                 return (p_port);
    361             }
    362         }
    363     }
    364     return (NULL);
    365 }
    366 
    367 
    368 /*******************************************************************************
    369 **
    370 ** Function         port_find_port
    371 **
    372 ** Description      Find port with DLCI, BD_ADDR
    373 **
    374 ** Returns          Pointer to the PORT or NULL if not found
    375 **
    376 *******************************************************************************/
    377 tPORT *port_find_port (UINT8 dlci, BD_ADDR bd_addr)
    378 {
    379     UINT16 i;
    380     tPORT  *p_port;
    381 
    382     for (i = 0; i < MAX_RFC_PORTS; i++)
    383     {
    384         p_port = &rfc_cb.port.port[i];
    385         if (p_port->in_use
    386          && (p_port->dlci == dlci)
    387          && !memcmp (p_port->bd_addr, bd_addr, BD_ADDR_LEN))
    388         {
    389             return (p_port);
    390         }
    391     }
    392     return (NULL);
    393 }
    394 
    395 
    396 /*******************************************************************************
    397 **
    398 ** Function         port_flow_control_user
    399 **
    400 ** Description      Check the current user flow control and if necessary return
    401 **                  events to be send to the user based on the user's specified
    402 **                  flow control type.
    403 **
    404 ** Returns          event mask to be returned to the application
    405 **
    406 *******************************************************************************/
    407 UINT32 port_flow_control_user (tPORT *p_port)
    408 {
    409     UINT32 event = 0;
    410 
    411     /* Flow control to the user can be caused by flow controlling by the peer */
    412     /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */
    413     /* tx_queue is full */
    414     BOOLEAN fc = p_port->tx.peer_fc
    415               || !p_port->rfc.p_mcb
    416               || !p_port->rfc.p_mcb->peer_ready
    417               || (p_port->tx.queue_size > PORT_TX_HIGH_WM)
    418               || (p_port->tx.queue.count > PORT_TX_BUF_HIGH_WM);
    419 
    420     if (p_port->tx.user_fc == fc)
    421         return (0);
    422 
    423     p_port->tx.user_fc = fc;
    424 
    425     if (fc)
    426         event = PORT_EV_FC;
    427     else
    428         event = PORT_EV_FC | PORT_EV_FCS;
    429 
    430     return (event);
    431 }
    432 
    433 
    434 /*******************************************************************************
    435 **
    436 ** Function         port_get_signal_changes
    437 **
    438 ** Description      Check modem signals that has been changed
    439 **
    440 ** Returns          event mask to be returned to the application
    441 **
    442 *******************************************************************************/
    443 UINT32 port_get_signal_changes (tPORT *p_port, UINT8 old_signals, UINT8 signal)
    444 {
    445     UINT8  changed_signals = (signal ^ old_signals);
    446     UINT32 events = 0;
    447 
    448     if (changed_signals & PORT_DTRDSR_ON)
    449     {
    450         events |= PORT_EV_DSR;
    451 
    452         if (signal & PORT_DTRDSR_ON)
    453             events |= PORT_EV_DSRS;
    454     }
    455 
    456     if (changed_signals & PORT_CTSRTS_ON)
    457     {
    458         events |= PORT_EV_CTS;
    459 
    460         if (signal & PORT_CTSRTS_ON)
    461             events |= PORT_EV_CTSS;
    462     }
    463 
    464     if (changed_signals & PORT_RING_ON)
    465         events |= PORT_EV_RING;
    466 
    467     if (changed_signals & PORT_DCD_ON)
    468     {
    469         events |= PORT_EV_RLSD;
    470 
    471         if (signal & PORT_DCD_ON)
    472             events |= PORT_EV_RLSDS;
    473     }
    474 
    475     return (p_port->ev_mask & events);
    476 }
    477 
    478 /*******************************************************************************
    479 **
    480 ** Function         port_flow_control_peer
    481 **
    482 ** Description      Send flow control messages to the peer for both enabling
    483 **                  and disabling flow control, for both credit-based and
    484 **                  TS 07.10 flow control mechanisms.
    485 **
    486 ** Returns          nothing
    487 **
    488 *******************************************************************************/
    489 void port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count)
    490 {
    491     if (!p_port->rfc.p_mcb)
    492         return;
    493 
    494     /* If using credit based flow control */
    495     if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT)
    496     {
    497         /* if want to enable flow from peer */
    498         if (enable)
    499         {
    500             /* update rx credits */
    501             if (count > p_port->credit_rx)
    502             {
    503                 p_port->credit_rx = 0;
    504             }
    505             else
    506             {
    507                 p_port->credit_rx -= count;
    508             }
    509 
    510             /* If credit count is less than low credit watermark, and user */
    511             /* did not force flow control, send a credit update */
    512             /* There might be a special case when we just adjusted rx_max */
    513             if ((p_port->credit_rx <= p_port->credit_rx_low)
    514              && !p_port->rx.user_fc
    515              && (p_port->credit_rx_max > p_port->credit_rx))
    516             {
    517                 rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci,
    518                                 (UINT8) (p_port->credit_rx_max - p_port->credit_rx));
    519 
    520                 p_port->credit_rx = p_port->credit_rx_max;
    521 
    522                 p_port->rx.peer_fc = FALSE;
    523             }
    524         }
    525         /* else want to disable flow from peer */
    526         else
    527         {
    528             /* if client registered data callback, just do what they want */
    529             if (p_port->p_data_callback || p_port->p_data_co_callback)
    530             {
    531                 p_port->rx.peer_fc = TRUE;
    532             }
    533             /* if queue count reached credit rx max, set peer fc */
    534             else if (p_port->rx.queue.count >= p_port->credit_rx_max)
    535             {
    536                 p_port->rx.peer_fc = TRUE;
    537             }
    538         }
    539     }
    540     /* else using TS 07.10 flow control */
    541     else
    542     {
    543         /* if want to enable flow from peer */
    544         if (enable)
    545         {
    546             /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
    547             /* check if it can be resumed now */
    548             if (p_port->rx.peer_fc
    549              && (p_port->rx.queue_size < PORT_RX_LOW_WM)
    550              && (p_port->rx.queue.count < PORT_RX_BUF_LOW_WM))
    551             {
    552                 p_port->rx.peer_fc = FALSE;
    553 
    554                 /* If user did not force flow control allow traffic now */
    555                 if (!p_port->rx.user_fc)
    556                     RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, TRUE);
    557             }
    558         }
    559         /* else want to disable flow from peer */
    560         else
    561         {
    562             /* if client registered data callback, just do what they want */
    563             if (p_port->p_data_callback || p_port->p_data_co_callback)
    564             {
    565                 p_port->rx.peer_fc = TRUE;
    566                 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
    567             }
    568             /* Check the size of the rx queue.  If it exceeds certain */
    569             /* level and flow control has not been sent to the peer do it now */
    570             else if ( ((p_port->rx.queue_size > PORT_RX_HIGH_WM)
    571                      || (p_port->rx.queue.count > PORT_RX_BUF_HIGH_WM))
    572                      && !p_port->rx.peer_fc)
    573             {
    574                 RFCOMM_TRACE_EVENT0 ("PORT_DataInd Data reached HW. Sending FC set.");
    575 
    576                 p_port->rx.peer_fc = TRUE;
    577                 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE);
    578             }
    579         }
    580     }
    581 }
    582 
    583