aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-core.c23
-rw-r--r--drivers/hid/hid-magicmouse.c5
-rw-r--r--drivers/hid/hidraw.c48
-rw-r--r--drivers/hid/usbhid/hid-core.c24
-rw-r--r--drivers/hid/usbhid/hiddev.c19
-rw-r--r--include/linux/hid.h8
6 files changed, 86 insertions, 41 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 69fdf1e2347b..33cac4890ca4 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1081,35 +1081,28 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
1081 1081
1082 buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); 1082 buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
1083 1083
1084 if (!buf) { 1084 if (!buf)
1085 report = hid_get_report(report_enum, data);
1086 goto nomem; 1085 goto nomem;
1087 }
1088
1089 snprintf(buf, HID_DEBUG_BUFSIZE - 1,
1090 "\nreport (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
1091 hid_debug_event(hid, buf);
1092
1093 report = hid_get_report(report_enum, data);
1094 if (!report) {
1095 kfree(buf);
1096 return -1;
1097 }
1098 1086
1099 /* dump the report */ 1087 /* dump the report */
1100 snprintf(buf, HID_DEBUG_BUFSIZE - 1, 1088 snprintf(buf, HID_DEBUG_BUFSIZE - 1,
1101 "report %d (size %u) = ", report->id, size); 1089 "\nreport (size %u) (%snumbered) = ", size, report_enum->numbered ? "" : "un");
1102 hid_debug_event(hid, buf); 1090 hid_debug_event(hid, buf);
1091
1103 for (i = 0; i < size; i++) { 1092 for (i = 0; i < size; i++) {
1104 snprintf(buf, HID_DEBUG_BUFSIZE - 1, 1093 snprintf(buf, HID_DEBUG_BUFSIZE - 1,
1105 " %02x", data[i]); 1094 " %02x", data[i]);
1106 hid_debug_event(hid, buf); 1095 hid_debug_event(hid, buf);
1107 } 1096 }
1108 hid_debug_event(hid, "\n"); 1097 hid_debug_event(hid, "\n");
1109
1110 kfree(buf); 1098 kfree(buf);
1111 1099
1112nomem: 1100nomem:
1101 report = hid_get_report(report_enum, data);
1102
1103 if (!report)
1104 return -1;
1105
1113 if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { 1106 if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
1114 ret = hdrv->raw_event(hid, report, data, size); 1107 ret = hdrv->raw_event(hid, report, data, size);
1115 if (ret != 0) 1108 if (ret != 0)
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 0d471fc2ab82..f10d56a15f21 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -354,12 +354,15 @@ static int magicmouse_probe(struct hid_device *hdev,
354 goto err_free; 354 goto err_free;
355 } 355 }
356 356
357 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_HIDINPUT); 357 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
358 if (ret) { 358 if (ret) {
359 dev_err(&hdev->dev, "magicmouse hw start failed\n"); 359 dev_err(&hdev->dev, "magicmouse hw start failed\n");
360 goto err_free; 360 goto err_free;
361 } 361 }
362 362
363 /* we are handling the input ourselves */
364 hidinput_disconnect(hdev);
365
363 report = hid_register_report(hdev, HID_INPUT_REPORT, TOUCH_REPORT_ID); 366 report = hid_register_report(hdev, HID_INPUT_REPORT, TOUCH_REPORT_ID);
364 if (!report) { 367 if (!report) {
365 dev_err(&hdev->dev, "unable to register touch report\n"); 368 dev_err(&hdev->dev, "unable to register touch report\n");
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index a9becf9cd0f6..3ccd47850677 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -106,38 +106,48 @@ out:
106static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) 106static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
107{ 107{
108 unsigned int minor = iminor(file->f_path.dentry->d_inode); 108 unsigned int minor = iminor(file->f_path.dentry->d_inode);
109 /* FIXME: What stops hidraw_table going NULL */ 109 struct hid_device *dev;
110 struct hid_device *dev = hidraw_table[minor]->hid;
111 __u8 *buf; 110 __u8 *buf;
112 int ret = 0; 111 int ret = 0;
113 112
114 if (!dev->hid_output_raw_report) 113 mutex_lock(&minors_lock);
115 return -ENODEV; 114 dev = hidraw_table[minor]->hid;
115
116 if (!dev->hid_output_raw_report) {
117 ret = -ENODEV;
118 goto out;
119 }
116 120
117 if (count > HID_MAX_BUFFER_SIZE) { 121 if (count > HID_MAX_BUFFER_SIZE) {
118 printk(KERN_WARNING "hidraw: pid %d passed too large report\n", 122 printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
119 task_pid_nr(current)); 123 task_pid_nr(current));
120 return -EINVAL; 124 ret = -EINVAL;
125 goto out;
121 } 126 }
122 127
123 if (count < 2) { 128 if (count < 2) {
124 printk(KERN_WARNING "hidraw: pid %d passed too short report\n", 129 printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
125 task_pid_nr(current)); 130 task_pid_nr(current));
126 return -EINVAL; 131 ret = -EINVAL;
132 goto out;
127 } 133 }
128 134
129 buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); 135 buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);
130 if (!buf) 136 if (!buf) {
131 return -ENOMEM; 137 ret = -ENOMEM;
138 goto out;
139 }
132 140
133 if (copy_from_user(buf, buffer, count)) { 141 if (copy_from_user(buf, buffer, count)) {
134 ret = -EFAULT; 142 ret = -EFAULT;
135 goto out; 143 goto out_free;
136 } 144 }
137 145
138 ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT); 146 ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT);
139out: 147out_free:
140 kfree(buf); 148 kfree(buf);
149out:
150 mutex_unlock(&minors_lock);
141 return ret; 151 return ret;
142} 152}
143 153
@@ -165,11 +175,8 @@ static int hidraw_open(struct inode *inode, struct file *file)
165 goto out; 175 goto out;
166 } 176 }
167 177
168 lock_kernel();
169 mutex_lock(&minors_lock); 178 mutex_lock(&minors_lock);
170 if (!hidraw_table[minor]) { 179 if (!hidraw_table[minor]) {
171 printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",
172 minor);
173 kfree(list); 180 kfree(list);
174 err = -ENODEV; 181 err = -ENODEV;
175 goto out_unlock; 182 goto out_unlock;
@@ -197,7 +204,6 @@ static int hidraw_open(struct inode *inode, struct file *file)
197 204
198out_unlock: 205out_unlock:
199 mutex_unlock(&minors_lock); 206 mutex_unlock(&minors_lock);
200 unlock_kernel();
201out: 207out:
202 return err; 208 return err;
203 209
@@ -209,11 +215,8 @@ static int hidraw_release(struct inode * inode, struct file * file)
209 struct hidraw *dev; 215 struct hidraw *dev;
210 struct hidraw_list *list = file->private_data; 216 struct hidraw_list *list = file->private_data;
211 217
212 if (!hidraw_table[minor]) { 218 if (!hidraw_table[minor])
213 printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",
214 minor);
215 return -ENODEV; 219 return -ENODEV;
216 }
217 220
218 list_del(&list->node); 221 list_del(&list->node);
219 dev = hidraw_table[minor]; 222 dev = hidraw_table[minor];
@@ -238,11 +241,12 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
238 struct inode *inode = file->f_path.dentry->d_inode; 241 struct inode *inode = file->f_path.dentry->d_inode;
239 unsigned int minor = iminor(inode); 242 unsigned int minor = iminor(inode);
240 long ret = 0; 243 long ret = 0;
241 /* FIXME: What stops hidraw_table going NULL */ 244 struct hidraw *dev;
242 struct hidraw *dev = hidraw_table[minor];
243 void __user *user_arg = (void __user*) arg; 245 void __user *user_arg = (void __user*) arg;
244 246
245 lock_kernel(); 247 mutex_lock(&minors_lock);
248 dev = hidraw_table[minor];
249
246 switch (cmd) { 250 switch (cmd) {
247 case HIDIOCGRDESCSIZE: 251 case HIDIOCGRDESCSIZE:
248 if (put_user(dev->hid->rsize, (int __user *)arg)) 252 if (put_user(dev->hid->rsize, (int __user *)arg))
@@ -315,7 +319,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
315 319
316 ret = -ENOTTY; 320 ret = -ENOTTY;
317 } 321 }
318 unlock_kernel(); 322 mutex_unlock(&minors_lock);
319 return ret; 323 return ret;
320} 324}
321 325
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index a2ebe1996740..ca3751fd4473 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -1313,6 +1313,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
1313 { 1313 {
1314 set_bit(HID_REPORTED_IDLE, &usbhid->iofl); 1314 set_bit(HID_REPORTED_IDLE, &usbhid->iofl);
1315 spin_unlock_irq(&usbhid->lock); 1315 spin_unlock_irq(&usbhid->lock);
1316 if (hid->driver && hid->driver->suspend) {
1317 status = hid->driver->suspend(hid, message);
1318 if (status < 0)
1319 return status;
1320 }
1316 } else { 1321 } else {
1317 usbhid_mark_busy(usbhid); 1322 usbhid_mark_busy(usbhid);
1318 spin_unlock_irq(&usbhid->lock); 1323 spin_unlock_irq(&usbhid->lock);
@@ -1320,6 +1325,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
1320 } 1325 }
1321 1326
1322 } else { 1327 } else {
1328 if (hid->driver && hid->driver->suspend) {
1329 status = hid->driver->suspend(hid, message);
1330 if (status < 0)
1331 return status;
1332 }
1323 spin_lock_irq(&usbhid->lock); 1333 spin_lock_irq(&usbhid->lock);
1324 set_bit(HID_REPORTED_IDLE, &usbhid->iofl); 1334 set_bit(HID_REPORTED_IDLE, &usbhid->iofl);
1325 spin_unlock_irq(&usbhid->lock); 1335 spin_unlock_irq(&usbhid->lock);
@@ -1374,6 +1384,11 @@ static int hid_resume(struct usb_interface *intf)
1374 hid_io_error(hid); 1384 hid_io_error(hid);
1375 usbhid_restart_queues(usbhid); 1385 usbhid_restart_queues(usbhid);
1376 1386
1387 if (status >= 0 && hid->driver && hid->driver->resume) {
1388 int ret = hid->driver->resume(hid);
1389 if (ret < 0)
1390 status = ret;
1391 }
1377 dev_dbg(&intf->dev, "resume status %d\n", status); 1392 dev_dbg(&intf->dev, "resume status %d\n", status);
1378 return 0; 1393 return 0;
1379} 1394}
@@ -1382,9 +1397,16 @@ static int hid_reset_resume(struct usb_interface *intf)
1382{ 1397{
1383 struct hid_device *hid = usb_get_intfdata(intf); 1398 struct hid_device *hid = usb_get_intfdata(intf);
1384 struct usbhid_device *usbhid = hid->driver_data; 1399 struct usbhid_device *usbhid = hid->driver_data;
1400 int status;
1385 1401
1386 clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); 1402 clear_bit(HID_REPORTED_IDLE, &usbhid->iofl);
1387 return hid_post_reset(intf); 1403 status = hid_post_reset(intf);
1404 if (status >= 0 && hid->driver && hid->driver->reset_resume) {
1405 int ret = hid->driver->reset_resume(hid);
1406 if (ret < 0)
1407 status = ret;
1408 }
1409 return status;
1388} 1410}
1389 1411
1390#endif /* CONFIG_PM */ 1412#endif /* CONFIG_PM */
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 433602aed468..c24d2fa3e3b6 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -267,6 +267,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
267 struct hiddev_list *list; 267 struct hiddev_list *list;
268 int res, i; 268 int res, i;
269 269
270 /* See comment in hiddev_connect() for BKL explanation */
270 lock_kernel(); 271 lock_kernel();
271 i = iminor(inode) - HIDDEV_MINOR_BASE; 272 i = iminor(inode) - HIDDEV_MINOR_BASE;
272 273
@@ -894,8 +895,22 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
894 hiddev->hid = hid; 895 hiddev->hid = hid;
895 hiddev->exist = 1; 896 hiddev->exist = 1;
896 897
897 /* when lock_kernel() usage is fixed in usb_open(), 898 /*
898 * we could also fix it here */ 899 * BKL here is used to avoid race after usb_register_dev().
900 * Once the device node has been created, open() could happen on it.
901 * The code below will then fail, as hiddev_table hasn't been
902 * updated.
903 *
904 * The obvious fix -- introducing mutex to guard hiddev_table[]
905 * doesn't work, as usb_open() and usb_register_dev() both take
906 * minor_rwsem, thus we'll have ABBA deadlock.
907 *
908 * Before BKL pushdown, usb_open() had been acquiring it in right
909 * order, so _open() was safe to use it to protect from this race.
910 * Now the order is different, but AB-BA deadlock still doesn't occur
911 * as BKL is dropped on schedule() (i.e. while sleeping on
912 * minor_rwsem). Fugly.
913 */
899 lock_kernel(); 914 lock_kernel();
900 retval = usb_register_dev(usbhid->intf, &hiddev_class); 915 retval = usb_register_dev(usbhid->intf, &hiddev_class);
901 if (retval) { 916 if (retval) {
diff --git a/include/linux/hid.h b/include/linux/hid.h
index f1f2b6f0d1c4..895001f7f4b2 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -591,6 +591,9 @@ struct hid_usage_id {
591 * @report_fixup: called before report descriptor parsing (NULL means nop) 591 * @report_fixup: called before report descriptor parsing (NULL means nop)
592 * @input_mapping: invoked on input registering before mapping an usage 592 * @input_mapping: invoked on input registering before mapping an usage
593 * @input_mapped: invoked on input registering after mapping an usage 593 * @input_mapped: invoked on input registering after mapping an usage
594 * @suspend: invoked on suspend (NULL means nop)
595 * @resume: invoked on resume if device was not reset (NULL means nop)
596 * @reset_resume: invoked on resume if device was reset (NULL means nop)
594 * 597 *
595 * raw_event and event should return 0 on no action performed, 1 when no 598 * raw_event and event should return 0 on no action performed, 1 when no
596 * further processing should be done and negative on error 599 * further processing should be done and negative on error
@@ -631,6 +634,11 @@ struct hid_driver {
631 int (*input_mapped)(struct hid_device *hdev, 634 int (*input_mapped)(struct hid_device *hdev,
632 struct hid_input *hidinput, struct hid_field *field, 635 struct hid_input *hidinput, struct hid_field *field,
633 struct hid_usage *usage, unsigned long **bit, int *max); 636 struct hid_usage *usage, unsigned long **bit, int *max);
637#ifdef CONFIG_PM
638 int (*suspend)(struct hid_device *hdev, pm_message_t message);
639 int (*resume)(struct hid_device *hdev);
640 int (*reset_resume)(struct hid_device *hdev);
641#endif
634/* private: */ 642/* private: */
635 struct device_driver driver; 643 struct device_driver driver;
636}; 644};