2007-02-09 23:24:33 +09:00
/*
2005-04-16 15:20:36 -07:00
BlueZ - Bluetooth protocol stack for Linux
2010-05-28 11:53:46 -04:00
Copyright ( c ) 2000 - 2001 , 2010 , Code Aurora Forum . All rights reserved .
2005-04-16 15:20:36 -07:00
Written 2000 , 2001 by Maxim Krasnyansky < maxk @ qualcomm . com >
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation ;
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS
OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS .
IN NO EVENT SHALL THE COPYRIGHT HOLDER ( S ) AND AUTHOR ( S ) BE LIABLE FOR ANY
2007-02-09 23:24:33 +09:00
CLAIM , OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES , OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE , DATA OR PROFITS , WHETHER IN AN
ACTION OF CONTRACT , NEGLIGENCE OR OTHER TORTIOUS ACTION , ARISING OUT OF
2005-04-16 15:20:36 -07:00
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE .
2007-02-09 23:24:33 +09:00
ALL LIABILITY , INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS ,
COPYRIGHTS , TRADEMARKS OR OTHER RIGHTS , RELATING TO USE OF THIS
2005-04-16 15:20:36 -07:00
SOFTWARE IS DISCLAIMED .
*/
/* Bluetooth HCI connection handling. */
2012-05-23 04:04:22 -03:00
# include <linux/export.h>
2005-04-16 15:20:36 -07:00
# include <net/bluetooth/bluetooth.h>
# include <net/bluetooth/hci_core.h>
2013-10-10 14:54:16 -07:00
# include "smp.h"
2013-10-10 14:54:15 -07:00
# include "a2mp.h"
2013-08-19 14:24:03 +02:00
struct sco_param {
u16 pkt_type ;
u16 max_latency ;
} ;
static const struct sco_param sco_param_cvsd [ ] = {
{ EDR_ESCO_MASK & ~ ESCO_2EV3 , 0x000a } , /* S3 */
{ EDR_ESCO_MASK & ~ ESCO_2EV3 , 0x0007 } , /* S2 */
{ EDR_ESCO_MASK | ESCO_EV3 , 0x0007 } , /* S1 */
{ EDR_ESCO_MASK | ESCO_HV3 , 0xffff } , /* D1 */
{ EDR_ESCO_MASK | ESCO_HV1 , 0xffff } , /* D0 */
} ;
static const struct sco_param sco_param_wideband [ ] = {
{ EDR_ESCO_MASK & ~ ESCO_2EV3 , 0x000d } , /* T2 */
{ EDR_ESCO_MASK | ESCO_EV3 , 0x0008 } , /* T1 */
} ;
2012-07-27 19:32:55 -03:00
static void hci_le_create_connection_cancel ( struct hci_conn * conn )
2011-02-10 22:38:47 -03:00
{
hci_send_cmd ( conn - > hdev , HCI_OP_LE_CREATE_CONN_CANCEL , 0 , NULL ) ;
}
2012-07-27 19:32:55 -03:00
static void hci_acl_create_connection ( struct hci_conn * conn )
2005-04-16 15:20:36 -07:00
{
struct hci_dev * hdev = conn - > hdev ;
struct inquiry_entry * ie ;
struct hci_cp_create_conn cp ;
2012-02-17 11:40:57 +02:00
BT_DBG ( " hcon %p " , conn ) ;
2005-04-16 15:20:36 -07:00
conn - > state = BT_CONNECT ;
2012-01-16 09:49:58 +02:00
conn - > out = true ;
2008-07-14 20:13:46 +02:00
2005-04-16 15:20:36 -07:00
conn - > link_mode = HCI_LM_MASTER ;
2006-10-15 17:30:56 +02:00
conn - > attempt + + ;
2008-07-14 20:13:47 +02:00
conn - > link_policy = hdev - > link_policy ;
2005-04-16 15:20:36 -07:00
memset ( & cp , 0 , sizeof ( cp ) ) ;
bacpy ( & cp . bdaddr , & conn - > dst ) ;
cp . pscan_rep_mode = 0x02 ;
2010-12-01 16:58:25 +02:00
ie = hci_inquiry_cache_lookup ( hdev , & conn - > dst ) ;
if ( ie ) {
2008-07-14 20:13:48 +02:00
if ( inquiry_entry_age ( ie ) < = INQUIRY_ENTRY_AGE_MAX ) {
cp . pscan_rep_mode = ie - > data . pscan_rep_mode ;
cp . pscan_mode = ie - > data . pscan_mode ;
cp . clock_offset = ie - > data . clock_offset |
2012-05-25 11:38:27 +03:00
__constant_cpu_to_le16 ( 0x8000 ) ;
2008-07-14 20:13:48 +02:00
}
2005-04-16 15:20:36 -07:00
memcpy ( conn - > dev_class , ie - > data . dev_class , 3 ) ;
2012-01-16 06:47:28 +02:00
if ( ie - > data . ssp_mode > 0 )
set_bit ( HCI_CONN_SSP_ENABLED , & conn - > flags ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-14 20:13:46 +02:00
cp . pkt_type = cpu_to_le16 ( conn - > pkt_type ) ;
2005-04-16 15:20:36 -07:00
if ( lmp_rswitch_capable ( hdev ) & & ! ( hdev - > link_mode & HCI_LM_MASTER ) )
2007-10-20 14:55:10 +02:00
cp . role_switch = 0x01 ;
2005-04-16 15:20:36 -07:00
else
2007-10-20 14:55:10 +02:00
cp . role_switch = 0x00 ;
2006-10-15 17:30:56 +02:00
2007-10-20 13:33:56 +02:00
hci_send_cmd ( hdev , HCI_OP_CREATE_CONN , sizeof ( cp ) , & cp ) ;
2005-04-16 15:20:36 -07:00
}
2012-07-27 19:32:55 -03:00
static void hci_acl_create_connection_cancel ( struct hci_conn * conn )
2006-09-26 09:43:48 +02:00
{
struct hci_cp_create_conn_cancel cp ;
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2006-09-26 09:43:48 +02:00
2011-12-01 14:33:27 +02:00
if ( conn - > hdev - > hci_ver < BLUETOOTH_VER_1_2 )
2006-09-26 09:43:48 +02:00
return ;
bacpy ( & cp . bdaddr , & conn - > dst ) ;
2007-10-20 13:33:56 +02:00
hci_send_cmd ( conn - > hdev , HCI_OP_CREATE_CONN_CANCEL , sizeof ( cp ) , & cp ) ;
2006-09-26 09:43:48 +02:00
}
2013-04-11 13:54:56 -03:00
static void hci_reject_sco ( struct hci_conn * conn )
{
struct hci_cp_reject_sync_conn_req cp ;
cp . reason = HCI_ERROR_REMOTE_USER_TERM ;
bacpy ( & cp . bdaddr , & conn - > dst ) ;
hci_send_cmd ( conn - > hdev , HCI_OP_REJECT_SYNC_CONN_REQ , sizeof ( cp ) , & cp ) ;
}
2013-01-30 11:50:56 -03:00
void hci_disconnect ( struct hci_conn * conn , __u8 reason )
2005-04-16 15:20:36 -07:00
{
struct hci_cp_disconnect cp ;
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2005-04-16 15:20:36 -07:00
conn - > state = BT_DISCONN ;
2007-03-25 20:12:50 -07:00
cp . handle = cpu_to_le16 ( conn - > handle ) ;
2005-04-16 15:20:36 -07:00
cp . reason = reason ;
2007-10-20 13:33:56 +02:00
hci_send_cmd ( conn - > hdev , HCI_OP_DISCONNECT , sizeof ( cp ) , & cp ) ;
2005-04-16 15:20:36 -07:00
}
2012-10-10 17:38:27 +03:00
static void hci_amp_disconn ( struct hci_conn * conn , __u8 reason )
{
struct hci_cp_disconn_phy_link cp ;
BT_DBG ( " hcon %p " , conn ) ;
conn - > state = BT_DISCONN ;
cp . phy_handle = HCI_PHY_HANDLE ( conn - > handle ) ;
cp . reason = reason ;
hci_send_cmd ( conn - > hdev , HCI_OP_DISCONN_PHY_LINK ,
sizeof ( cp ) , & cp ) ;
}
2012-07-27 19:32:54 -03:00
static void hci_add_sco ( struct hci_conn * conn , __u16 handle )
2005-04-16 15:20:36 -07:00
{
struct hci_dev * hdev = conn - > hdev ;
struct hci_cp_add_sco cp ;
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2005-04-16 15:20:36 -07:00
conn - > state = BT_CONNECT ;
2012-01-16 09:49:58 +02:00
conn - > out = true ;
2005-04-16 15:20:36 -07:00
2009-02-06 09:13:37 +01:00
conn - > attempt + + ;
2007-03-25 20:12:50 -07:00
cp . handle = cpu_to_le16 ( handle ) ;
2008-07-14 20:13:46 +02:00
cp . pkt_type = cpu_to_le16 ( conn - > pkt_type ) ;
2005-04-16 15:20:36 -07:00
2007-10-20 13:33:56 +02:00
hci_send_cmd ( hdev , HCI_OP_ADD_SCO , sizeof ( cp ) , & cp ) ;
2005-04-16 15:20:36 -07:00
}
2013-08-19 14:24:03 +02:00
bool hci_setup_sync ( struct hci_conn * conn , __u16 handle )
2007-10-20 14:55:10 +02:00
{
struct hci_dev * hdev = conn - > hdev ;
struct hci_cp_setup_sync_conn cp ;
2013-08-19 14:24:03 +02:00
const struct sco_param * param ;
2007-10-20 14:55:10 +02:00
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2007-10-20 14:55:10 +02:00
conn - > state = BT_CONNECT ;
2012-01-16 09:49:58 +02:00
conn - > out = true ;
2007-10-20 14:55:10 +02:00
2009-02-06 09:13:37 +01:00
conn - > attempt + + ;
2007-10-20 14:55:10 +02:00
cp . handle = cpu_to_le16 ( handle ) ;
2012-05-25 11:38:27 +03:00
cp . tx_bandwidth = __constant_cpu_to_le32 ( 0x00001f40 ) ;
cp . rx_bandwidth = __constant_cpu_to_le32 ( 0x00001f40 ) ;
2013-08-19 14:23:59 +02:00
cp . voice_setting = cpu_to_le16 ( conn - > setting ) ;
switch ( conn - > setting & SCO_AIRMODE_MASK ) {
case SCO_AIRMODE_TRANSP :
2013-08-19 14:24:03 +02:00
if ( conn - > attempt > ARRAY_SIZE ( sco_param_wideband ) )
return false ;
2013-08-19 14:23:59 +02:00
cp . retrans_effort = 0x02 ;
2013-08-19 14:24:03 +02:00
param = & sco_param_wideband [ conn - > attempt - 1 ] ;
2013-08-19 14:23:59 +02:00
break ;
case SCO_AIRMODE_CVSD :
2013-08-19 14:24:03 +02:00
if ( conn - > attempt > ARRAY_SIZE ( sco_param_cvsd ) )
return false ;
cp . retrans_effort = 0x01 ;
param = & sco_param_cvsd [ conn - > attempt - 1 ] ;
2013-08-19 14:23:59 +02:00
break ;
2013-08-19 14:24:03 +02:00
default :
return false ;
2013-08-19 14:23:59 +02:00
}
2007-10-20 14:55:10 +02:00
2013-08-19 14:24:03 +02:00
cp . pkt_type = __cpu_to_le16 ( param - > pkt_type ) ;
cp . max_latency = __cpu_to_le16 ( param - > max_latency ) ;
if ( hci_send_cmd ( hdev , HCI_OP_SETUP_SYNC_CONN , sizeof ( cp ) , & cp ) < 0 )
return false ;
return true ;
2007-10-20 14:55:10 +02:00
}
2011-02-16 20:44:53 -02:00
void hci_le_conn_update ( struct hci_conn * conn , u16 min , u16 max ,
2012-05-17 00:36:25 -03:00
u16 latency , u16 to_multiplier )
2011-02-16 20:44:53 -02:00
{
struct hci_cp_le_conn_update cp ;
struct hci_dev * hdev = conn - > hdev ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
cp . handle = cpu_to_le16 ( conn - > handle ) ;
cp . conn_interval_min = cpu_to_le16 ( min ) ;
cp . conn_interval_max = cpu_to_le16 ( max ) ;
cp . conn_latency = cpu_to_le16 ( latency ) ;
cp . supervision_timeout = cpu_to_le16 ( to_multiplier ) ;
2012-05-25 11:38:27 +03:00
cp . min_ce_len = __constant_cpu_to_le16 ( 0x0001 ) ;
cp . max_ce_len = __constant_cpu_to_le16 ( 0x0001 ) ;
2011-02-16 20:44:53 -02:00
hci_send_cmd ( hdev , HCI_OP_LE_CONN_UPDATE , sizeof ( cp ) , & cp ) ;
}
2011-06-09 18:50:47 -03:00
void hci_le_start_enc ( struct hci_conn * conn , __le16 ediv , __u8 rand [ 8 ] ,
2012-05-17 00:36:25 -03:00
__u8 ltk [ 16 ] )
2011-06-09 18:50:47 -03:00
{
struct hci_dev * hdev = conn - > hdev ;
struct hci_cp_le_start_enc cp ;
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2011-06-09 18:50:47 -03:00
memset ( & cp , 0 , sizeof ( cp ) ) ;
cp . handle = cpu_to_le16 ( conn - > handle ) ;
memcpy ( cp . ltk , ltk , sizeof ( cp . ltk ) ) ;
cp . ediv = ediv ;
2011-09-19 14:41:09 -04:00
memcpy ( cp . rand , rand , sizeof ( cp . rand ) ) ;
2011-06-09 18:50:47 -03:00
hci_send_cmd ( hdev , HCI_OP_LE_START_ENC , sizeof ( cp ) , & cp ) ;
}
2010-07-26 10:06:00 -04:00
/* Device _must_ be locked */
void hci_sco_setup ( struct hci_conn * conn , __u8 status )
{
struct hci_conn * sco = conn - > link ;
if ( ! sco )
return ;
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2010-07-26 10:06:00 -04:00
if ( ! status ) {
if ( lmp_esco_capable ( conn - > hdev ) )
hci_setup_sync ( sco , conn - > handle ) ;
else
hci_add_sco ( sco , conn - > handle ) ;
} else {
hci_proto_connect_cfm ( sco , status ) ;
hci_conn_del ( sco ) ;
}
}
2012-10-10 17:38:27 +03:00
static void hci_conn_disconnect ( struct hci_conn * conn )
{
__u8 reason = hci_proto_disconn_ind ( conn ) ;
switch ( conn - > type ) {
case AMP_LINK :
hci_amp_disconn ( conn , reason ) ;
break ;
2013-01-30 11:50:55 -03:00
default :
2013-01-30 11:50:56 -03:00
hci_disconnect ( conn , reason ) ;
2013-01-30 11:50:55 -03:00
break ;
2012-10-10 17:38:27 +03:00
}
}
2011-06-17 13:03:21 -03:00
static void hci_conn_timeout ( struct work_struct * work )
2005-04-16 15:20:36 -07:00
{
2011-06-17 13:03:21 -03:00
struct hci_conn * conn = container_of ( work , struct hci_conn ,
2012-05-17 00:36:25 -03:00
disc_work . work ) ;
2005-04-16 15:20:36 -07:00
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p state %s " , conn , state_to_string ( conn - > state ) ) ;
2005-04-16 15:20:36 -07:00
if ( atomic_read ( & conn - > refcnt ) )
return ;
2006-09-26 09:43:48 +02:00
switch ( conn - > state ) {
case BT_CONNECT :
2008-07-14 20:13:49 +02:00
case BT_CONNECT2 :
2011-02-10 22:38:47 -03:00
if ( conn - > out ) {
if ( conn - > type = = ACL_LINK )
2012-07-27 19:32:55 -03:00
hci_acl_create_connection_cancel ( conn ) ;
2011-02-10 22:38:47 -03:00
else if ( conn - > type = = LE_LINK )
2012-07-27 19:32:55 -03:00
hci_le_create_connection_cancel ( conn ) ;
2013-04-11 13:54:56 -03:00
} else if ( conn - > type = = SCO_LINK | | conn - > type = = ESCO_LINK ) {
hci_reject_sco ( conn ) ;
2011-02-10 22:38:47 -03:00
}
2006-09-26 09:43:48 +02:00
break ;
2008-07-14 20:13:49 +02:00
case BT_CONFIG :
2007-02-09 23:24:33 +09:00
case BT_CONNECTED :
2012-10-10 17:38:27 +03:00
hci_conn_disconnect ( conn ) ;
2006-09-26 09:43:48 +02:00
break ;
default :
2005-04-16 15:20:36 -07:00
conn - > state = BT_CLOSED ;
2006-09-26 09:43:48 +02:00
break ;
}
2005-04-16 15:20:36 -07:00
}
2011-12-07 13:24:33 -02:00
/* Enter sniff mode */
2013-10-16 18:11:40 +03:00
static void hci_conn_idle ( struct work_struct * work )
2011-12-07 13:24:33 -02:00
{
2013-10-16 18:11:40 +03:00
struct hci_conn * conn = container_of ( work , struct hci_conn ,
idle_work . work ) ;
2011-12-07 13:24:33 -02:00
struct hci_dev * hdev = conn - > hdev ;
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p mode %d " , conn , conn - > mode ) ;
2011-12-07 13:24:33 -02:00
if ( test_bit ( HCI_RAW , & hdev - > flags ) )
return ;
if ( ! lmp_sniff_capable ( hdev ) | | ! lmp_sniff_capable ( conn ) )
return ;
if ( conn - > mode ! = HCI_CM_ACTIVE | | ! ( conn - > link_policy & HCI_LP_SNIFF ) )
return ;
if ( lmp_sniffsubr_capable ( hdev ) & & lmp_sniffsubr_capable ( conn ) ) {
struct hci_cp_sniff_subrate cp ;
cp . handle = cpu_to_le16 ( conn - > handle ) ;
2012-05-25 11:38:27 +03:00
cp . max_latency = __constant_cpu_to_le16 ( 0 ) ;
cp . min_remote_timeout = __constant_cpu_to_le16 ( 0 ) ;
cp . min_local_timeout = __constant_cpu_to_le16 ( 0 ) ;
2011-12-07 13:24:33 -02:00
hci_send_cmd ( hdev , HCI_OP_SNIFF_SUBRATE , sizeof ( cp ) , & cp ) ;
}
2012-01-16 06:10:31 +02:00
if ( ! test_and_set_bit ( HCI_CONN_MODE_CHANGE_PEND , & conn - > flags ) ) {
2011-12-07 13:24:33 -02:00
struct hci_cp_sniff_mode cp ;
cp . handle = cpu_to_le16 ( conn - > handle ) ;
cp . max_interval = cpu_to_le16 ( hdev - > sniff_max_interval ) ;
cp . min_interval = cpu_to_le16 ( hdev - > sniff_min_interval ) ;
2012-05-25 11:38:27 +03:00
cp . attempt = __constant_cpu_to_le16 ( 4 ) ;
cp . timeout = __constant_cpu_to_le16 ( 1 ) ;
2011-12-07 13:24:33 -02:00
hci_send_cmd ( hdev , HCI_OP_SNIFF_MODE , sizeof ( cp ) , & cp ) ;
}
}
2013-10-16 18:11:39 +03:00
static void hci_conn_auto_accept ( struct work_struct * work )
2011-04-28 11:28:54 -07:00
{
2013-10-16 18:11:39 +03:00
struct hci_conn * conn = container_of ( work , struct hci_conn ,
auto_accept_work . work ) ;
2011-04-28 11:28:54 -07:00
2013-10-16 18:11:39 +03:00
hci_send_cmd ( conn - > hdev , HCI_OP_USER_CONFIRM_REPLY , sizeof ( conn - > dst ) ,
2012-05-17 00:36:25 -03:00
& conn - > dst ) ;
2011-04-28 11:28:54 -07:00
}
2005-04-16 15:20:36 -07:00
struct hci_conn * hci_conn_add ( struct hci_dev * hdev , int type , bdaddr_t * dst )
{
struct hci_conn * conn ;
2012-09-25 12:49:43 +03:00
BT_DBG ( " %s dst %pMR " , hdev - > name , dst ) ;
2005-04-16 15:20:36 -07:00
2012-01-30 09:22:09 -03:00
conn = kzalloc ( sizeof ( struct hci_conn ) , GFP_KERNEL ) ;
2006-07-03 10:02:33 +02:00
if ( ! conn )
2005-04-16 15:20:36 -07:00
return NULL ;
bacpy ( & conn - > dst , dst ) ;
2013-10-13 05:23:59 -07:00
bacpy ( & conn - > src , & hdev - > bdaddr ) ;
2008-07-14 20:13:46 +02:00
conn - > hdev = hdev ;
conn - > type = type ;
conn - > mode = HCI_CM_ACTIVE ;
conn - > state = BT_OPEN ;
2009-09-03 12:34:19 +03:00
conn - > auth_type = HCI_AT_GENERAL_BONDING ;
2011-01-25 13:28:33 +02:00
conn - > io_capability = hdev - > io_capability ;
2011-02-19 12:06:01 -03:00
conn - > remote_auth = 0xff ;
2011-04-28 12:07:55 +02:00
conn - > key_type = 0xff ;
2005-04-16 15:20:36 -07:00
2012-01-16 06:47:28 +02:00
set_bit ( HCI_CONN_POWER_SAVE , & conn - > flags ) ;
2009-04-26 20:01:22 +02:00
conn - > disc_timeout = HCI_DISCONN_TIMEOUT ;
2006-07-03 10:02:33 +02:00
2008-07-14 20:13:46 +02:00
switch ( type ) {
case ACL_LINK :
conn - > pkt_type = hdev - > pkt_type & ACL_PTYPE_MASK ;
break ;
case SCO_LINK :
if ( lmp_esco_capable ( hdev ) )
2009-02-06 09:13:37 +01:00
conn - > pkt_type = ( hdev - > esco_type & SCO_ESCO_MASK ) |
( hdev - > esco_type & EDR_ESCO_MASK ) ;
2008-07-14 20:13:46 +02:00
else
conn - > pkt_type = hdev - > pkt_type & SCO_PTYPE_MASK ;
break ;
case ESCO_LINK :
2009-02-06 09:13:37 +01:00
conn - > pkt_type = hdev - > esco_type & ~ EDR_ESCO_MASK ;
2008-07-14 20:13:46 +02:00
break ;
}
2005-04-16 15:20:36 -07:00
skb_queue_head_init ( & conn - > data_q ) ;
2006-07-03 10:02:33 +02:00
2012-02-22 12:06:43 +01:00
INIT_LIST_HEAD ( & conn - > chan_list ) ;
2011-11-02 15:52:01 +02:00
2011-06-17 13:03:21 -03:00
INIT_DELAYED_WORK ( & conn - > disc_work , hci_conn_timeout ) ;
2013-10-16 18:11:39 +03:00
INIT_DELAYED_WORK ( & conn - > auto_accept_work , hci_conn_auto_accept ) ;
2013-10-16 18:11:40 +03:00
INIT_DELAYED_WORK ( & conn - > idle_work , hci_conn_idle ) ;
2005-04-16 15:20:36 -07:00
atomic_set ( & conn - > refcnt , 0 ) ;
hci_dev_hold ( hdev ) ;
hci_conn_hash_add ( hdev , conn ) ;
2011-12-14 22:58:44 -02:00
if ( hdev - > notify )
2005-04-16 15:20:36 -07:00
hdev - > notify ( hdev , HCI_NOTIFY_CONN_ADD ) ;
2009-05-02 18:24:06 -07:00
hci_conn_init_sysfs ( conn ) ;
2005-04-16 15:20:36 -07:00
return conn ;
}
int hci_conn_del ( struct hci_conn * conn )
{
struct hci_dev * hdev = conn - > hdev ;
2012-06-15 11:50:28 +03:00
BT_DBG ( " %s hcon %p handle %d " , hdev - > name , conn , conn - > handle ) ;
2005-04-16 15:20:36 -07:00
2011-06-17 13:03:21 -03:00
cancel_delayed_work_sync ( & conn - > disc_work ) ;
2013-10-16 18:11:39 +03:00
cancel_delayed_work_sync ( & conn - > auto_accept_work ) ;
2013-10-16 18:11:40 +03:00
cancel_delayed_work_sync ( & conn - > idle_work ) ;
2011-04-28 11:28:54 -07:00
2007-07-11 09:51:55 +02:00
if ( conn - > type = = ACL_LINK ) {
2005-04-16 15:20:36 -07:00
struct hci_conn * sco = conn - > link ;
if ( sco )
sco - > link = NULL ;
/* Unacked frames */
hdev - > acl_cnt + = conn - > sent ;
2011-02-10 22:38:48 -03:00
} else if ( conn - > type = = LE_LINK ) {
if ( hdev - > le_pkts )
hdev - > le_cnt + = conn - > sent ;
else
hdev - > acl_cnt + = conn - > sent ;
2007-07-11 09:51:55 +02:00
} else {
struct hci_conn * acl = conn - > link ;
if ( acl ) {
acl - > link = NULL ;
2013-04-06 20:28:37 +02:00
hci_conn_drop ( acl ) ;
2007-07-11 09:51:55 +02:00
}
2005-04-16 15:20:36 -07:00
}
2011-12-14 13:02:51 -02:00
hci_chan_list_flush ( conn ) ;
2011-11-02 15:52:01 +02:00
2012-05-29 13:59:02 +03:00
if ( conn - > amp_mgr )
amp_mgr_put ( conn - > amp_mgr ) ;
2005-04-16 15:20:36 -07:00
hci_conn_hash_del ( hdev , conn ) ;
2011-12-14 22:58:44 -02:00
if ( hdev - > notify )
2005-04-16 15:20:36 -07:00
hdev - > notify ( hdev , HCI_NOTIFY_CONN_DEL ) ;
2008-07-14 20:13:51 +02:00
2005-04-16 15:20:36 -07:00
skb_queue_purge ( & conn - > data_q ) ;
Bluetooth: remove unneeded hci_conn_hold/put_device()
hci_conn_hold/put_device() is used to control when hci_conn->dev is no
longer needed and can be deleted from the system. Lets first look how they
are currently used throughout the code (excluding HIDP!).
All code that uses hci_conn_hold_device() looks like this:
...
hci_conn_hold_device();
hci_conn_add_sysfs();
...
On the other side, hci_conn_put_device() is exclusively used in
hci_conn_del().
So, considering that hci_conn_del() must not be called twice (which would
fail horribly), we know that hci_conn_put_device() is only called _once_
(which is in hci_conn_del()).
On the other hand, hci_conn_add_sysfs() must not be called twice, either
(it would call device_add twice, which breaks the device, see
drivers/base/core.c). So we know that hci_conn_hold_device() is also
called only once (it's only called directly before hci_conn_add_sysfs()).
So hold and put are known to be called only once. That means we can safely
remove them and directly call hci_conn_del_sysfs() in hci_conn_del().
But there is one issue left: HIDP also uses hci_conn_hold/put_device().
However, this case can be ignored and simply removed as it is totally
broken. The issue is, the only thing HIDP delays with
hci_conn_hold_device() is the removal of the hci_conn->dev from sysfs.
But, the hci_conn device has no mechanism to get notified when its own
parent (hci_dev) gets removed from sysfs. hci_dev_hold/put() does _not_
control when it is removed but only when the device object is created
and destroyed.
And hci_dev calls hci_conn_flush_*() when it removes itself from sysfs,
which itself causes hci_conn_del() to be called, but it does _not_ cause
hci_conn_del_sysfs() to be called, which is wrong.
Hence, we fix it to call hci_conn_del_sysfs() in hci_conn_del(). This
guarantees that a hci_conn object is removed from sysfs _before_ its
parent hci_dev is removed.
The changes to HIDP look scary, wrong and broken. However, if you look at
the HIDP session management, you will notice they're already broken in the
exact _same_ way (ever tried "unplugging" HIDP devices? Breaks _all_ the
time).
So this patch only makes HIDP look _scary_ and _obviously broken_. It does
not break HIDP itself, it already is!
See later patches in this series which fix HIDP to use proper
session-management.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
2013-04-06 20:28:38 +02:00
hci_conn_del_sysfs ( conn ) ;
2009-02-21 16:13:34 +08:00
2009-05-08 18:20:43 -07:00
hci_dev_put ( hdev ) ;
Bluetooth: introduce hci_conn ref-counting
We currently do not allow using hci_conn from outside of HCI-core.
However, several other users could make great use of it. This includes
HIDP, rfcomm and all other sub-protocols that rely on an active
connection.
Hence, we now introduce hci_conn ref-counting. We currently never call
get_device(). put_device() is exclusively used in hci_conn_del_sysfs().
Hence, we currently never have a greater device-refcnt than 1.
Therefore, it is safe to move the put_device() call from
hci_conn_del_sysfs() to hci_conn_del() (it's the only caller). In fact,
this even fixes a "use-after-free" bug as we access hci_conn after calling
hci_conn_del_sysfs() in hci_conn_del().
From now on we can add references to hci_conn objects in other layers
(like l2cap_sock, HIDP, rfcomm, ...) and grab a reference via
hci_conn_get(). This does _not_ guarantee, that the connection is still
alive. But, this isn't what we want. We can simply lock the hci_conn
device and use "device_is_registered(hci_conn->dev)" to test that.
However, this is hardly necessary as outside users should never rely on
the HCI connection to be alive, anyway. Instead, they should solely rely
on the device-object to be available.
But if sub-devices want the hci_conn object as sysfs parent, they need to
be notified when the connection drops. This will be introduced in later
patches with l2cap_users.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
2013-04-06 20:28:39 +02:00
hci_conn_put ( conn ) ;
2011-06-30 16:30:44 -03:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
struct hci_dev * hci_get_route ( bdaddr_t * dst , bdaddr_t * src )
{
int use_src = bacmp ( src , BDADDR_ANY ) ;
2011-11-01 10:58:56 +02:00
struct hci_dev * hdev = NULL , * d ;
2005-04-16 15:20:36 -07:00
2012-09-25 12:49:43 +03:00
BT_DBG ( " %pMR -> %pMR " , src , dst ) ;
2005-04-16 15:20:36 -07:00
2011-12-22 16:30:27 -02:00
read_lock ( & hci_dev_list_lock ) ;
2005-04-16 15:20:36 -07:00
2011-11-01 10:58:56 +02:00
list_for_each_entry ( d , & hci_dev_list , list ) {
2012-05-23 04:04:21 -03:00
if ( ! test_bit ( HCI_UP , & d - > flags ) | |
2012-06-19 15:21:21 +03:00
test_bit ( HCI_RAW , & d - > flags ) | |
2013-09-03 18:08:37 -07:00
test_bit ( HCI_USER_CHANNEL , & d - > dev_flags ) | |
2012-06-19 15:21:21 +03:00
d - > dev_type ! = HCI_BREDR )
2005-04-16 15:20:36 -07:00
continue ;
2007-02-09 23:24:33 +09:00
/* Simple routing:
2005-04-16 15:20:36 -07:00
* No source address - find interface with bdaddr ! = dst
* Source address - find interface with bdaddr = = src
*/
if ( use_src ) {
if ( ! bacmp ( & d - > bdaddr , src ) ) {
hdev = d ; break ;
}
} else {
if ( bacmp ( & d - > bdaddr , dst ) ) {
hdev = d ; break ;
}
}
}
if ( hdev )
hdev = hci_dev_hold ( hdev ) ;
2011-12-22 16:30:27 -02:00
read_unlock ( & hci_dev_list_lock ) ;
2005-04-16 15:20:36 -07:00
return hdev ;
}
EXPORT_SYMBOL ( hci_get_route ) ;
2013-10-08 08:21:17 -03:00
static void create_le_conn_complete ( struct hci_dev * hdev , u8 status )
{
struct hci_conn * conn ;
if ( status = = 0 )
return ;
BT_ERR ( " HCI request failed to create LE connection: status 0x%2.2x " ,
status ) ;
hci_dev_lock ( hdev ) ;
conn = hci_conn_hash_lookup_state ( hdev , LE_LINK , BT_CONNECT ) ;
if ( ! conn )
goto done ;
conn - > state = BT_CLOSED ;
mgmt_connect_failed ( hdev , & conn - > dst , conn - > type , conn - > dst_type ,
status ) ;
hci_proto_connect_cfm ( conn , status ) ;
hci_conn_del ( conn ) ;
done :
hci_dev_unlock ( hdev ) ;
}
static int hci_create_le_conn ( struct hci_conn * conn )
{
struct hci_dev * hdev = conn - > hdev ;
struct hci_cp_le_create_conn cp ;
struct hci_request req ;
int err ;
hci_req_init ( & req , hdev ) ;
memset ( & cp , 0 , sizeof ( cp ) ) ;
2013-10-11 08:23:19 -07:00
cp . scan_interval = cpu_to_le16 ( hdev - > le_scan_interval ) ;
cp . scan_window = cpu_to_le16 ( hdev - > le_scan_window ) ;
2013-10-08 08:21:17 -03:00
bacpy ( & cp . peer_addr , & conn - > dst ) ;
cp . peer_addr_type = conn - > dst_type ;
2013-10-13 03:57:39 -07:00
cp . own_address_type = conn - > src_type ;
2013-10-19 07:09:13 -07:00
cp . conn_interval_min = cpu_to_le16 ( hdev - > le_conn_min_interval ) ;
cp . conn_interval_max = cpu_to_le16 ( hdev - > le_conn_max_interval ) ;
2013-10-08 08:21:17 -03:00
cp . supervision_timeout = __constant_cpu_to_le16 ( 0x002a ) ;
cp . min_ce_len = __constant_cpu_to_le16 ( 0x0000 ) ;
cp . max_ce_len = __constant_cpu_to_le16 ( 0x0000 ) ;
2013-10-19 07:09:13 -07:00
2013-10-08 08:21:17 -03:00
hci_req_add ( & req , HCI_OP_LE_CREATE_CONN , sizeof ( cp ) , & cp ) ;
err = hci_req_run ( & req , create_le_conn_complete ) ;
if ( err ) {
hci_conn_del ( conn ) ;
return err ;
}
return 0 ;
}
2012-07-27 19:32:56 -03:00
static struct hci_conn * hci_connect_le ( struct hci_dev * hdev , bdaddr_t * dst ,
u8 dst_type , u8 sec_level , u8 auth_type )
2005-04-16 15:20:36 -07:00
{
2013-10-03 18:25:44 -03:00
struct hci_conn * conn ;
2013-10-08 08:21:17 -03:00
int err ;
2005-04-16 15:20:36 -07:00
2013-10-05 12:01:04 +02:00
if ( test_bit ( HCI_ADVERTISING , & hdev - > flags ) )
2012-10-24 21:12:03 +03:00
return ERR_PTR ( - ENOTSUPP ) ;
2013-10-08 08:21:18 -03:00
/* Some devices send ATT messages as soon as the physical link is
* established . To be able to handle these ATT messages , the user -
* space first establishes the connection and then starts the pairing
* process .
*
* So if a hci_conn object already exists for the following connection
* attempt , we simply update pending_sec_level and auth_type fields
* and return the object found .
*/
2013-10-03 18:25:44 -03:00
conn = hci_conn_hash_lookup_ba ( hdev , LE_LINK , dst ) ;
2013-10-08 08:21:18 -03:00
if ( conn ) {
conn - > pending_sec_level = sec_level ;
conn - > auth_type = auth_type ;
goto done ;
}
2012-05-30 15:39:21 +02:00
2013-10-08 08:21:18 -03:00
/* Since the controller supports only one LE connection attempt at a
* time , we return - EBUSY if there is any connection attempt running .
*/
conn = hci_conn_hash_lookup_state ( hdev , LE_LINK , BT_CONNECT ) ;
if ( conn )
return ERR_PTR ( - EBUSY ) ;
2013-10-03 18:25:45 -03:00
2013-10-08 08:21:18 -03:00
conn = hci_conn_add ( hdev , LE_LINK , dst ) ;
if ( ! conn )
return ERR_PTR ( - ENOMEM ) ;
2012-04-20 15:46:08 -03:00
2013-10-13 03:57:38 -07:00
if ( dst_type = = BDADDR_LE_PUBLIC )
conn - > dst_type = ADDR_LE_DEV_PUBLIC ;
else
conn - > dst_type = ADDR_LE_DEV_RANDOM ;
2013-10-13 03:57:39 -07:00
2013-10-18 16:38:09 -07:00
conn - > src_type = hdev - > own_addr_type ;
2013-10-13 03:57:39 -07:00
2013-10-08 08:21:18 -03:00
conn - > state = BT_CONNECT ;
conn - > out = true ;
conn - > link_mode | = HCI_LM_MASTER ;
conn - > sec_level = BT_SECURITY_LOW ;
2013-10-03 18:25:44 -03:00
conn - > pending_sec_level = sec_level ;
conn - > auth_type = auth_type ;
2011-05-31 14:20:56 -03:00
2013-10-08 08:21:18 -03:00
err = hci_create_le_conn ( conn ) ;
if ( err )
return ERR_PTR ( err ) ;
2011-02-10 22:38:47 -03:00
2013-10-08 08:21:18 -03:00
done :
hci_conn_hold ( conn ) ;
2013-10-03 18:25:44 -03:00
return conn ;
2012-07-27 19:32:56 -03:00
}
2011-02-10 22:38:47 -03:00
2012-07-28 22:35:59 -03:00
static struct hci_conn * hci_connect_acl ( struct hci_dev * hdev , bdaddr_t * dst ,
u8 sec_level , u8 auth_type )
2005-04-16 15:20:36 -07:00
{
struct hci_conn * acl ;
2011-02-10 22:38:47 -03:00
2013-10-02 13:43:13 +03:00
if ( ! test_bit ( HCI_BREDR_ENABLED , & hdev - > dev_flags ) )
return ERR_PTR ( - ENOTSUPP ) ;
2010-12-01 16:58:25 +02:00
acl = hci_conn_hash_lookup_ba ( hdev , ACL_LINK , dst ) ;
if ( ! acl ) {
acl = hci_conn_add ( hdev , ACL_LINK , dst ) ;
if ( ! acl )
2012-02-19 14:06:48 +02:00
return ERR_PTR ( - ENOMEM ) ;
2005-04-16 15:20:36 -07:00
}
hci_conn_hold ( acl ) ;
2008-09-09 07:19:20 +02:00
if ( acl - > state = = BT_OPEN | | acl - > state = = BT_CLOSED ) {
2011-01-19 12:06:52 +05:30
acl - > sec_level = BT_SECURITY_LOW ;
acl - > pending_sec_level = sec_level ;
2008-09-09 07:19:20 +02:00
acl - > auth_type = auth_type ;
2012-07-27 19:32:55 -03:00
hci_acl_create_connection ( acl ) ;
2008-09-09 07:19:20 +02:00
}
2005-04-16 15:20:36 -07:00
2012-07-28 22:35:59 -03:00
return acl ;
}
2013-08-19 14:23:59 +02:00
struct hci_conn * hci_connect_sco ( struct hci_dev * hdev , int type , bdaddr_t * dst ,
__u16 setting )
2012-07-28 22:35:59 -03:00
{
struct hci_conn * acl ;
struct hci_conn * sco ;
2013-08-19 14:23:54 +02:00
acl = hci_connect_acl ( hdev , dst , BT_SECURITY_LOW , HCI_AT_NO_BONDING ) ;
2012-07-28 22:35:59 -03:00
if ( IS_ERR ( acl ) )
2007-07-11 09:51:55 +02:00
return acl ;
2005-04-16 15:20:36 -07:00
2010-12-01 16:58:25 +02:00
sco = hci_conn_hash_lookup_ba ( hdev , type , dst ) ;
if ( ! sco ) {
sco = hci_conn_add ( hdev , type , dst ) ;
if ( ! sco ) {
2013-04-06 20:28:37 +02:00
hci_conn_drop ( acl ) ;
2012-02-19 14:06:48 +02:00
return ERR_PTR ( - ENOMEM ) ;
2005-04-16 15:20:36 -07:00
}
2007-07-11 09:51:55 +02:00
}
2005-04-16 15:20:36 -07:00
2007-07-11 09:51:55 +02:00
acl - > link = sco ;
sco - > link = acl ;
2005-04-16 15:20:36 -07:00
2007-07-11 09:51:55 +02:00
hci_conn_hold ( sco ) ;
2005-04-16 15:20:36 -07:00
2013-08-19 14:23:59 +02:00
sco - > setting = setting ;
2007-07-11 09:51:55 +02:00
if ( acl - > state = = BT_CONNECTED & &
2012-05-17 00:36:25 -03:00
( sco - > state = = BT_OPEN | | sco - > state = = BT_CLOSED ) ) {
2012-01-16 06:47:28 +02:00
set_bit ( HCI_CONN_POWER_SAVE , & acl - > flags ) ;
2011-05-23 18:06:04 -07:00
hci_conn_enter_active_mode ( acl , BT_POWER_FORCE_ACTIVE_ON ) ;
2009-11-13 14:16:32 -08:00
2012-01-16 06:10:31 +02:00
if ( test_bit ( HCI_CONN_MODE_CHANGE_PEND , & acl - > flags ) ) {
2010-07-26 10:06:00 -04:00
/* defer SCO setup until mode change completed */
2012-01-16 06:10:31 +02:00
set_bit ( HCI_CONN_SCO_SETUP_PEND , & acl - > flags ) ;
2010-07-26 10:06:00 -04:00
return sco ;
}
hci_sco_setup ( acl , 0x00 ) ;
2007-10-20 14:55:10 +02:00
}
2007-07-11 09:51:55 +02:00
return sco ;
2005-04-16 15:20:36 -07:00
}
2012-07-27 19:32:58 -03:00
/* Create SCO, ACL or LE connection. */
struct hci_conn * hci_connect ( struct hci_dev * hdev , int type , bdaddr_t * dst ,
__u8 dst_type , __u8 sec_level , __u8 auth_type )
{
2012-09-25 12:49:43 +03:00
BT_DBG ( " %s dst %pMR type 0x%x " , hdev - > name , dst , type ) ;
2012-07-27 19:32:58 -03:00
2012-07-27 19:32:59 -03:00
switch ( type ) {
case LE_LINK :
2012-07-27 19:32:58 -03:00
return hci_connect_le ( hdev , dst , dst_type , sec_level , auth_type ) ;
2012-07-27 19:32:59 -03:00
case ACL_LINK :
2012-07-27 19:32:58 -03:00
return hci_connect_acl ( hdev , dst , sec_level , auth_type ) ;
2012-07-27 19:32:59 -03:00
}
2012-07-27 19:32:58 -03:00
2012-07-27 19:32:59 -03:00
return ERR_PTR ( - EINVAL ) ;
2012-07-27 19:32:58 -03:00
}
2008-09-09 07:19:20 +02:00
/* Check link security requirement */
int hci_conn_check_link_mode ( struct hci_conn * conn )
{
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2008-09-09 07:19:20 +02:00
2012-01-18 21:33:12 +02:00
if ( hci_conn_ssp_enabled ( conn ) & & ! ( conn - > link_mode & HCI_LM_ENCRYPT ) )
2008-09-09 07:19:20 +02:00
return 0 ;
return 1 ;
}
2005-04-16 15:20:36 -07:00
/* Authenticate remote device */
2009-02-09 02:48:38 +01:00
static int hci_conn_auth ( struct hci_conn * conn , __u8 sec_level , __u8 auth_type )
2005-04-16 15:20:36 -07:00
{
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2005-04-16 15:20:36 -07:00
2011-01-19 12:06:52 +05:30
if ( conn - > pending_sec_level > sec_level )
sec_level = conn - > pending_sec_level ;
2009-02-12 16:23:03 +01:00
if ( sec_level > conn - > sec_level )
2011-01-19 12:06:52 +05:30
conn - > pending_sec_level = sec_level ;
2009-02-12 16:23:03 +01:00
else if ( conn - > link_mode & HCI_LM_AUTH )
2005-04-16 15:20:36 -07:00
return 1 ;
2011-01-19 12:06:49 +05:30
/* Make sure we preserve an existing MITM requirement*/
auth_type | = ( conn - > auth_type & 0x01 ) ;
2009-02-12 16:23:03 +01:00
conn - > auth_type = auth_type ;
2012-01-16 06:10:31 +02:00
if ( ! test_and_set_bit ( HCI_CONN_AUTH_PEND , & conn - > flags ) ) {
2005-04-16 15:20:36 -07:00
struct hci_cp_auth_requested cp ;
2012-01-13 15:11:30 +01:00
/* encrypt must be pending if auth is also pending */
set_bit ( HCI_CONN_ENCRYPT_PEND , & conn - > flags ) ;
2007-03-25 20:12:50 -07:00
cp . handle = cpu_to_le16 ( conn - > handle ) ;
2008-07-14 20:13:50 +02:00
hci_send_cmd ( conn - > hdev , HCI_OP_AUTH_REQUESTED ,
2012-05-17 00:36:25 -03:00
sizeof ( cp ) , & cp ) ;
2011-05-31 15:49:25 +02:00
if ( conn - > key_type ! = 0xff )
2012-01-16 06:10:31 +02:00
set_bit ( HCI_CONN_REAUTH_PEND , & conn - > flags ) ;
2005-04-16 15:20:36 -07:00
}
2009-01-15 21:58:04 +01:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2011-04-28 12:07:55 +02:00
/* Encrypt the the link */
static void hci_conn_encrypt ( struct hci_conn * conn )
{
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2011-04-28 12:07:55 +02:00
2012-01-16 06:10:31 +02:00
if ( ! test_and_set_bit ( HCI_CONN_ENCRYPT_PEND , & conn - > flags ) ) {
2011-04-28 12:07:55 +02:00
struct hci_cp_set_conn_encrypt cp ;
cp . handle = cpu_to_le16 ( conn - > handle ) ;
cp . encrypt = 0x01 ;
hci_send_cmd ( conn - > hdev , HCI_OP_SET_CONN_ENCRYPT , sizeof ( cp ) ,
2012-05-17 00:36:25 -03:00
& cp ) ;
2011-04-28 12:07:55 +02:00
}
}
2009-01-15 21:58:04 +01:00
/* Enable security */
2009-02-09 02:48:38 +01:00
int hci_conn_security ( struct hci_conn * conn , __u8 sec_level , __u8 auth_type )
2005-04-16 15:20:36 -07:00
{
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2005-04-16 15:20:36 -07:00
2012-08-23 21:32:44 -03:00
if ( conn - > type = = LE_LINK )
return smp_conn_security ( conn , sec_level ) ;
2011-04-28 12:07:55 +02:00
/* For sdp we don't need the link key. */
2009-01-15 21:58:04 +01:00
if ( sec_level = = BT_SECURITY_SDP )
return 1 ;
2011-04-28 12:07:55 +02:00
/* For non 2.1 devices and low security level we don't need the link
key . */
2012-01-18 21:33:12 +02:00
if ( sec_level = = BT_SECURITY_LOW & & ! hci_conn_ssp_enabled ( conn ) )
2009-04-28 09:04:55 -07:00
return 1 ;
2009-01-15 21:58:04 +01:00
2011-04-28 12:07:55 +02:00
/* For other security levels we need the link key. */
if ( ! ( conn - > link_mode & HCI_LM_AUTH ) )
goto auth ;
/* An authenticated combination key has sufficient security for any
security level . */
if ( conn - > key_type = = HCI_LK_AUTH_COMBINATION )
goto encrypt ;
/* An unauthenticated combination key has sufficient security for
security level 1 and 2. */
if ( conn - > key_type = = HCI_LK_UNAUTH_COMBINATION & &
2012-05-17 00:36:25 -03:00
( sec_level = = BT_SECURITY_MEDIUM | | sec_level = = BT_SECURITY_LOW ) )
2011-04-28 12:07:55 +02:00
goto encrypt ;
/* A combination key has always sufficient security for the security
levels 1 or 2. High security level requires the combination key
is generated using maximum PIN code length ( 16 ) .
For pre 2.1 units . */
if ( conn - > key_type = = HCI_LK_COMBINATION & &
2012-05-17 00:36:25 -03:00
( sec_level ! = BT_SECURITY_HIGH | | conn - > pin_length = = 16 ) )
2011-04-28 12:07:55 +02:00
goto encrypt ;
auth :
2012-01-16 06:10:31 +02:00
if ( test_bit ( HCI_CONN_ENCRYPT_PEND , & conn - > flags ) )
2005-04-16 15:20:36 -07:00
return 0 ;
2011-06-13 15:37:35 +03:00
if ( ! hci_conn_auth ( conn , sec_level , auth_type ) )
return 0 ;
2011-04-28 12:07:55 +02:00
encrypt :
if ( conn - > link_mode & HCI_LM_ENCRYPT )
return 1 ;
2009-01-15 21:58:04 +01:00
2011-04-28 12:07:55 +02:00
hci_conn_encrypt ( conn ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2009-01-15 21:58:04 +01:00
EXPORT_SYMBOL ( hci_conn_security ) ;
2005-04-16 15:20:36 -07:00
2011-05-06 09:42:31 +02:00
/* Check secure link requirement */
int hci_conn_check_secure ( struct hci_conn * conn , __u8 sec_level )
{
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2011-05-06 09:42:31 +02:00
if ( sec_level ! = BT_SECURITY_HIGH )
return 1 ; /* Accept if non-secure is required */
2011-06-02 14:24:52 +02:00
if ( conn - > sec_level = = BT_SECURITY_HIGH )
2011-05-06 09:42:31 +02:00
return 1 ;
return 0 ; /* Reject not secure link */
}
EXPORT_SYMBOL ( hci_conn_check_secure ) ;
2005-04-16 15:20:36 -07:00
/* Change link key */
int hci_conn_change_link_key ( struct hci_conn * conn )
{
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2005-04-16 15:20:36 -07:00
2012-01-16 06:10:31 +02:00
if ( ! test_and_set_bit ( HCI_CONN_AUTH_PEND , & conn - > flags ) ) {
2005-04-16 15:20:36 -07:00
struct hci_cp_change_conn_link_key cp ;
2007-03-25 20:12:50 -07:00
cp . handle = cpu_to_le16 ( conn - > handle ) ;
2008-07-14 20:13:50 +02:00
hci_send_cmd ( conn - > hdev , HCI_OP_CHANGE_CONN_LINK_KEY ,
2012-05-17 00:36:25 -03:00
sizeof ( cp ) , & cp ) ;
2005-04-16 15:20:36 -07:00
}
2009-01-15 21:58:04 +01:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
/* Switch role */
2009-01-15 21:58:04 +01:00
int hci_conn_switch_role ( struct hci_conn * conn , __u8 role )
2005-04-16 15:20:36 -07:00
{
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2005-04-16 15:20:36 -07:00
if ( ! role & & conn - > link_mode & HCI_LM_MASTER )
return 1 ;
2012-01-16 06:10:31 +02:00
if ( ! test_and_set_bit ( HCI_CONN_RSWITCH_PEND , & conn - > flags ) ) {
2005-04-16 15:20:36 -07:00
struct hci_cp_switch_role cp ;
bacpy ( & cp . bdaddr , & conn - > dst ) ;
cp . role = role ;
2007-10-20 13:33:56 +02:00
hci_send_cmd ( conn - > hdev , HCI_OP_SWITCH_ROLE , sizeof ( cp ) , & cp ) ;
2005-04-16 15:20:36 -07:00
}
2009-01-15 21:58:04 +01:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
EXPORT_SYMBOL ( hci_conn_switch_role ) ;
2006-07-03 10:02:33 +02:00
/* Enter active mode */
2011-05-23 18:06:04 -07:00
void hci_conn_enter_active_mode ( struct hci_conn * conn , __u8 force_active )
2006-07-03 10:02:33 +02:00
{
struct hci_dev * hdev = conn - > hdev ;
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p mode %d " , conn , conn - > mode ) ;
2006-07-03 10:02:33 +02:00
if ( test_bit ( HCI_RAW , & hdev - > flags ) )
return ;
2011-05-23 18:06:04 -07:00
if ( conn - > mode ! = HCI_CM_SNIFF )
goto timer ;
2012-01-16 06:47:28 +02:00
if ( ! test_bit ( HCI_CONN_POWER_SAVE , & conn - > flags ) & & ! force_active )
2006-07-03 10:02:33 +02:00
goto timer ;
2012-01-16 06:10:31 +02:00
if ( ! test_and_set_bit ( HCI_CONN_MODE_CHANGE_PEND , & conn - > flags ) ) {
2006-07-03 10:02:33 +02:00
struct hci_cp_exit_sniff_mode cp ;
2007-03-25 20:12:50 -07:00
cp . handle = cpu_to_le16 ( conn - > handle ) ;
2007-10-20 13:33:56 +02:00
hci_send_cmd ( hdev , HCI_OP_EXIT_SNIFF_MODE , sizeof ( cp ) , & cp ) ;
2006-07-03 10:02:33 +02:00
}
timer :
if ( hdev - > idle_timeout > 0 )
2013-10-16 18:11:40 +03:00
queue_delayed_work ( hdev - > workqueue , & conn - > idle_work ,
msecs_to_jiffies ( hdev - > idle_timeout ) ) ;
2006-07-03 10:02:33 +02:00
}
2005-04-16 15:20:36 -07:00
/* Drop all connection on the device */
void hci_conn_hash_flush ( struct hci_dev * hdev )
{
struct hci_conn_hash * h = & hdev - > conn_hash ;
2012-02-02 10:32:17 +02:00
struct hci_conn * c , * n ;
2005-04-16 15:20:36 -07:00
BT_DBG ( " hdev %s " , hdev - > name ) ;
2012-02-02 10:32:17 +02:00
list_for_each_entry_safe ( c , n , & h - > list , list ) {
2005-04-16 15:20:36 -07:00
c - > state = BT_CLOSED ;
2011-11-07 14:20:25 +02:00
hci_proto_disconn_cfm ( c , HCI_ERROR_LOCAL_HOST_TERM ) ;
2005-04-16 15:20:36 -07:00
hci_conn_del ( c ) ;
}
}
2007-10-20 13:33:56 +02:00
/* Check pending connect attempts */
void hci_conn_check_pending ( struct hci_dev * hdev )
{
struct hci_conn * conn ;
BT_DBG ( " hdev %s " , hdev - > name ) ;
hci_dev_lock ( hdev ) ;
conn = hci_conn_hash_lookup_state ( hdev , ACL_LINK , BT_CONNECT2 ) ;
if ( conn )
2012-07-27 19:32:55 -03:00
hci_acl_create_connection ( conn ) ;
2007-10-20 13:33:56 +02:00
hci_dev_unlock ( hdev ) ;
}
2005-04-16 15:20:36 -07:00
int hci_get_conn_list ( void __user * arg )
{
2012-05-23 04:04:19 -03:00
struct hci_conn * c ;
2005-04-16 15:20:36 -07:00
struct hci_conn_list_req req , * cl ;
struct hci_conn_info * ci ;
struct hci_dev * hdev ;
int n = 0 , size , err ;
if ( copy_from_user ( & req , arg , sizeof ( req ) ) )
return - EFAULT ;
if ( ! req . conn_num | | req . conn_num > ( PAGE_SIZE * 2 ) / sizeof ( * ci ) )
return - EINVAL ;
size = sizeof ( req ) + req . conn_num * sizeof ( * ci ) ;
2010-12-01 16:58:25 +02:00
cl = kmalloc ( size , GFP_KERNEL ) ;
if ( ! cl )
2005-04-16 15:20:36 -07:00
return - ENOMEM ;
2010-12-01 16:58:25 +02:00
hdev = hci_dev_get ( req . dev_id ) ;
if ( ! hdev ) {
2005-04-16 15:20:36 -07:00
kfree ( cl ) ;
return - ENODEV ;
}
ci = cl - > conn_info ;
2011-06-17 13:03:21 -03:00
hci_dev_lock ( hdev ) ;
2011-11-01 10:58:56 +02:00
list_for_each_entry ( c , & hdev - > conn_hash . list , list ) {
2005-04-16 15:20:36 -07:00
bacpy ( & ( ci + n ) - > bdaddr , & c - > dst ) ;
( ci + n ) - > handle = c - > handle ;
( ci + n ) - > type = c - > type ;
( ci + n ) - > out = c - > out ;
( ci + n ) - > state = c - > state ;
( ci + n ) - > link_mode = c - > link_mode ;
if ( + + n > = req . conn_num )
break ;
}
2011-06-17 13:03:21 -03:00
hci_dev_unlock ( hdev ) ;
2005-04-16 15:20:36 -07:00
cl - > dev_id = hdev - > id ;
cl - > conn_num = n ;
size = sizeof ( req ) + n * sizeof ( * ci ) ;
hci_dev_put ( hdev ) ;
err = copy_to_user ( arg , cl , size ) ;
kfree ( cl ) ;
return err ? - EFAULT : 0 ;
}
int hci_get_conn_info ( struct hci_dev * hdev , void __user * arg )
{
struct hci_conn_info_req req ;
struct hci_conn_info ci ;
struct hci_conn * conn ;
char __user * ptr = arg + sizeof ( req ) ;
if ( copy_from_user ( & req , arg , sizeof ( req ) ) )
return - EFAULT ;
2011-06-17 13:03:21 -03:00
hci_dev_lock ( hdev ) ;
2005-04-16 15:20:36 -07:00
conn = hci_conn_hash_lookup_ba ( hdev , req . type , & req . bdaddr ) ;
if ( conn ) {
bacpy ( & ci . bdaddr , & conn - > dst ) ;
ci . handle = conn - > handle ;
ci . type = conn - > type ;
ci . out = conn - > out ;
ci . state = conn - > state ;
ci . link_mode = conn - > link_mode ;
}
2011-06-17 13:03:21 -03:00
hci_dev_unlock ( hdev ) ;
2005-04-16 15:20:36 -07:00
if ( ! conn )
return - ENOENT ;
return copy_to_user ( ptr , & ci , sizeof ( ci ) ) ? - EFAULT : 0 ;
}
2008-07-14 20:13:50 +02:00
int hci_get_auth_info ( struct hci_dev * hdev , void __user * arg )
{
struct hci_auth_info_req req ;
struct hci_conn * conn ;
if ( copy_from_user ( & req , arg , sizeof ( req ) ) )
return - EFAULT ;
2011-06-17 13:03:21 -03:00
hci_dev_lock ( hdev ) ;
2008-07-14 20:13:50 +02:00
conn = hci_conn_hash_lookup_ba ( hdev , ACL_LINK , & req . bdaddr ) ;
if ( conn )
req . type = conn - > auth_type ;
2011-06-17 13:03:21 -03:00
hci_dev_unlock ( hdev ) ;
2008-07-14 20:13:50 +02:00
if ( ! conn )
return - ENOENT ;
return copy_to_user ( arg , & req , sizeof ( req ) ) ? - EFAULT : 0 ;
}
2011-11-02 15:52:01 +02:00
struct hci_chan * hci_chan_create ( struct hci_conn * conn )
{
struct hci_dev * hdev = conn - > hdev ;
struct hci_chan * chan ;
2012-06-15 11:50:28 +03:00
BT_DBG ( " %s hcon %p " , hdev - > name , conn ) ;
2011-11-02 15:52:01 +02:00
2012-01-30 09:22:10 -03:00
chan = kzalloc ( sizeof ( struct hci_chan ) , GFP_KERNEL ) ;
2011-11-02 15:52:01 +02:00
if ( ! chan )
return NULL ;
chan - > conn = conn ;
skb_queue_head_init ( & chan - > data_q ) ;
2012-10-23 15:24:13 -07:00
chan - > state = BT_CONNECTED ;
2011-11-02 15:52:01 +02:00
2011-12-14 15:08:48 -02:00
list_add_rcu ( & chan - > list , & conn - > chan_list ) ;
2011-11-02 15:52:01 +02:00
return chan ;
}
2012-09-06 15:05:43 +03:00
void hci_chan_del ( struct hci_chan * chan )
2011-11-02 15:52:01 +02:00
{
struct hci_conn * conn = chan - > conn ;
struct hci_dev * hdev = conn - > hdev ;
2012-06-15 11:50:28 +03:00
BT_DBG ( " %s hcon %p chan %p " , hdev - > name , conn , chan ) ;
2011-11-02 15:52:01 +02:00
2011-12-14 15:08:48 -02:00
list_del_rcu ( & chan - > list ) ;
synchronize_rcu ( ) ;
2011-11-02 15:52:01 +02:00
2013-04-06 20:28:37 +02:00
hci_conn_drop ( conn ) ;
2012-10-25 15:20:51 +03:00
2011-11-02 15:52:01 +02:00
skb_queue_purge ( & chan - > data_q ) ;
kfree ( chan ) ;
}
2011-12-14 13:02:51 -02:00
void hci_chan_list_flush ( struct hci_conn * conn )
2011-11-02 15:52:01 +02:00
{
2012-02-02 10:32:18 +02:00
struct hci_chan * chan , * n ;
2011-11-02 15:52:01 +02:00
2012-06-15 11:50:28 +03:00
BT_DBG ( " hcon %p " , conn ) ;
2011-11-02 15:52:01 +02:00
2012-02-02 10:32:18 +02:00
list_for_each_entry_safe ( chan , n , & conn - > chan_list , list )
2011-11-02 15:52:01 +02:00
hci_chan_del ( chan ) ;
}
2012-10-10 17:38:28 +03:00
static struct hci_chan * __hci_chan_lookup_handle ( struct hci_conn * hcon ,
__u16 handle )
{
struct hci_chan * hchan ;
list_for_each_entry ( hchan , & hcon - > chan_list , list ) {
if ( hchan - > handle = = handle )
return hchan ;
}
return NULL ;
}
struct hci_chan * hci_chan_lookup_handle ( struct hci_dev * hdev , __u16 handle )
{
struct hci_conn_hash * h = & hdev - > conn_hash ;
struct hci_conn * hcon ;
struct hci_chan * hchan = NULL ;
rcu_read_lock ( ) ;
list_for_each_entry_rcu ( hcon , & h - > list , list ) {
hchan = __hci_chan_lookup_handle ( hcon , handle ) ;
if ( hchan )
break ;
}
rcu_read_unlock ( ) ;
return hchan ;
}