2005-04-17 02:20:36 +04:00
/* Bluetooth HCI driver model support. */
2010-02-08 18:22:31 +03:00
# include <linux/debugfs.h>
2011-05-27 17:12:25 +04:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <net/bluetooth/bluetooth.h>
# include <net/bluetooth/hci_core.h>
2010-03-21 07:27:45 +03:00
static struct class * bt_class ;
2008-08-18 15:23:53 +04:00
2011-02-18 01:22:19 +03:00
struct dentry * bt_debugfs ;
2010-02-08 18:22:31 +03:00
EXPORT_SYMBOL_GPL ( bt_debugfs ) ;
2008-08-18 15:23:53 +04:00
static inline char * link_typetostr ( int type )
{
switch ( type ) {
case ACL_LINK :
return " ACL " ;
case SCO_LINK :
return " SCO " ;
case ESCO_LINK :
return " eSCO " ;
2011-08-24 18:04:56 +04:00
case LE_LINK :
return " LE " ;
2008-08-18 15:23:53 +04:00
default :
return " UNKNOWN " ;
}
}
2012-05-17 07:36:23 +04:00
static ssize_t show_link_type ( struct device * dev ,
struct device_attribute * attr , char * buf )
2008-08-18 15:23:53 +04:00
{
2012-02-10 00:58:33 +04:00
struct hci_conn * conn = to_hci_conn ( dev ) ;
2008-08-18 15:23:53 +04:00
return sprintf ( buf , " %s \n " , link_typetostr ( conn - > type ) ) ;
}
2012-05-17 07:36:23 +04:00
static ssize_t show_link_address ( struct device * dev ,
struct device_attribute * attr , char * buf )
2008-08-18 15:23:53 +04:00
{
2012-02-10 00:58:33 +04:00
struct hci_conn * conn = to_hci_conn ( dev ) ;
2012-09-25 13:49:44 +04:00
return sprintf ( buf , " %pMR \n " , & conn - > dst ) ;
2008-08-18 15:23:53 +04:00
}
2012-05-17 07:36:23 +04:00
static ssize_t show_link_features ( struct device * dev ,
struct device_attribute * attr , char * buf )
2008-08-18 15:23:53 +04:00
{
2012-02-10 00:58:33 +04:00
struct hci_conn * conn = to_hci_conn ( dev ) ;
2008-08-18 15:23:53 +04:00
return sprintf ( buf , " 0x%02x%02x%02x%02x%02x%02x%02x%02x \n " ,
2012-05-17 07:36:23 +04:00
conn - > features [ 0 ] , conn - > features [ 1 ] ,
conn - > features [ 2 ] , conn - > features [ 3 ] ,
conn - > features [ 4 ] , conn - > features [ 5 ] ,
conn - > features [ 6 ] , conn - > features [ 7 ] ) ;
2008-08-18 15:23:53 +04:00
}
2011-02-18 01:22:19 +03:00
# define LINK_ATTR(_name, _mode, _show, _store) \
struct device_attribute link_attr_ # # _name = __ATTR ( _name , _mode , _show , _store )
2008-08-18 15:23:53 +04:00
static LINK_ATTR ( type , S_IRUGO , show_link_type , NULL ) ;
static LINK_ATTR ( address , S_IRUGO , show_link_address , NULL ) ;
static LINK_ATTR ( features , S_IRUGO , show_link_features , NULL ) ;
static struct attribute * bt_link_attrs [ ] = {
& link_attr_type . attr ,
& link_attr_address . attr ,
& link_attr_features . attr ,
NULL
} ;
static struct attribute_group bt_link_group = {
. attrs = bt_link_attrs ,
} ;
2009-06-24 21:06:31 +04:00
static const struct attribute_group * bt_link_groups [ ] = {
2008-08-18 15:23:53 +04:00
& bt_link_group ,
NULL
} ;
static void bt_link_release ( struct device * dev )
{
2012-02-10 00:58:34 +04:00
struct hci_conn * conn = to_hci_conn ( dev ) ;
kfree ( conn ) ;
2008-08-18 15:23:53 +04:00
}
static struct device_type bt_link = {
. name = " link " ,
. groups = bt_link_groups ,
. release = bt_link_release ,
} ;
2011-12-18 00:53:02 +04:00
/*
* The rfcomm tty device will possibly retain even when conn
* is down , and sysfs doesn ' t support move zombie device ,
* so we should move the device before conn device is destroyed .
*/
static int __match_tty ( struct device * dev , void * data )
{
return ! strncmp ( dev_name ( dev ) , " rfcomm " , 6 ) ;
}
void hci_conn_init_sysfs ( struct hci_conn * conn )
{
struct hci_dev * hdev = conn - > hdev ;
BT_DBG ( " conn %p " , conn ) ;
conn - > dev . type = & bt_link ;
conn - > dev . class = bt_class ;
conn - > dev . parent = & hdev - > dev ;
device_initialize ( & conn - > dev ) ;
}
void hci_conn_add_sysfs ( struct hci_conn * conn )
2008-08-18 15:23:53 +04:00
{
2009-05-06 00:09:01 +04:00
struct hci_dev * hdev = conn - > hdev ;
2008-08-18 15:23:53 +04:00
2011-12-18 00:53:02 +04:00
BT_DBG ( " conn %p " , conn ) ;
2009-05-06 00:09:01 +04:00
dev_set_name ( & conn - > dev , " %s:%d " , hdev - > name , conn - > handle ) ;
2008-08-18 15:23:53 +04:00
if ( device_add ( & conn - > dev ) < 0 ) {
BT_ERR ( " Failed to register connection device " ) ;
return ;
}
2009-05-09 05:20:43 +04:00
hci_dev_hold ( hdev ) ;
2008-08-18 15:23:53 +04:00
}
2011-12-18 00:53:02 +04:00
void hci_conn_del_sysfs ( struct hci_conn * conn )
2008-08-18 15:23:53 +04:00
{
struct hci_dev * hdev = conn - > hdev ;
2009-05-03 05:24:06 +04:00
if ( ! device_is_registered ( & conn - > dev ) )
return ;
2009-04-23 15:50:54 +04:00
2008-08-18 15:23:53 +04:00
while ( 1 ) {
struct device * dev ;
dev = device_find_child ( & conn - > dev , NULL , __match_tty ) ;
if ( ! dev )
break ;
2009-03-04 14:44:00 +03:00
device_move ( dev , NULL , DPM_ORDER_DEV_LAST ) ;
2008-08-18 15:23:53 +04:00
put_device ( dev ) ;
}
device_del ( & conn - > dev ) ;
put_device ( & conn - > dev ) ;
2009-05-09 05:20:43 +04:00
2008-08-18 15:23:53 +04:00
hci_dev_put ( hdev ) ;
}
2010-02-08 17:27:07 +03:00
static inline char * host_bustostr ( int bus )
2005-04-17 02:20:36 +04:00
{
2010-02-08 17:27:07 +03:00
switch ( bus ) {
2006-07-08 15:57:15 +04:00
case HCI_VIRTUAL :
2006-07-06 14:34:41 +04:00
return " VIRTUAL " ;
case HCI_USB :
return " USB " ;
case HCI_PCCARD :
return " PCCARD " ;
case HCI_UART :
return " UART " ;
case HCI_RS232 :
return " RS232 " ;
case HCI_PCI :
return " PCI " ;
2006-07-08 15:57:15 +04:00
case HCI_SDIO :
return " SDIO " ;
2006-07-06 14:34:41 +04:00
default :
return " UNKNOWN " ;
}
2005-04-17 02:20:36 +04:00
}
2010-02-13 04:28:41 +03:00
static inline char * host_typetostr ( int type )
{
switch ( type ) {
case HCI_BREDR :
return " BR/EDR " ;
2010-08-10 01:38:10 +04:00
case HCI_AMP :
return " AMP " ;
2010-02-13 04:28:41 +03:00
default :
return " UNKNOWN " ;
}
}
2012-05-17 07:36:23 +04:00
static ssize_t show_bus ( struct device * dev ,
struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2010-02-08 17:27:07 +03:00
return sprintf ( buf , " %s \n " , host_bustostr ( hdev - > bus ) ) ;
2005-04-17 02:20:36 +04:00
}
2012-05-17 07:36:23 +04:00
static ssize_t show_type ( struct device * dev ,
struct device_attribute * attr , char * buf )
2010-02-13 04:28:41 +03:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2010-02-13 04:28:41 +03:00
return sprintf ( buf , " %s \n " , host_typetostr ( hdev - > dev_type ) ) ;
}
2012-05-17 07:36:23 +04:00
static ssize_t show_name ( struct device * dev ,
struct device_attribute * attr , char * buf )
2007-10-20 15:33:56 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2011-03-16 15:29:35 +03:00
char name [ HCI_MAX_NAME_LENGTH + 1 ] ;
2007-10-20 15:33:56 +04:00
int i ;
2011-03-16 15:29:35 +03:00
for ( i = 0 ; i < HCI_MAX_NAME_LENGTH ; i + + )
2007-10-20 15:33:56 +04:00
name [ i ] = hdev - > dev_name [ i ] ;
2011-03-16 15:29:35 +03:00
name [ HCI_MAX_NAME_LENGTH ] = ' \0 ' ;
2007-10-20 15:33:56 +04:00
return sprintf ( buf , " %s \n " , name ) ;
}
2012-05-17 07:36:23 +04:00
static ssize_t show_class ( struct device * dev ,
struct device_attribute * attr , char * buf )
2007-10-20 15:33:56 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2012-05-23 11:04:21 +04:00
return sprintf ( buf , " 0x%.2x%.2x%.2x \n " , hdev - > dev_class [ 2 ] ,
hdev - > dev_class [ 1 ] , hdev - > dev_class [ 0 ] ) ;
2007-10-20 15:33:56 +04:00
}
2012-05-17 07:36:23 +04:00
static ssize_t show_address ( struct device * dev ,
struct device_attribute * attr , char * buf )
2005-04-17 02:20:36 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2012-09-25 13:49:44 +04:00
return sprintf ( buf , " %pMR \n " , & hdev - > bdaddr ) ;
2005-04-17 02:20:36 +04:00
}
2012-05-17 07:36:23 +04:00
static ssize_t show_features ( struct device * dev ,
struct device_attribute * attr , char * buf )
2007-10-20 15:33:56 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2007-10-20 15:33:56 +04:00
return sprintf ( buf , " 0x%02x%02x%02x%02x%02x%02x%02x%02x \n " ,
2012-05-17 07:36:23 +04:00
hdev - > features [ 0 ] , hdev - > features [ 1 ] ,
hdev - > features [ 2 ] , hdev - > features [ 3 ] ,
hdev - > features [ 4 ] , hdev - > features [ 5 ] ,
hdev - > features [ 6 ] , hdev - > features [ 7 ] ) ;
2007-10-20 15:33:56 +04:00
}
2012-05-17 07:36:23 +04:00
static ssize_t show_manufacturer ( struct device * dev ,
struct device_attribute * attr , char * buf )
2006-09-23 11:57:20 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2006-09-23 11:57:20 +04:00
return sprintf ( buf , " %d \n " , hdev - > manufacturer ) ;
}
2012-05-17 07:36:23 +04:00
static ssize_t show_hci_version ( struct device * dev ,
struct device_attribute * attr , char * buf )
2006-09-23 11:57:20 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2006-09-23 11:57:20 +04:00
return sprintf ( buf , " %d \n " , hdev - > hci_ver ) ;
}
2012-05-17 07:36:23 +04:00
static ssize_t show_hci_revision ( struct device * dev ,
struct device_attribute * attr , char * buf )
2006-09-23 11:57:20 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2006-09-23 11:57:20 +04:00
return sprintf ( buf , " %d \n " , hdev - > hci_rev ) ;
}
2012-05-17 07:36:23 +04:00
static ssize_t show_idle_timeout ( struct device * dev ,
struct device_attribute * attr , char * buf )
2006-07-03 12:02:33 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2006-07-03 12:02:33 +04:00
return sprintf ( buf , " %d \n " , hdev - > idle_timeout ) ;
}
2012-05-17 07:36:23 +04:00
static ssize_t store_idle_timeout ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
2006-07-03 12:02:33 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2011-04-02 15:19:41 +04:00
unsigned int val ;
int rv ;
2006-07-03 12:02:33 +04:00
2011-04-02 15:19:41 +04:00
rv = kstrtouint ( buf , 0 , & val ) ;
if ( rv < 0 )
return rv ;
2006-07-03 12:02:33 +04:00
if ( val ! = 0 & & ( val < 500 | | val > 3600000 ) )
return - EINVAL ;
hdev - > idle_timeout = val ;
return count ;
}
2012-05-17 07:36:23 +04:00
static ssize_t show_sniff_max_interval ( struct device * dev ,
struct device_attribute * attr , char * buf )
2006-07-03 12:02:33 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2006-07-03 12:02:33 +04:00
return sprintf ( buf , " %d \n " , hdev - > sniff_max_interval ) ;
}
2012-05-17 07:36:23 +04:00
static ssize_t store_sniff_max_interval ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
2006-07-03 12:02:33 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2011-04-02 15:19:41 +04:00
u16 val ;
int rv ;
2006-07-03 12:02:33 +04:00
2011-04-02 15:19:41 +04:00
rv = kstrtou16 ( buf , 0 , & val ) ;
if ( rv < 0 )
return rv ;
2006-07-03 12:02:33 +04:00
2011-04-02 15:19:41 +04:00
if ( val = = 0 | | val % 2 | | val < hdev - > sniff_min_interval )
2006-07-03 12:02:33 +04:00
return - EINVAL ;
hdev - > sniff_max_interval = val ;
return count ;
}
2012-05-17 07:36:23 +04:00
static ssize_t show_sniff_min_interval ( struct device * dev ,
struct device_attribute * attr , char * buf )
2006-07-03 12:02:33 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2006-07-03 12:02:33 +04:00
return sprintf ( buf , " %d \n " , hdev - > sniff_min_interval ) ;
}
2012-05-17 07:36:23 +04:00
static ssize_t store_sniff_min_interval ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
2006-07-03 12:02:33 +04:00
{
2012-02-10 00:58:30 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
2011-04-02 15:19:41 +04:00
u16 val ;
int rv ;
2006-07-03 12:02:33 +04:00
2011-04-02 15:19:41 +04:00
rv = kstrtou16 ( buf , 0 , & val ) ;
if ( rv < 0 )
return rv ;
2006-07-03 12:02:33 +04:00
2011-04-02 15:19:41 +04:00
if ( val = = 0 | | val % 2 | | val > hdev - > sniff_max_interval )
2006-07-03 12:02:33 +04:00
return - EINVAL ;
hdev - > sniff_min_interval = val ;
return count ;
}
2010-02-08 17:27:07 +03:00
static DEVICE_ATTR ( bus , S_IRUGO , show_bus , NULL ) ;
2010-02-13 04:28:41 +03:00
static DEVICE_ATTR ( type , S_IRUGO , show_type , NULL ) ;
2007-10-20 15:33:56 +04:00
static DEVICE_ATTR ( name , S_IRUGO , show_name , NULL ) ;
static DEVICE_ATTR ( class , S_IRUGO , show_class , NULL ) ;
2006-07-03 12:02:41 +04:00
static DEVICE_ATTR ( address , S_IRUGO , show_address , NULL ) ;
2007-10-20 15:33:56 +04:00
static DEVICE_ATTR ( features , S_IRUGO , show_features , NULL ) ;
2006-09-23 11:57:20 +04:00
static DEVICE_ATTR ( manufacturer , S_IRUGO , show_manufacturer , NULL ) ;
static DEVICE_ATTR ( hci_version , S_IRUGO , show_hci_version , NULL ) ;
static DEVICE_ATTR ( hci_revision , S_IRUGO , show_hci_revision , NULL ) ;
2005-04-17 02:20:36 +04:00
2006-07-03 12:02:41 +04:00
static DEVICE_ATTR ( idle_timeout , S_IRUGO | S_IWUSR ,
2012-05-17 07:36:23 +04:00
show_idle_timeout , store_idle_timeout ) ;
2006-07-03 12:02:41 +04:00
static DEVICE_ATTR ( sniff_max_interval , S_IRUGO | S_IWUSR ,
2012-05-17 07:36:23 +04:00
show_sniff_max_interval , store_sniff_max_interval ) ;
2006-07-03 12:02:41 +04:00
static DEVICE_ATTR ( sniff_min_interval , S_IRUGO | S_IWUSR ,
2012-05-17 07:36:23 +04:00
show_sniff_min_interval , store_sniff_min_interval ) ;
2006-07-03 12:02:33 +04:00
2008-08-18 15:23:53 +04:00
static struct attribute * bt_host_attrs [ ] = {
2010-02-08 17:27:07 +03:00
& dev_attr_bus . attr ,
2010-02-13 04:28:41 +03:00
& dev_attr_type . attr ,
2008-08-18 15:23:53 +04:00
& dev_attr_name . attr ,
& dev_attr_class . attr ,
& dev_attr_address . attr ,
& dev_attr_features . attr ,
& dev_attr_manufacturer . attr ,
& dev_attr_hci_version . attr ,
& dev_attr_hci_revision . attr ,
& dev_attr_idle_timeout . attr ,
& dev_attr_sniff_max_interval . attr ,
& dev_attr_sniff_min_interval . attr ,
2005-04-17 02:20:36 +04:00
NULL
} ;
2008-08-18 15:23:53 +04:00
static struct attribute_group bt_host_group = {
. attrs = bt_host_attrs ,
2006-07-06 14:38:46 +04:00
} ;
2009-06-24 21:06:31 +04:00
static const struct attribute_group * bt_host_groups [ ] = {
2008-08-18 15:23:53 +04:00
& bt_host_group ,
NULL
2006-07-03 12:02:37 +04:00
} ;
2008-08-18 15:23:53 +04:00
static void bt_host_release ( struct device * dev )
2006-07-03 12:02:41 +04:00
{
2012-02-10 00:58:34 +04:00
struct hci_dev * hdev = to_hci_dev ( dev ) ;
kfree ( hdev ) ;
2012-01-07 18:47:21 +04:00
module_put ( THIS_MODULE ) ;
2006-07-06 14:38:46 +04:00
}
2008-08-18 15:23:53 +04:00
static struct device_type bt_host = {
. name = " host " ,
. groups = bt_host_groups ,
. release = bt_host_release ,
} ;
2006-07-03 12:02:41 +04:00
2010-03-02 18:48:23 +03:00
static int inquiry_cache_show ( struct seq_file * f , void * p )
2010-02-08 18:22:31 +03:00
{
2010-03-02 18:48:23 +03:00
struct hci_dev * hdev = f - > private ;
2012-01-04 16:16:21 +04:00
struct discovery_state * cache = & hdev - > discovery ;
2010-02-08 18:22:31 +03:00
struct inquiry_entry * e ;
2011-06-17 20:03:21 +04:00
hci_dev_lock ( hdev ) ;
2010-02-08 18:22:31 +03:00
2012-01-04 15:31:59 +04:00
list_for_each_entry ( e , & cache - > all , all ) {
2010-02-08 18:22:31 +03:00
struct inquiry_data * data = & e - > data ;
2012-09-25 13:49:44 +04:00
seq_printf ( f , " %pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u \n " ,
& data - > bdaddr ,
2010-03-02 18:48:23 +03:00
data - > pscan_rep_mode , data - > pscan_period_mode ,
data - > pscan_mode , data - > dev_class [ 2 ] ,
data - > dev_class [ 1 ] , data - > dev_class [ 0 ] ,
__le16_to_cpu ( data - > clock_offset ) ,
data - > rssi , data - > ssp_mode , e - > timestamp ) ;
2010-02-08 18:22:31 +03:00
}
2011-06-17 20:03:21 +04:00
hci_dev_unlock ( hdev ) ;
2010-02-08 18:22:31 +03:00
2010-03-02 18:48:23 +03:00
return 0 ;
}
static int inquiry_cache_open ( struct inode * inode , struct file * file )
{
return single_open ( file , inquiry_cache_show , inode - > i_private ) ;
2010-02-08 18:22:31 +03:00
}
static const struct file_operations inquiry_cache_fops = {
2010-03-02 18:48:23 +03:00
. open = inquiry_cache_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
2010-02-08 18:22:31 +03:00
} ;
2010-05-18 15:54:49 +04:00
static int blacklist_show ( struct seq_file * f , void * p )
{
struct hci_dev * hdev = f - > private ;
2011-11-01 12:58:56 +04:00
struct bdaddr_list * b ;
2010-05-18 15:54:49 +04:00
2011-06-17 20:03:21 +04:00
hci_dev_lock ( hdev ) ;
2010-05-18 15:54:49 +04:00
2011-11-01 12:58:56 +04:00
list_for_each_entry ( b , & hdev - > blacklist , list )
2012-09-25 13:49:44 +04:00
seq_printf ( f , " %pMR \n " , & b - > bdaddr ) ;
2010-05-18 15:54:49 +04:00
2011-06-17 20:03:21 +04:00
hci_dev_unlock ( hdev ) ;
2010-05-18 15:54:49 +04:00
return 0 ;
}
static int blacklist_open ( struct inode * inode , struct file * file )
{
return single_open ( file , blacklist_show , inode - > i_private ) ;
}
static const struct file_operations blacklist_fops = {
. open = blacklist_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
2011-01-04 12:39:44 +03:00
static void print_bt_uuid ( struct seq_file * f , u8 * uuid )
{
2012-03-12 17:59:31 +04:00
__be32 data0 , data4 ;
__be16 data1 , data2 , data3 , data5 ;
2011-01-04 12:39:44 +03:00
memcpy ( & data0 , & uuid [ 0 ] , 4 ) ;
memcpy ( & data1 , & uuid [ 4 ] , 2 ) ;
memcpy ( & data2 , & uuid [ 6 ] , 2 ) ;
memcpy ( & data3 , & uuid [ 8 ] , 2 ) ;
memcpy ( & data4 , & uuid [ 10 ] , 4 ) ;
memcpy ( & data5 , & uuid [ 14 ] , 2 ) ;
seq_printf ( f , " %.8x-%.4x-%.4x-%.4x-%.8x%.4x \n " ,
2012-05-17 07:36:23 +04:00
ntohl ( data0 ) , ntohs ( data1 ) , ntohs ( data2 ) , ntohs ( data3 ) ,
ntohl ( data4 ) , ntohs ( data5 ) ) ;
2011-01-04 12:39:44 +03:00
}
static int uuids_show ( struct seq_file * f , void * p )
{
struct hci_dev * hdev = f - > private ;
2011-11-01 12:58:56 +04:00
struct bt_uuid * uuid ;
2011-01-04 12:39:44 +03:00
2011-06-17 20:03:21 +04:00
hci_dev_lock ( hdev ) ;
2011-01-04 12:39:44 +03:00
2011-11-01 12:58:56 +04:00
list_for_each_entry ( uuid , & hdev - > uuids , list )
2011-01-04 12:39:44 +03:00
print_bt_uuid ( f , uuid - > uuid ) ;
2011-06-17 20:03:21 +04:00
hci_dev_unlock ( hdev ) ;
2011-01-04 12:39:44 +03:00
return 0 ;
}
static int uuids_open ( struct inode * inode , struct file * file )
{
return single_open ( file , uuids_show , inode - > i_private ) ;
}
static const struct file_operations uuids_fops = {
. open = uuids_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
2011-04-28 22:28:54 +04:00
static int auto_accept_delay_set ( void * data , u64 val )
{
struct hci_dev * hdev = data ;
2011-06-17 20:03:21 +04:00
hci_dev_lock ( hdev ) ;
2011-04-28 22:28:54 +04:00
hdev - > auto_accept_delay = val ;
2011-06-17 20:03:21 +04:00
hci_dev_unlock ( hdev ) ;
2011-04-28 22:28:54 +04:00
return 0 ;
}
static int auto_accept_delay_get ( void * data , u64 * val )
{
struct hci_dev * hdev = data ;
2011-06-17 20:03:21 +04:00
hci_dev_lock ( hdev ) ;
2011-04-28 22:28:54 +04:00
* val = hdev - > auto_accept_delay ;
2011-06-17 20:03:21 +04:00
hci_dev_unlock ( hdev ) ;
2011-04-28 22:28:54 +04:00
return 0 ;
}
DEFINE_SIMPLE_ATTRIBUTE ( auto_accept_delay_fops , auto_accept_delay_get ,
2012-05-17 07:36:23 +04:00
auto_accept_delay_set , " %llu \n " ) ;
2011-04-28 22:28:54 +04:00
2011-10-08 16:58:47 +04:00
void hci_init_sysfs ( struct hci_dev * hdev )
{
struct device * dev = & hdev - > dev ;
dev - > type = & bt_host ;
dev - > class = bt_class ;
2012-01-07 18:47:21 +04:00
__module_get ( THIS_MODULE ) ;
2011-10-08 16:58:47 +04:00
device_initialize ( dev ) ;
}
2011-10-08 16:58:48 +04:00
int hci_add_sysfs ( struct hci_dev * hdev )
2005-04-17 02:20:36 +04:00
{
2006-07-03 12:02:41 +04:00
struct device * dev = & hdev - > dev ;
2005-04-17 02:20:36 +04:00
int err ;
2010-02-08 17:27:07 +03:00
BT_DBG ( " %p name %s bus %d " , hdev , hdev - > name , hdev - > bus ) ;
2005-04-17 02:20:36 +04:00
2008-11-30 14:17:29 +03:00
dev_set_name ( dev , " %s " , hdev - > name ) ;
2005-04-17 02:20:36 +04:00
2011-10-08 16:58:47 +04:00
err = device_add ( dev ) ;
2005-04-17 02:20:36 +04:00
if ( err < 0 )
return err ;
2010-02-08 18:22:31 +03:00
if ( ! bt_debugfs )
return 0 ;
hdev - > debugfs = debugfs_create_dir ( hdev - > name , bt_debugfs ) ;
if ( ! hdev - > debugfs )
return 0 ;
debugfs_create_file ( " inquiry_cache " , 0444 , hdev - > debugfs ,
2012-05-17 07:36:23 +04:00
hdev , & inquiry_cache_fops ) ;
2010-02-08 18:22:31 +03:00
2010-05-18 15:54:49 +04:00
debugfs_create_file ( " blacklist " , 0444 , hdev - > debugfs ,
2012-05-17 07:36:23 +04:00
hdev , & blacklist_fops ) ;
2010-05-18 15:54:49 +04:00
2011-01-04 12:39:44 +03:00
debugfs_create_file ( " uuids " , 0444 , hdev - > debugfs , hdev , & uuids_fops ) ;
2011-04-28 22:28:54 +04:00
debugfs_create_file ( " auto_accept_delay " , 0444 , hdev - > debugfs , hdev ,
2012-05-17 07:36:23 +04:00
& auto_accept_delay_fops ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2011-10-08 16:58:48 +04:00
void hci_del_sysfs ( struct hci_dev * hdev )
2005-04-17 02:20:36 +04:00
{
2010-02-08 17:27:07 +03:00
BT_DBG ( " %p name %s bus %d " , hdev , hdev - > name , hdev - > bus ) ;
2005-04-17 02:20:36 +04:00
2010-02-08 18:22:31 +03:00
debugfs_remove_recursive ( hdev - > debugfs ) ;
2006-07-06 14:34:41 +04:00
device_del ( & hdev - > dev ) ;
2005-04-17 02:20:36 +04:00
}
int __init bt_sysfs_init ( void )
{
2010-02-08 18:22:31 +03:00
bt_debugfs = debugfs_create_dir ( " bluetooth " , NULL ) ;
2006-07-03 12:02:41 +04:00
bt_class = class_create ( THIS_MODULE , " bluetooth " ) ;
2010-03-20 17:20:04 +03:00
if ( IS_ERR ( bt_class ) )
2008-08-18 15:23:53 +04:00
return PTR_ERR ( bt_class ) ;
2006-07-03 12:02:37 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2006-09-29 02:29:37 +04:00
void bt_sysfs_cleanup ( void )
2005-04-17 02:20:36 +04:00
{
2006-07-03 12:02:41 +04:00
class_destroy ( bt_class ) ;
2010-02-08 18:22:31 +03:00
debugfs_remove_recursive ( bt_debugfs ) ;
2005-04-17 02:20:36 +04:00
}