···354354 goto err_free;355355 }356356357357- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_HIDINPUT);357357+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);358358 if (ret) {359359 dev_err(&hdev->dev, "magicmouse hw start failed\n");360360 goto err_free;361361 }362362+363363+ /* we are handling the input ourselves */364364+ hidinput_disconnect(hdev);362365363366 report = hid_register_report(hdev, HID_INPUT_REPORT, TOUCH_REPORT_ID);364367 if (!report) {
+31-27
drivers/hid/hidraw.c
···106106static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)107107{108108 unsigned int minor = iminor(file->f_path.dentry->d_inode);109109- /* FIXME: What stops hidraw_table going NULL */110110- struct hid_device *dev = hidraw_table[minor]->hid;109109+ struct hid_device *dev;111110 __u8 *buf;112111 int ret = 0;113112114114- if (!dev->hid_output_raw_report)115115- return -ENODEV;113113+ mutex_lock(&minors_lock);114114+ dev = hidraw_table[minor]->hid;115115+116116+ if (!dev->hid_output_raw_report) {117117+ ret = -ENODEV;118118+ goto out;119119+ }116120117121 if (count > HID_MAX_BUFFER_SIZE) {118122 printk(KERN_WARNING "hidraw: pid %d passed too large report\n",119123 task_pid_nr(current));120120- return -EINVAL;124124+ ret = -EINVAL;125125+ goto out;121126 }122127123128 if (count < 2) {124129 printk(KERN_WARNING "hidraw: pid %d passed too short report\n",125130 task_pid_nr(current));126126- return -EINVAL;127127- }128128-129129- buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);130130- if (!buf)131131- return -ENOMEM;132132-133133- if (copy_from_user(buf, buffer, count)) {134134- ret = -EFAULT;131131+ ret = -EINVAL;135132 goto out;136133 }137134135135+ buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);136136+ if (!buf) {137137+ ret = -ENOMEM;138138+ goto out;139139+ }140140+141141+ if (copy_from_user(buf, buffer, count)) {142142+ ret = -EFAULT;143143+ goto out_free;144144+ }145145+138146 ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT);139139-out:147147+out_free:140148 kfree(buf);149149+out:150150+ mutex_unlock(&minors_lock);141151 return ret;142152}143153···175165 goto out;176166 }177167178178- lock_kernel();179168 mutex_lock(&minors_lock);180169 if (!hidraw_table[minor]) {181181- printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",182182- minor);183170 kfree(list);184171 err = -ENODEV;185172 goto out_unlock;···204197205198out_unlock:206199 mutex_unlock(&minors_lock);207207- unlock_kernel();208200out:209201 return err;210202···215209 struct hidraw *dev;216210 struct hidraw_list *list = file->private_data;217211218218- if (!hidraw_table[minor]) {219219- printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",220220- minor);212212+ if (!hidraw_table[minor])221213 return -ENODEV;222222- }223214224215 list_del(&list->node);225216 dev = hidraw_table[minor];···241238 struct inode *inode = file->f_path.dentry->d_inode;242239 unsigned int minor = iminor(inode);243240 long ret = 0;244244- /* FIXME: What stops hidraw_table going NULL */245245- struct hidraw *dev = hidraw_table[minor];241241+ struct hidraw *dev;246242 void __user *user_arg = (void __user*) arg;247243248248- lock_kernel();244244+ mutex_lock(&minors_lock);245245+ dev = hidraw_table[minor];246246+249247 switch (cmd) {250248 case HIDIOCGRDESCSIZE:251249 if (put_user(dev->hid->rsize, (int __user *)arg))···319315320316 ret = -ENOTTY;321317 }322322- unlock_kernel();318318+ mutex_unlock(&minors_lock);323319 return ret;324320}325321
+23-1
drivers/hid/usbhid/hid-core.c
···13131313 {13141314 set_bit(HID_REPORTED_IDLE, &usbhid->iofl);13151315 spin_unlock_irq(&usbhid->lock);13161316+ if (hid->driver && hid->driver->suspend) {13171317+ status = hid->driver->suspend(hid, message);13181318+ if (status < 0)13191319+ return status;13201320+ }13161321 } else {13171322 usbhid_mark_busy(usbhid);13181323 spin_unlock_irq(&usbhid->lock);···13251320 }1326132113271322 } else {13231323+ if (hid->driver && hid->driver->suspend) {13241324+ status = hid->driver->suspend(hid, message);13251325+ if (status < 0)13261326+ return status;13271327+ }13281328 spin_lock_irq(&usbhid->lock);13291329 set_bit(HID_REPORTED_IDLE, &usbhid->iofl);13301330 spin_unlock_irq(&usbhid->lock);···13841374 hid_io_error(hid);13851375 usbhid_restart_queues(usbhid);1386137613771377+ if (status >= 0 && hid->driver && hid->driver->resume) {13781378+ int ret = hid->driver->resume(hid);13791379+ if (ret < 0)13801380+ status = ret;13811381+ }13871382 dev_dbg(&intf->dev, "resume status %d\n", status);13881383 return 0;13891384}···13971382{13981383 struct hid_device *hid = usb_get_intfdata(intf);13991384 struct usbhid_device *usbhid = hid->driver_data;13851385+ int status;1400138614011387 clear_bit(HID_REPORTED_IDLE, &usbhid->iofl);14021402- return hid_post_reset(intf);13881388+ status = hid_post_reset(intf);13891389+ if (status >= 0 && hid->driver && hid->driver->reset_resume) {13901390+ int ret = hid->driver->reset_resume(hid);13911391+ if (ret < 0)13921392+ status = ret;13931393+ }13941394+ return status;14031395}1404139614051397#endif /* CONFIG_PM */
+17-2
drivers/hid/usbhid/hiddev.c
···267267 struct hiddev_list *list;268268 int res, i;269269270270+ /* See comment in hiddev_connect() for BKL explanation */270271 lock_kernel();271272 i = iminor(inode) - HIDDEV_MINOR_BASE;272273···895894 hiddev->hid = hid;896895 hiddev->exist = 1;897896898898- /* when lock_kernel() usage is fixed in usb_open(),899899- * we could also fix it here */897897+ /*898898+ * BKL here is used to avoid race after usb_register_dev().899899+ * Once the device node has been created, open() could happen on it.900900+ * The code below will then fail, as hiddev_table hasn't been901901+ * updated.902902+ *903903+ * The obvious fix -- introducing mutex to guard hiddev_table[]904904+ * doesn't work, as usb_open() and usb_register_dev() both take905905+ * minor_rwsem, thus we'll have ABBA deadlock.906906+ *907907+ * Before BKL pushdown, usb_open() had been acquiring it in right908908+ * order, so _open() was safe to use it to protect from this race.909909+ * Now the order is different, but AB-BA deadlock still doesn't occur910910+ * as BKL is dropped on schedule() (i.e. while sleeping on911911+ * minor_rwsem). Fugly.912912+ */900913 lock_kernel();901914 retval = usb_register_dev(usbhid->intf, &hiddev_class);902915 if (retval) {
+8
include/linux/hid.h
···591591 * @report_fixup: called before report descriptor parsing (NULL means nop)592592 * @input_mapping: invoked on input registering before mapping an usage593593 * @input_mapped: invoked on input registering after mapping an usage594594+ * @suspend: invoked on suspend (NULL means nop)595595+ * @resume: invoked on resume if device was not reset (NULL means nop)596596+ * @reset_resume: invoked on resume if device was reset (NULL means nop)594597 *595598 * raw_event and event should return 0 on no action performed, 1 when no596599 * further processing should be done and negative on error···634631 int (*input_mapped)(struct hid_device *hdev,635632 struct hid_input *hidinput, struct hid_field *field,636633 struct hid_usage *usage, unsigned long **bit, int *max);634634+#ifdef CONFIG_PM635635+ int (*suspend)(struct hid_device *hdev, pm_message_t message);636636+ int (*resume)(struct hid_device *hdev);637637+ int (*reset_resume)(struct hid_device *hdev);638638+#endif637639/* private: */638640 struct device_driver driver;639641};