Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'hidraw' into for-linus

+565 -2
+19
drivers/hid/Kconfig
··· 46 46 47 47 If unsure, say N 48 48 49 + config HIDRAW 50 + bool "/dev/hidraw raw HID device support" 51 + depends on HID 52 + ---help--- 53 + Say Y here if you want to support HID devices (from the USB 54 + specification standpoint) that aren't strictly user interface 55 + devices, like monitor controls and Uninterruptable Power Supplies. 56 + 57 + This module supports these devices separately using a separate 58 + event interface on /dev/hidraw. 59 + 60 + There is also a /dev/hiddev configuration option in the USB HID 61 + configuration menu. In comparison to hiddev, this device does not process 62 + the hid events at all (no parsing, no lookups). This lets applications 63 + to work on raw hid events when they want to, and avoid using transport-specific 64 + userspace libhid/libusb libraries. 65 + 66 + If unsure, say Y. 67 + 49 68 source "drivers/hid/usbhid/Kconfig" 50 69 51 70 endif # HID_SUPPORT
+2
drivers/hid/Makefile
··· 4 4 hid-objs := hid-core.o hid-input.o 5 5 6 6 obj-$(CONFIG_HID) += hid.o 7 + 7 8 hid-$(CONFIG_HID_DEBUG) += hid-debug.o 9 + hid-$(CONFIG_HIDRAW) += hidraw.o 8 10 9 11 obj-$(CONFIG_USB_HID) += usbhid/ 10 12 obj-$(CONFIG_USB_MOUSE) += usbhid/
+16
drivers/hid/hid-core.c
··· 30 30 #include <linux/hid.h> 31 31 #include <linux/hiddev.h> 32 32 #include <linux/hid-debug.h> 33 + #include <linux/hidraw.h> 33 34 34 35 /* 35 36 * Version Information ··· 980 979 981 980 if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) 982 981 hid->hiddev_report_event(hid, report); 982 + if (hid->claimed & HID_CLAIMED_HIDRAW) 983 + hidraw_report_event(hid, data, size); 983 984 984 985 for (n = 0; n < report->maxfield; n++) 985 986 hid_input_field(hid, report->field[n], data, interrupt); ··· 992 989 return 0; 993 990 } 994 991 EXPORT_SYMBOL_GPL(hid_input_report); 992 + 993 + static int __init hid_init(void) 994 + { 995 + return hidraw_init(); 996 + } 997 + 998 + static void __exit hid_exit(void) 999 + { 1000 + hidraw_exit(); 1001 + } 1002 + 1003 + module_init(hid_init); 1004 + module_exit(hid_exit); 995 1005 996 1006 MODULE_LICENSE(DRIVER_LICENSE); 997 1007
+401
drivers/hid/hidraw.c
··· 1 + /* 2 + * HID raw devices, giving access to raw HID events. 3 + * 4 + * In comparison to hiddev, this device does not process the 5 + * hid events at all (no parsing, no lookups). This lets applications 6 + * to work on raw hid events as they want to, and avoids a need to 7 + * use a transport-specific userspace libhid/libusb libraries. 8 + * 9 + * Copyright (c) 2007 Jiri Kosina 10 + */ 11 + 12 + /* 13 + * This program is free software; you can redistribute it and/or modify it 14 + * under the terms and conditions of the GNU General Public License, 15 + * version 2, as published by the Free Software Foundation. 16 + * 17 + * You should have received a copy of the GNU General Public License along with 18 + * this program; if not, write to the Free Software Foundation, Inc., 19 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 20 + */ 21 + 22 + #include <linux/fs.h> 23 + #include <linux/module.h> 24 + #include <linux/errno.h> 25 + #include <linux/kernel.h> 26 + #include <linux/init.h> 27 + #include <linux/cdev.h> 28 + #include <linux/poll.h> 29 + #include <linux/device.h> 30 + #include <linux/major.h> 31 + #include <linux/hid.h> 32 + #include <linux/mutex.h> 33 + 34 + #include <linux/hidraw.h> 35 + 36 + static int hidraw_major; 37 + static struct cdev hidraw_cdev; 38 + static struct class *hidraw_class; 39 + static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; 40 + static DEFINE_SPINLOCK(minors_lock); 41 + 42 + static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) 43 + { 44 + struct hidraw_list *list = file->private_data; 45 + int ret = 0, len; 46 + char *report; 47 + DECLARE_WAITQUEUE(wait, current); 48 + 49 + while (ret == 0) { 50 + 51 + mutex_lock(&list->read_mutex); 52 + 53 + if (list->head == list->tail) { 54 + add_wait_queue(&list->hidraw->wait, &wait); 55 + set_current_state(TASK_INTERRUPTIBLE); 56 + 57 + while (list->head == list->tail) { 58 + if (file->f_flags & O_NONBLOCK) { 59 + ret = -EAGAIN; 60 + break; 61 + } 62 + if (signal_pending(current)) { 63 + ret = -ERESTARTSYS; 64 + break; 65 + } 66 + if (!list->hidraw->exist) { 67 + ret = -EIO; 68 + break; 69 + } 70 + 71 + /* allow O_NONBLOCK to work well from other threads */ 72 + mutex_unlock(&list->read_mutex); 73 + schedule(); 74 + mutex_lock(&list->read_mutex); 75 + set_current_state(TASK_INTERRUPTIBLE); 76 + } 77 + 78 + set_current_state(TASK_RUNNING); 79 + remove_wait_queue(&list->hidraw->wait, &wait); 80 + } 81 + 82 + if (ret) 83 + goto out; 84 + 85 + report = list->buffer[list->tail].value; 86 + len = list->buffer[list->tail].len > count ? 87 + count : list->buffer[list->tail].len; 88 + 89 + if (copy_to_user(buffer, list->buffer[list->tail].value, len)) { 90 + ret = -EFAULT; 91 + goto out; 92 + } 93 + ret += len; 94 + 95 + kfree(list->buffer[list->tail].value); 96 + list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1); 97 + } 98 + out: 99 + mutex_unlock(&list->read_mutex); 100 + return ret; 101 + } 102 + 103 + /* the first byte is expected to be a report number */ 104 + static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) 105 + { 106 + unsigned int minor = iminor(file->f_path.dentry->d_inode); 107 + struct hid_device *dev = hidraw_table[minor]->hid; 108 + __u8 *buf; 109 + int ret = 0; 110 + 111 + if (!dev->hid_output_raw_report) 112 + return -ENODEV; 113 + 114 + if (count > HID_MIN_BUFFER_SIZE) { 115 + printk(KERN_WARNING "hidraw: pid %d passed too large report\n", 116 + current->pid); 117 + return -EINVAL; 118 + } 119 + 120 + if (count < 2) { 121 + printk(KERN_WARNING "hidraw: pid %d passed too short report\n", 122 + current->pid); 123 + return -EINVAL; 124 + } 125 + 126 + buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); 127 + if (!buf) 128 + return -ENOMEM; 129 + 130 + if (copy_from_user(buf, buffer, count)) { 131 + ret = -EFAULT; 132 + goto out; 133 + } 134 + 135 + ret = dev->hid_output_raw_report(dev, buf, count); 136 + out: 137 + kfree(buf); 138 + return ret; 139 + } 140 + 141 + static unsigned int hidraw_poll(struct file *file, poll_table *wait) 142 + { 143 + struct hidraw_list *list = file->private_data; 144 + 145 + poll_wait(file, &list->hidraw->wait, wait); 146 + if (list->head != list->tail) 147 + return POLLIN | POLLRDNORM; 148 + if (!list->hidraw->exist) 149 + return POLLERR | POLLHUP; 150 + return 0; 151 + } 152 + 153 + static int hidraw_open(struct inode *inode, struct file *file) 154 + { 155 + unsigned int minor = iminor(inode); 156 + struct hidraw *dev; 157 + struct hidraw_list *list; 158 + int err = 0; 159 + 160 + if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { 161 + err = -ENOMEM; 162 + goto out; 163 + } 164 + 165 + spin_lock(&minors_lock); 166 + if (!hidraw_table[minor]) { 167 + printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", 168 + minor); 169 + kfree(list); 170 + err = -ENODEV; 171 + goto out_unlock; 172 + } 173 + 174 + list->hidraw = hidraw_table[minor]; 175 + mutex_init(&list->read_mutex); 176 + list_add_tail(&list->node, &hidraw_table[minor]->list); 177 + file->private_data = list; 178 + 179 + dev = hidraw_table[minor]; 180 + if (!dev->open++) 181 + dev->hid->hid_open(dev->hid); 182 + 183 + out_unlock: 184 + spin_unlock(&minors_lock); 185 + out: 186 + return err; 187 + 188 + } 189 + 190 + static int hidraw_release(struct inode * inode, struct file * file) 191 + { 192 + unsigned int minor = iminor(inode); 193 + struct hidraw *dev; 194 + struct hidraw_list *list = file->private_data; 195 + 196 + if (!hidraw_table[minor]) { 197 + printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", 198 + minor); 199 + return -ENODEV; 200 + } 201 + 202 + list_del(&list->node); 203 + dev = hidraw_table[minor]; 204 + if (!dev->open--) { 205 + if (list->hidraw->exist) 206 + dev->hid->hid_close(dev->hid); 207 + else 208 + kfree(list->hidraw); 209 + } 210 + 211 + return 0; 212 + } 213 + 214 + static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 215 + { 216 + unsigned int minor = iminor(inode); 217 + struct hidraw *dev = hidraw_table[minor]; 218 + void __user *user_arg = (void __user*) arg; 219 + 220 + switch (cmd) { 221 + case HIDIOCGRDESCSIZE: 222 + if (put_user(dev->hid->rsize, (int __user *)arg)) 223 + return -EFAULT; 224 + return 0; 225 + 226 + case HIDIOCGRDESC: 227 + { 228 + __u32 len; 229 + 230 + if (get_user(len, (int __user *)arg)) 231 + return -EFAULT; 232 + if (copy_to_user(*((__u8 **)(user_arg + 233 + sizeof(__u32))), 234 + dev->hid->rdesc, len)) 235 + return -EFAULT; 236 + return 0; 237 + } 238 + case HIDIOCGRAWINFO: 239 + { 240 + struct hidraw_devinfo dinfo; 241 + 242 + dinfo.bustype = dev->hid->bus; 243 + dinfo.vendor = dev->hid->vendor; 244 + dinfo.product = dev->hid->product; 245 + if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) 246 + return -EFAULT; 247 + 248 + return 0; 249 + } 250 + default: 251 + printk(KERN_EMERG "hidraw: unsupported ioctl() %x\n", 252 + cmd); 253 + } 254 + return -EINVAL; 255 + } 256 + 257 + static const struct file_operations hidraw_ops = { 258 + .owner = THIS_MODULE, 259 + .read = hidraw_read, 260 + .write = hidraw_write, 261 + .poll = hidraw_poll, 262 + .open = hidraw_open, 263 + .release = hidraw_release, 264 + .ioctl = hidraw_ioctl, 265 + }; 266 + 267 + void hidraw_report_event(struct hid_device *hid, u8 *data, int len) 268 + { 269 + struct hidraw *dev = hid->hidraw; 270 + struct hidraw_list *list; 271 + 272 + list_for_each_entry(list, &dev->list, node) { 273 + list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC); 274 + list->buffer[list->head].len = len; 275 + list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); 276 + kill_fasync(&list->fasync, SIGIO, POLL_IN); 277 + } 278 + 279 + wake_up_interruptible(&dev->wait); 280 + } 281 + EXPORT_SYMBOL_GPL(hidraw_report_event); 282 + 283 + int hidraw_connect(struct hid_device *hid) 284 + { 285 + int minor, result; 286 + struct hidraw *dev; 287 + 288 + /* TODO currently we accept any HID device. This should later 289 + * probably be fixed to accept only those devices which provide 290 + * non-input applications 291 + */ 292 + 293 + dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL); 294 + if (!dev) 295 + return -ENOMEM; 296 + 297 + result = -EINVAL; 298 + 299 + spin_lock(&minors_lock); 300 + 301 + for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) { 302 + if (hidraw_table[minor]) 303 + continue; 304 + hidraw_table[minor] = dev; 305 + result = 0; 306 + break; 307 + } 308 + 309 + spin_unlock(&minors_lock); 310 + 311 + if (result) { 312 + kfree(dev); 313 + goto out; 314 + } 315 + 316 + dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor), 317 + "%s%d", "hidraw", minor); 318 + 319 + if (IS_ERR(dev->dev)) { 320 + spin_lock(&minors_lock); 321 + hidraw_table[minor] = NULL; 322 + spin_unlock(&minors_lock); 323 + result = PTR_ERR(dev->dev); 324 + kfree(dev); 325 + goto out; 326 + } 327 + 328 + init_waitqueue_head(&dev->wait); 329 + INIT_LIST_HEAD(&dev->list); 330 + 331 + dev->hid = hid; 332 + dev->minor = minor; 333 + 334 + dev->exist = 1; 335 + hid->hidraw = dev; 336 + 337 + out: 338 + return result; 339 + 340 + } 341 + EXPORT_SYMBOL_GPL(hidraw_connect); 342 + 343 + void hidraw_disconnect(struct hid_device *hid) 344 + { 345 + struct hidraw *hidraw = hid->hidraw; 346 + 347 + hidraw->exist = 0; 348 + 349 + spin_lock(&minors_lock); 350 + hidraw_table[hidraw->minor] = NULL; 351 + spin_unlock(&minors_lock); 352 + 353 + device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); 354 + 355 + if (hidraw->open) { 356 + hid->hid_close(hid); 357 + wake_up_interruptible(&hidraw->wait); 358 + } else { 359 + kfree(hidraw); 360 + } 361 + } 362 + EXPORT_SYMBOL_GPL(hidraw_disconnect); 363 + 364 + int __init hidraw_init(void) 365 + { 366 + int result; 367 + dev_t dev_id; 368 + 369 + result = alloc_chrdev_region(&dev_id, HIDRAW_FIRST_MINOR, 370 + HIDRAW_MAX_DEVICES, "hidraw"); 371 + 372 + hidraw_major = MAJOR(dev_id); 373 + 374 + if (result < 0) { 375 + printk(KERN_WARNING "hidraw: can't get major number\n"); 376 + result = 0; 377 + goto out; 378 + } 379 + 380 + hidraw_class = class_create(THIS_MODULE, "hidraw"); 381 + if (IS_ERR(hidraw_class)) { 382 + result = PTR_ERR(hidraw_class); 383 + unregister_chrdev(hidraw_major, "hidraw"); 384 + goto out; 385 + } 386 + 387 + cdev_init(&hidraw_cdev, &hidraw_ops); 388 + cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES); 389 + out: 390 + return result; 391 + } 392 + 393 + void __exit hidraw_exit(void) 394 + { 395 + dev_t dev_id = MKDEV(hidraw_major, 0); 396 + 397 + cdev_del(&hidraw_cdev); 398 + class_destroy(hidraw_class); 399 + unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES); 400 + 401 + }
+36 -2
drivers/hid/usbhid/hid-core.c
··· 32 32 #include <linux/hid.h> 33 33 #include <linux/hiddev.h> 34 34 #include <linux/hid-debug.h> 35 + #include <linux/hidraw.h> 35 36 #include "usbhid.h" 36 37 37 38 /* ··· 640 639 return 0; 641 640 } 642 641 642 + static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count) 643 + { 644 + struct usbhid_device *usbhid = hid->driver_data; 645 + struct usb_device *dev = hid_to_usb_dev(hid); 646 + struct usb_interface *intf = usbhid->intf; 647 + struct usb_host_interface *interface = intf->cur_altsetting; 648 + int ret; 649 + 650 + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 651 + HID_REQ_SET_REPORT, 652 + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 653 + cpu_to_le16(((HID_OUTPUT_REPORT + 1) << 8) | *buf), 654 + interface->desc.bInterfaceNumber, buf + 1, count - 1, 655 + USB_CTRL_SET_TIMEOUT); 656 + 657 + /* count also the report id */ 658 + if (ret > 0) 659 + ret++; 660 + 661 + return ret; 662 + } 663 + 643 664 static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) 644 665 { 645 666 struct usbhid_device *usbhid = hid->driver_data; ··· 905 882 hid->hiddev_hid_event = hiddev_hid_event; 906 883 hid->hiddev_report_event = hiddev_report_event; 907 884 #endif 885 + hid->hid_output_raw_report = usbhid_output_raw_report; 908 886 return hid; 909 887 910 888 fail: ··· 944 920 hidinput_disconnect(hid); 945 921 if (hid->claimed & HID_CLAIMED_HIDDEV) 946 922 hiddev_disconnect(hid); 923 + if (hid->claimed & HID_CLAIMED_HIDRAW) 924 + hidraw_disconnect(hid); 947 925 948 926 usb_free_urb(usbhid->urbin); 949 927 usb_free_urb(usbhid->urbctrl); ··· 978 952 hid->claimed |= HID_CLAIMED_INPUT; 979 953 if (!hiddev_connect(hid)) 980 954 hid->claimed |= HID_CLAIMED_HIDDEV; 955 + if (!hidraw_connect(hid)) 956 + hid->claimed |= HID_CLAIMED_HIDRAW; 981 957 982 958 usb_set_intfdata(intf, hid); 983 959 984 960 if (!hid->claimed) { 985 - printk ("HID device not claimed by input or hiddev\n"); 961 + printk ("HID device claimed by neither input, hiddev nor hidraw\n"); 986 962 hid_disconnect(intf); 987 963 return -ENODEV; 988 964 } ··· 1000 972 1001 973 if (hid->claimed & HID_CLAIMED_INPUT) 1002 974 printk("input"); 1003 - if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV)) 975 + if ((hid->claimed & HID_CLAIMED_INPUT) && ((hid->claimed & HID_CLAIMED_HIDDEV) || 976 + hid->claimed & HID_CLAIMED_HIDRAW)) 1004 977 printk(","); 1005 978 if (hid->claimed & HID_CLAIMED_HIDDEV) 1006 979 printk("hiddev%d", hid->minor); 980 + if ((hid->claimed & HID_CLAIMED_INPUT) && (hid->claimed & HID_CLAIMED_HIDDEV) && 981 + (hid->claimed & HID_CLAIMED_HIDRAW)) 982 + printk(","); 983 + if (hid->claimed & HID_CLAIMED_HIDRAW) 984 + printk("hidraw%d", ((struct hidraw*)hid->hidraw)->minor); 1007 985 1008 986 c = "Device"; 1009 987 for (i = 0; i < hid->maxcollection; i++) {
+5
include/linux/hid.h
··· 405 405 406 406 #define HID_CLAIMED_INPUT 1 407 407 #define HID_CLAIMED_HIDDEV 2 408 + #define HID_CLAIMED_HIDRAW 4 408 409 409 410 #define HID_CTRL_RUNNING 1 410 411 #define HID_OUT_RUNNING 2 ··· 441 440 442 441 struct list_head inputs; /* The list of inputs */ 443 442 void *hiddev; /* The hiddev structure */ 443 + void *hidraw; 444 444 int minor; /* Hiddev minor number */ 445 445 446 446 wait_queue_head_t wait; /* For sleeping */ ··· 462 460 void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field, 463 461 struct hid_usage *, __s32); 464 462 void (*hiddev_report_event) (struct hid_device *, struct hid_report *); 463 + 464 + /* handler for raw output data, used by hidraw */ 465 + int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t); 465 466 #ifdef CONFIG_USB_HIDINPUT_POWERBOOK 466 467 unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; 467 468 unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
+86
include/linux/hidraw.h
··· 1 + #ifndef _HIDRAW_H 2 + #define _HIDRAW_H 3 + 4 + /* 5 + * Copyright (c) 2007 Jiri Kosina 6 + */ 7 + 8 + /* 9 + * This program is free software; you can redistribute it and/or modify it 10 + * under the terms and conditions of the GNU General Public License, 11 + * version 2, as published by the Free Software Foundation. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 15 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 + */ 17 + 18 + struct hidraw_report_descriptor { 19 + __u32 size; 20 + __u8 *value; 21 + }; 22 + 23 + struct hidraw_devinfo { 24 + __u32 bustype; 25 + __s16 vendor; 26 + __s16 product; 27 + }; 28 + 29 + /* ioctl interface */ 30 + #define HIDIOCGRDESCSIZE _IOR('H', 0x01, int) 31 + #define HIDIOCGRDESC _IOR('H', 0x02, struct hidraw_report_descriptor) 32 + #define HIDIOCGRAWINFO _IOR('H', 0x03, struct hidraw_devinfo) 33 + 34 + #define HIDRAW_FIRST_MINOR 0 35 + #define HIDRAW_MAX_DEVICES 64 36 + /* number of reports to buffer */ 37 + #define HIDRAW_BUFFER_SIZE 64 38 + 39 + 40 + /* kernel-only API declarations */ 41 + #ifdef __KERNEL__ 42 + 43 + #include <linux/hid.h> 44 + 45 + struct hidraw { 46 + unsigned int minor; 47 + int exist; 48 + int open; 49 + wait_queue_head_t wait; 50 + struct hid_device *hid; 51 + struct device *dev; 52 + struct list_head list; 53 + }; 54 + 55 + struct hidraw_report { 56 + __u8 *value; 57 + int len; 58 + }; 59 + 60 + struct hidraw_list { 61 + struct hidraw_report buffer[HIDRAW_BUFFER_SIZE]; 62 + int head; 63 + int tail; 64 + struct fasync_struct *fasync; 65 + struct hidraw *hidraw; 66 + struct list_head node; 67 + struct mutex read_mutex; 68 + }; 69 + 70 + #ifdef CONFIG_HIDRAW 71 + int hidraw_init(void); 72 + void hidraw_exit(void); 73 + void hidraw_report_event(struct hid_device *, u8 *, int); 74 + int hidraw_connect(struct hid_device *); 75 + void hidraw_disconnect(struct hid_device *); 76 + #else 77 + static inline int hidraw_init(void) { return 0; } 78 + static inline void hidraw_exit(void) { } 79 + static inline void hidraw_report_event(struct hid_device *hid, u8 *data, int len) { } 80 + static inline int hidraw_connect(struct hid_device *hid) { return -1; } 81 + static inline void hidraw_disconnect(struct hid_device *hid) { } 82 + #endif 83 + 84 + #endif 85 + 86 + #endif