hci_sysfs.c revision 4d0eb0049ce94101f7f169f89216ba58475219e2
1/* Bluetooth HCI driver model support. */ 2 3#include <linux/kernel.h> 4#include <linux/init.h> 5 6#include <linux/platform_device.h> 7 8#include <net/bluetooth/bluetooth.h> 9#include <net/bluetooth/hci_core.h> 10 11#ifndef CONFIG_BT_HCI_CORE_DEBUG 12#undef BT_DBG 13#define BT_DBG(D...) 14#endif 15 16static inline char *typetostr(int type) 17{ 18 switch (type) { 19 case HCI_VHCI: 20 return "VIRTUAL"; 21 case HCI_USB: 22 return "USB"; 23 case HCI_PCCARD: 24 return "PCCARD"; 25 case HCI_UART: 26 return "UART"; 27 case HCI_RS232: 28 return "RS232"; 29 case HCI_PCI: 30 return "PCI"; 31 default: 32 return "UNKNOWN"; 33 } 34} 35 36static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) 37{ 38 struct hci_dev *hdev = dev_get_drvdata(dev); 39 return sprintf(buf, "%s\n", typetostr(hdev->type)); 40} 41 42static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf) 43{ 44 struct hci_dev *hdev = dev_get_drvdata(dev); 45 bdaddr_t bdaddr; 46 baswap(&bdaddr, &hdev->bdaddr); 47 return sprintf(buf, "%s\n", batostr(&bdaddr)); 48} 49 50static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf) 51{ 52 struct hci_dev *hdev = dev_get_drvdata(dev); 53 struct inquiry_cache *cache = &hdev->inq_cache; 54 struct inquiry_entry *e; 55 int n = 0; 56 57 hci_dev_lock_bh(hdev); 58 59 for (e = cache->list; e; e = e->next) { 60 struct inquiry_data *data = &e->data; 61 bdaddr_t bdaddr; 62 baswap(&bdaddr, &data->bdaddr); 63 n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %u\n", 64 batostr(&bdaddr), 65 data->pscan_rep_mode, data->pscan_period_mode, data->pscan_mode, 66 data->dev_class[2], data->dev_class[1], data->dev_class[0], 67 __le16_to_cpu(data->clock_offset), data->rssi, e->timestamp); 68 } 69 70 hci_dev_unlock_bh(hdev); 71 return n; 72} 73 74static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *attr, char *buf) 75{ 76 struct hci_dev *hdev = dev_get_drvdata(dev); 77 return sprintf(buf, "%d\n", hdev->idle_timeout); 78} 79 80static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 81{ 82 struct hci_dev *hdev = dev_get_drvdata(dev); 83 char *ptr; 84 __u32 val; 85 86 val = simple_strtoul(buf, &ptr, 10); 87 if (ptr == buf) 88 return -EINVAL; 89 90 if (val != 0 && (val < 500 || val > 3600000)) 91 return -EINVAL; 92 93 hdev->idle_timeout = val; 94 95 return count; 96} 97 98static ssize_t show_sniff_max_interval(struct device *dev, struct device_attribute *attr, char *buf) 99{ 100 struct hci_dev *hdev = dev_get_drvdata(dev); 101 return sprintf(buf, "%d\n", hdev->sniff_max_interval); 102} 103 104static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 105{ 106 struct hci_dev *hdev = dev_get_drvdata(dev); 107 char *ptr; 108 __u16 val; 109 110 val = simple_strtoul(buf, &ptr, 10); 111 if (ptr == buf) 112 return -EINVAL; 113 114 if (val < 0x0002 || val > 0xFFFE || val % 2) 115 return -EINVAL; 116 117 if (val < hdev->sniff_min_interval) 118 return -EINVAL; 119 120 hdev->sniff_max_interval = val; 121 122 return count; 123} 124 125static ssize_t show_sniff_min_interval(struct device *dev, struct device_attribute *attr, char *buf) 126{ 127 struct hci_dev *hdev = dev_get_drvdata(dev); 128 return sprintf(buf, "%d\n", hdev->sniff_min_interval); 129} 130 131static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 132{ 133 struct hci_dev *hdev = dev_get_drvdata(dev); 134 char *ptr; 135 __u16 val; 136 137 val = simple_strtoul(buf, &ptr, 10); 138 if (ptr == buf) 139 return -EINVAL; 140 141 if (val < 0x0002 || val > 0xFFFE || val % 2) 142 return -EINVAL; 143 144 if (val > hdev->sniff_max_interval) 145 return -EINVAL; 146 147 hdev->sniff_min_interval = val; 148 149 return count; 150} 151 152static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); 153static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); 154static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL); 155 156static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR, 157 show_idle_timeout, store_idle_timeout); 158static DEVICE_ATTR(sniff_max_interval, S_IRUGO | S_IWUSR, 159 show_sniff_max_interval, store_sniff_max_interval); 160static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, 161 show_sniff_min_interval, store_sniff_min_interval); 162 163static struct device_attribute *bt_attrs[] = { 164 &dev_attr_type, 165 &dev_attr_address, 166 &dev_attr_inquiry_cache, 167 &dev_attr_idle_timeout, 168 &dev_attr_sniff_max_interval, 169 &dev_attr_sniff_min_interval, 170 NULL 171}; 172 173struct class *bt_class = NULL; 174EXPORT_SYMBOL_GPL(bt_class); 175 176static struct bus_type bt_bus = { 177 .name = "bluetooth", 178}; 179 180static struct platform_device *bt_platform; 181 182static void bt_release(struct device *dev) 183{ 184 struct hci_dev *hdev = dev_get_drvdata(dev); 185 kfree(hdev); 186} 187 188int hci_register_sysfs(struct hci_dev *hdev) 189{ 190 struct device *dev = &hdev->dev; 191 unsigned int i; 192 int err; 193 194 BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); 195 196 dev->class = bt_class; 197 198 if (hdev->parent) 199 dev->parent = hdev->parent; 200 else 201 dev->parent = &bt_platform->dev; 202 203 strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE); 204 205 dev->release = bt_release; 206 207 dev_set_drvdata(dev, hdev); 208 209 err = device_register(dev); 210 if (err < 0) 211 return err; 212 213 for (i = 0; bt_attrs[i]; i++) 214 device_create_file(dev, bt_attrs[i]); 215 216 return 0; 217} 218 219void hci_unregister_sysfs(struct hci_dev *hdev) 220{ 221 BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); 222 223 device_del(&hdev->dev); 224} 225 226int __init bt_sysfs_init(void) 227{ 228 int err; 229 230 bt_platform = platform_device_register_simple("bluetooth", -1, NULL, 0); 231 if (IS_ERR(bt_platform)) 232 return PTR_ERR(bt_platform); 233 234 err = bus_register(&bt_bus); 235 if (err < 0) { 236 platform_device_unregister(bt_platform); 237 return err; 238 } 239 240 bt_class = class_create(THIS_MODULE, "bluetooth"); 241 if (IS_ERR(bt_class)) { 242 bus_unregister(&bt_bus); 243 platform_device_unregister(bt_platform); 244 return PTR_ERR(bt_class); 245 } 246 247 return 0; 248} 249 250void __exit bt_sysfs_cleanup(void) 251{ 252 class_destroy(bt_class); 253 254 bus_unregister(&bt_bus); 255 256 platform_device_unregister(bt_platform); 257} 258