hci_sysfs.c revision 04837f6447c7f3ef114cda1ad761822dedbff8cf
1/* Bluetooth HCI driver model support. */ 2 3#include <linux/kernel.h> 4#include <linux/init.h> 5 6#include <net/bluetooth/bluetooth.h> 7#include <net/bluetooth/hci_core.h> 8 9#ifndef CONFIG_BT_HCI_CORE_DEBUG 10#undef BT_DBG 11#define BT_DBG(D...) 12#endif 13 14static ssize_t show_name(struct class_device *cdev, char *buf) 15{ 16 struct hci_dev *hdev = class_get_devdata(cdev); 17 return sprintf(buf, "%s\n", hdev->name); 18} 19 20static ssize_t show_type(struct class_device *cdev, char *buf) 21{ 22 struct hci_dev *hdev = class_get_devdata(cdev); 23 return sprintf(buf, "%d\n", hdev->type); 24} 25 26static ssize_t show_address(struct class_device *cdev, char *buf) 27{ 28 struct hci_dev *hdev = class_get_devdata(cdev); 29 bdaddr_t bdaddr; 30 baswap(&bdaddr, &hdev->bdaddr); 31 return sprintf(buf, "%s\n", batostr(&bdaddr)); 32} 33 34static ssize_t show_flags(struct class_device *cdev, char *buf) 35{ 36 struct hci_dev *hdev = class_get_devdata(cdev); 37 return sprintf(buf, "0x%lx\n", hdev->flags); 38} 39 40static ssize_t show_inquiry_cache(struct class_device *cdev, char *buf) 41{ 42 struct hci_dev *hdev = class_get_devdata(cdev); 43 struct inquiry_cache *cache = &hdev->inq_cache; 44 struct inquiry_entry *e; 45 int n = 0; 46 47 hci_dev_lock_bh(hdev); 48 49 for (e = cache->list; e; e = e->next) { 50 struct inquiry_data *data = &e->data; 51 bdaddr_t bdaddr; 52 baswap(&bdaddr, &data->bdaddr); 53 n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %u\n", 54 batostr(&bdaddr), 55 data->pscan_rep_mode, data->pscan_period_mode, data->pscan_mode, 56 data->dev_class[2], data->dev_class[1], data->dev_class[0], 57 __le16_to_cpu(data->clock_offset), data->rssi, e->timestamp); 58 } 59 60 hci_dev_unlock_bh(hdev); 61 return n; 62} 63 64static ssize_t show_idle_timeout(struct class_device *cdev, char *buf) 65{ 66 struct hci_dev *hdev = class_get_devdata(cdev); 67 return sprintf(buf, "%d\n", hdev->idle_timeout); 68} 69 70static ssize_t store_idle_timeout(struct class_device *cdev, const char *buf, size_t count) 71{ 72 struct hci_dev *hdev = class_get_devdata(cdev); 73 char *ptr; 74 __u32 val; 75 76 val = simple_strtoul(buf, &ptr, 10); 77 if (ptr == buf) 78 return -EINVAL; 79 80 if (val != 0 && (val < 500 || val > 3600000)) 81 return -EINVAL; 82 83 hdev->idle_timeout = val; 84 85 return count; 86} 87 88static ssize_t show_sniff_max_interval(struct class_device *cdev, char *buf) 89{ 90 struct hci_dev *hdev = class_get_devdata(cdev); 91 return sprintf(buf, "%d\n", hdev->sniff_max_interval); 92} 93 94static ssize_t store_sniff_max_interval(struct class_device *cdev, const char *buf, size_t count) 95{ 96 struct hci_dev *hdev = class_get_devdata(cdev); 97 char *ptr; 98 __u16 val; 99 100 val = simple_strtoul(buf, &ptr, 10); 101 if (ptr == buf) 102 return -EINVAL; 103 104 if (val < 0x0002 || val > 0xFFFE || val % 2) 105 return -EINVAL; 106 107 if (val < hdev->sniff_min_interval) 108 return -EINVAL; 109 110 hdev->sniff_max_interval = val; 111 112 return count; 113} 114 115static ssize_t show_sniff_min_interval(struct class_device *cdev, char *buf) 116{ 117 struct hci_dev *hdev = class_get_devdata(cdev); 118 return sprintf(buf, "%d\n", hdev->sniff_min_interval); 119} 120 121static ssize_t store_sniff_min_interval(struct class_device *cdev, const char *buf, size_t count) 122{ 123 struct hci_dev *hdev = class_get_devdata(cdev); 124 char *ptr; 125 __u16 val; 126 127 val = simple_strtoul(buf, &ptr, 10); 128 if (ptr == buf) 129 return -EINVAL; 130 131 if (val < 0x0002 || val > 0xFFFE || val % 2) 132 return -EINVAL; 133 134 if (val > hdev->sniff_max_interval) 135 return -EINVAL; 136 137 hdev->sniff_min_interval = val; 138 139 return count; 140} 141 142static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL); 143static CLASS_DEVICE_ATTR(type, S_IRUGO, show_type, NULL); 144static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL); 145static CLASS_DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL); 146static CLASS_DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL); 147 148static CLASS_DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR, 149 show_idle_timeout, store_idle_timeout); 150static CLASS_DEVICE_ATTR(sniff_max_interval, S_IRUGO | S_IWUSR, 151 show_sniff_max_interval, store_sniff_max_interval); 152static CLASS_DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, 153 show_sniff_min_interval, store_sniff_min_interval); 154 155static struct class_device_attribute *bt_attrs[] = { 156 &class_device_attr_name, 157 &class_device_attr_type, 158 &class_device_attr_address, 159 &class_device_attr_flags, 160 &class_device_attr_inquiry_cache, 161 &class_device_attr_idle_timeout, 162 &class_device_attr_sniff_max_interval, 163 &class_device_attr_sniff_min_interval, 164 NULL 165}; 166 167#ifdef CONFIG_HOTPLUG 168static int bt_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size) 169{ 170 struct hci_dev *hdev = class_get_devdata(cdev); 171 int n, i = 0; 172 173 envp[i++] = buf; 174 n = snprintf(buf, size, "INTERFACE=%s", hdev->name) + 1; 175 buf += n; 176 size -= n; 177 178 if ((size <= 0) || (i >= num_envp)) 179 return -ENOMEM; 180 181 envp[i] = NULL; 182 return 0; 183} 184#endif 185 186static void bt_release(struct class_device *cdev) 187{ 188 struct hci_dev *hdev = class_get_devdata(cdev); 189 190 kfree(hdev); 191} 192 193struct class bt_class = { 194 .name = "bluetooth", 195 .release = bt_release, 196#ifdef CONFIG_HOTPLUG 197 .uevent = bt_uevent, 198#endif 199}; 200 201EXPORT_SYMBOL_GPL(bt_class); 202 203int hci_register_sysfs(struct hci_dev *hdev) 204{ 205 struct class_device *cdev = &hdev->class_dev; 206 unsigned int i; 207 int err; 208 209 BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); 210 211 cdev->class = &bt_class; 212 class_set_devdata(cdev, hdev); 213 214 strlcpy(cdev->class_id, hdev->name, BUS_ID_SIZE); 215 err = class_device_register(cdev); 216 if (err < 0) 217 return err; 218 219 for (i = 0; bt_attrs[i]; i++) 220 class_device_create_file(cdev, bt_attrs[i]); 221 222 return 0; 223} 224 225void hci_unregister_sysfs(struct hci_dev *hdev) 226{ 227 struct class_device * cdev = &hdev->class_dev; 228 229 BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); 230 231 class_device_del(cdev); 232} 233 234int __init bt_sysfs_init(void) 235{ 236 return class_register(&bt_class); 237} 238 239void __exit bt_sysfs_cleanup(void) 240{ 241 class_unregister(&bt_class); 242} 243