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