OSDN Git Service

Cleanup L2CAP socket properly on close
authorSrinu Jella <sjella@codeaurora.org>
Thu, 7 Apr 2016 13:35:44 +0000 (19:05 +0530)
committerLinux Build Service Account <lnxbuild@localhost>
Wed, 24 Aug 2016 14:09:49 +0000 (08:09 -0600)
Use case:
1. Sometimes pairing pop up occurs during Android beam
   transfer though it is not required.
2. No OPP Tx request over OBEX if we cancel during file transfer.

Steps:
1. Pair and connect from DUT to remote.
2. Go to gallery and send a file.
3. Accept same file and stop it from remote during transfer.
4. Repeat step 2-4 10 times.

Failure:
OPP Tx should not fail.

Root cause:
Close request was not properly handled from BTIF layer.

Fix:
1. Close the request properly from BTIF layer
   to close the socket variables and instruct the BTA layer
   close from there as well.

2. Clean up L2CAP socket properly on closure to free
   the entry registered with security manager to avoid
   leak in security manager records.

3. Close the socket for all valid handles including handle 0.

Change-Id: I4e37dcd858af258fbd64fbfb2fbf0083bd743e06

Check ccb state before executing channel state machine events

Use Case: When disconnect response is being executed, timeout
occurs and timeout event gets enqueued in BTU process. When
processing of disc event completes, timout event is received
at csm and is executed. However, by this time the Channel
Control Block is already released during previous event causing
errors.

Steps:
Various connection/disconnection scenario.

Failure: If ccb is already released while processing of
previous event, the occurance of new enqueued event causes
crash.

Root cause: Disconnection response event has already released
ccb and set lcb for this channel to null. The occurance of
timer event after this results in crash because lcb is
dereferenced while header creation to send disc response to
peer device.

Fix: Added check for ccb state for whether it is currently in
use or released before executing events in csm.

Change-Id: I9110e6dd5273fa162b51c8aa15bd0030567d664b

Handle L2CAP disconnection on incomplete connection

- Sometimes before even receiving the connection complete
  event from remote device, upper layer might send a
  disconnection on incomplete L2CAP connection, and expects
  notification of connection failure.

- This chnage notifies disconnection confirmation to upper
  layers with error incase L2CAP disconnection is received on
  incomplete L2CAP channel.

Change-Id: I4ab675329b3d791a3f68101495a6e6d90b13bde4

L2cap: Handle invalid HCI packets from Test tool

- Handled Buffer over flow for UINT16
- Handled full packet size more than gki buffer case.
- Discard invalid HCI packets from Codenomican test
  tool as data length and actual data not matching
  during reassembly

Use case: Execute L2CAP test suit from Defensics Codenomican

Steps:
1. Pair and connect DUT to Codenomican tool
2. Execute L2CAP test suit from Defensics Codenomican

Failure: Crash observed on DUT and Codenomican tool stuck in execution.

Root cause: Codenomican tool sending invalid HCI packets to DUT and
there are no checks to handle buffer over flow and other invalid data
from Codenomican tool.

Change-Id: I6f93c80244fc39d607ad285185136bbbca83d7ae

Increasing LE Properties to broadcast.

Use case: Remote BD_NAME is not broadcasted when BLE device
pairing is done by using NFC where we broadcasted only UUID.

steps:
Connect with BLE device by using NFC and check the remote name.

Failure: Remote device name is not available.

Root cause: BD_NAME is not broadcasted when BLE device pairing
is done.

Fix: Added property to broadcast remote BD_NAME also as part
BLE device pairing using NFC.

Change-Id: Ie6cda489aabff15a0ebbc692a16f9428729a7dba

Reset the pairing_cb for BREDR/cross key pairing address

Use case: HID connection stuck during multi pairing.

Steps to reproduce:
precondition:
1 DUT
1 Headset HFP supported -- Pair and Unpair
1 HID mouse -- Pair and Unpair

Steps:
1. Pair and connect HFP remote device HM1700
2. Pair and connect HID remote device Sculpt Touch Mouse
3. Unpair both the remote devices and check them in the available
   devices list in settings app.
4. Initiate HFP connection from remote device HM1700 by
   resetting the headset.
5. Along with above step, initiate HID connection to the mouse from DUT.
   Along with step 5,Power down the HID mouse to avoid another connection.

Failure: At step 5, Observe that HID mouse shows ever connecting state in
the DUT UI.

Root cause: pairing_cb state is reseted for non pairing device and leading
to stuck in pairing to other device.

Fix: Reset the pairing_cb structure for BREDR or cross key pairing address
only. Without this check pairing_cb state can be reset by other non
pairing bd addresses which can lead to stuck in pairing.

Change-Id: I077bebffac9df7a0c7559af58656651467158c14

L2CAP: Allocate sufficient memory for FCS while cloning buffer

Use Case: OPP file transfer using OBEX over L2CAP.

Failure: Crash seen while sending the file using Obex over
L2CAP due to corruption in end canary.

Root Cause: Did not allocate sufficient memory for FCS
while cloning the PDU packet, eventually FCS bytes written
will corrupt the end canary.

Fix: Allocating sufficient memory for the PDU packet which
includes FCS also.

Change-Id: Ie47b9bc07732b02f774d1dce474d488fe063f50b

Don't process pair request when controller is not ready

Use case: when one application is trying to pair and
other application is turning off bluetooth.

Steps: when one application is trying to pair and
other application is turning off bluetooth.

Failure: Bluetooth process crashed.

Root Cause: Bluetooth process crashed due to assertion,
as controller module is not ready.

Fix: Made a checks for controller module is ready or not, If
it is ready then only go for pairing.

Change-Id: I72c72f6b5545c845e79874212359854023ffad98

Add null checks for L2CAP socket callback

Use Case: Bluetooth process crashed while sending the file
to remote device.

Steps: Send a file over L2CAP (OBEX over L2CAP) to remote device

Failure: BT process will crash and restarted automatically

Root Cause: L2CAP socket callback reset to null on error
condition, and when other function try to dereference it, this
leads to BT crash.

Fix: Added null checks for L2CAP socket callback

Change-Id: I2e4f20278fcc8a09bd4dbd507a6c4147e0de93c1

Handled pairing state change in collision scenario

Use case: DUT Stuck in pairing state forever with selfy stick
during repair.

Steps:
1. Pair and connect remote devices with DUT.
2. Now un pair selfy stick from DUT.
3. Keep remote in discoverable mode.
4. Start inquiry and try to pair with device.

Failure: Pairing with selfy stick always fails after collision.

Root Cause: As we return from btm_sec_dd_create_conn with out
moving pairing state in connection collision scenario. Pairing
state will remains idle and pairing won't proceed further.

Fix: Move the pairing state in collision scenario so that pairing
can proceed further.

Change-Id: Ic5c446ad3902b0ce16c7223ec2d8e4a625831446

Conflicts:
stack/l2cap/l2c_fcr.c
Change-Id: Ia83fbcf2477152005dd60cf8344ce1db708b1379

Conflicts:
hci/src/packet_fragmenter.c
Change-Id: I1ebcd267713ee4799cba4f9ab45a2db7300c60da

bta/jv/bta_jv_act.c
btif/include/btif_common.h
btif/src/btif_dm.c
btif/src/btif_sock_l2cap.c
stack/btm/btm_sec.c
stack/l2cap/l2c_csm.c
stack/l2cap/l2c_int.h
stack/l2cap/l2c_utils.c

index 410f83b..3f73625 100644 (file)
@@ -1122,7 +1122,8 @@ void bta_jv_l2cap_connect(tBTA_JV_MSG *p_data)
     }
 
     evt_data.handle = handle;
-    cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
+    if(cc->p_cback)
+        cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
 }
 
 
@@ -1287,7 +1288,8 @@ void bta_jv_l2cap_start_server(tBTA_JV_MSG *p_data)
         p_cb->psm = ls->local_psm;
     }
 
-    ls->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data, ls->user_data);
+    if(ls->p_cback)
+        ls->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data, ls->user_data);
 }
 
 /*******************************************************************************
@@ -1316,7 +1318,8 @@ void bta_jv_l2cap_stop_server(tBTA_JV_MSG *p_data)
             evt_data.handle = p_cb->handle;
             evt_data.status = bta_jv_free_l2c_cb(p_cb);
             evt_data.async = FALSE;
-            p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
+            if(p_cback)
+                p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, ls->user_data);
             break;
         }
     }
index b48631b..a63ba3f 100644 (file)
@@ -34,7 +34,7 @@
 ********************************************************************************/
 
 #define ASSERTC(cond, msg, val) if (!(cond)) { LOG_ERROR(LOG_TAG, \
-    "### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);}
+    "### ASSERT : %s %s line %d %s (%d) ###", __FILE__, __func__, __LINE__, msg, val);}
 
 /* Calculate start of event enumeration; id is top 8 bits of event */
 #define BTIF_SIG_START(id)       ((id) << 8)
index aea496a..34737fd 100644 (file)
@@ -649,7 +649,9 @@ static void bond_state_changed(bt_status_t status, bt_bdaddr_t *bd_addr, bt_bond
         pairing_cb.state = state;
         bdcpy(pairing_cb.bd_addr, bd_addr->address);
     } else {
-        if (!pairing_cb.sdp_attempts)
+        if ((!pairing_cb.sdp_attempts)&&
+            ((bdcmp(bd_addr->address, pairing_cb.bd_addr) == 0) ||
+             (bdcmp(bd_addr->address, pairing_cb.static_bdaddr.address) == 0)))
             memset(&pairing_cb, 0, sizeof(pairing_cb));
         else
             BTIF_TRACE_DEBUG("%s: BR-EDR service discovery active", __func__);
@@ -1684,10 +1686,11 @@ static void btif_dm_search_services_evt(UINT16 event, char *p_param)
              bt_uuid_t  uuid;
              int i = 0;
              int j = 15;
+             int num_properties = 0;
              if (p_data->disc_ble_res.service.uu.uuid16 == UUID_SERVCLASS_LE_HID)
              {
                 BTIF_TRACE_DEBUG("%s: Found HOGP UUID",__FUNCTION__);
-                bt_property_t prop;
+                bt_property_t prop[2];
                 bt_bdaddr_t bd_addr;
                 char temp[256];
                 bt_status_t ret;
@@ -1707,17 +1710,30 @@ static void btif_dm_search_services_evt(UINT16 event, char *p_param)
                 LOG_INFO(LOG_TAG, "%s uuid:%s", __func__, temp);
 
                 bdcpy(bd_addr.address, p_data->disc_ble_res.bd_addr);
-                prop.type = BT_PROPERTY_UUIDS;
-                prop.val = uuid.uu;
-                prop.len = MAX_UUID_SIZE;
+                prop[0].type = BT_PROPERTY_UUIDS;
+                prop[0].val = uuid.uu;
+                prop[0].len = MAX_UUID_SIZE;
 
                 /* Also write this to the NVRAM */
-                ret = btif_storage_set_remote_device_property(&bd_addr, &prop);
+                ret = btif_storage_set_remote_device_property(&bd_addr, &prop[0]);
                 ASSERTC(ret == BT_STATUS_SUCCESS, "storing remote services failed", ret);
+                num_properties++;
+
+                /* Remote name update */
+                if (strnlen((const char *) p_data->disc_ble_res.bd_name, BD_NAME_LEN))
+                {
+                    prop[1].type = BT_PROPERTY_BDNAME;
+                    prop[1].val = p_data->disc_ble_res.bd_name;
+                    prop[1].len = strnlen((char *)p_data->disc_ble_res.bd_name, BD_NAME_LEN);
+
+                    ret = btif_storage_set_remote_device_property(&bd_addr, &prop[1]);
+                    ASSERTC(ret == BT_STATUS_SUCCESS, "failed to save remote device property", ret);
+                    num_properties++;
+                }
 
                 /* Send the event to the BTIF */
                 HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb,
-                                 BT_STATUS_SUCCESS, &bd_addr, 1, &prop);
+                                 BT_STATUS_SUCCESS, &bd_addr, num_properties, prop);
 
             }
         break;
index 6c87eeb..7543431 100644 (file)
@@ -276,7 +276,7 @@ static void btsock_l2cap_free_l(l2cap_socket *sock)
     else
     {
         // Only call if we are non server connections
-        if (sock->handle && (sock->server == FALSE)) {
+        if ((sock->handle >= 0) && (sock->server == FALSE)) {
             if (sock->fixed_chan)
                 BTA_JvL2capCloseLE(sock->handle);
             else
@@ -287,6 +287,11 @@ static void btsock_l2cap_free_l(l2cap_socket *sock)
                 BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP_LE);
             else
                 BTA_JvFreeChannel(sock->channel, BTA_JV_CONN_TYPE_L2CAP);
+
+            if (!sock->fixed_chan) {
+                APPL_TRACE_DEBUG("%s stopping L2CAP server channel %d", __func__, sock->channel);
+                BTA_JvL2capStopServer(sock->channel, UINT_TO_PTR(sock->id));
+            }
         }
     }
 
index be8f85c..d6df76f 100644 (file)
@@ -994,7 +994,11 @@ tBTM_STATUS btm_sec_bond_by_transport (BD_ADDR bd_addr, tBT_TRANSPORT transport,
     {
         return(BTM_NO_RESOURCES);
     }
-
+    if (!controller_get_interface()->get_is_ready())
+    {
+        BTM_TRACE_ERROR ("%s controller module is not ready", __func__);
+        return(BTM_NO_RESOURCES);
+    }
     BTM_TRACE_DEBUG ("before update sec_flags=0x%x", p_dev_rec->sec_flags);
 
     /* Finished if connection is active and already paired */
@@ -3003,6 +3007,7 @@ static tBTM_STATUS btm_sec_dd_create_conn (tBTM_SEC_DEV_REC *p_dev_rec)
     if (p_lcb && (p_lcb->link_state == LST_CONNECTED || p_lcb->link_state == LST_CONNECTING))
     {
        BTM_TRACE_WARNING("%s Connection already exists", __func__);
+       btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_PIN_REQ);
        return BTM_CMD_STARTED;
     }
 
index ac77e47..0df4ee8 100644 (file)
@@ -67,6 +67,11 @@ static char *l2c_csm_get_event_name (UINT16 event);
 *******************************************************************************/
 void l2c_csm_execute (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
 {
+    if (!l2cu_is_ccb_active(p_ccb)) {
+        L2CAP_TRACE_WARNING("%s This ccb is not in use, the event(%d) can't be processed", __func__, event);
+        return;
+    }
+
     switch (p_ccb->chnl_state)
     {
     case CST_CLOSED:
@@ -573,6 +578,7 @@ static void l2c_csm_w4_l2cap_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p
 {
     tL2C_CONN_INFO          *p_ci = (tL2C_CONN_INFO *)p_data;
     tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
+    tL2CA_DISCONNECT_CFM_CB *disconnect_cfm = p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb;
     tL2CA_CONNECT_CFM_CB    *connect_cfm = p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb;
     UINT16                  local_cid = p_ccb->local_cid;
 
@@ -655,7 +661,14 @@ static void l2c_csm_w4_l2cap_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p
                                btu_general_alarm_queue);
         }
         else
+        {
             l2cu_release_ccb (p_ccb);
+            if(disconnect_cfm)
+            {
+                L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
+                (*disconnect_cfm)(local_cid, L2CAP_CONN_NO_LINK);
+            }
+        }
         break;
 
     case L2CEVT_L2CA_DATA_WRITE:                    /* Upper layer data to send */
index 54e1f03..5118c30 100644 (file)
@@ -640,6 +640,7 @@ extern void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB *p_ccb);
 extern BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 fixed_cid, tL2CAP_FCR_OPTS *p_fcr);
 extern void    l2cu_no_dynamic_ccbs (tL2C_LCB *p_lcb);
 extern void    l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb);
+extern BOOLEAN l2cu_is_ccb_active (tL2C_CCB *p_ccb);
 
 /* Functions provided by l2c_ucd.c
 ************************************
index bbaa1f1..20f8ee0 100755 (executable)
@@ -3832,3 +3832,17 @@ void l2cu_check_channel_congestion (tL2C_CCB *p_ccb)
     }
 }
 
+/*******************************************************************************
+**
+** Function         l2cu_is_ccb_active
+**
+** Description      Check if Channel Control Block is in use or released
+**
+** Returns          BOOLEAN - TRUE if Channel Control Block is in use
+**                            FALSE if p_ccb is null or is released.
+**
+*******************************************************************************/
+BOOLEAN l2cu_is_ccb_active (tL2C_CCB *p_ccb)
+{
+    return (p_ccb && p_ccb->in_use);
+}