#include <linux/major.h>
#include <linux/hid.h>
#include <linux/mutex.h>
+#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/hidraw.h>
char *report;
DECLARE_WAITQUEUE(wait, current);
- while (ret == 0) {
-
- mutex_lock(&list->read_mutex);
+ mutex_lock(&list->read_mutex);
+ while (ret == 0) {
if (list->head == list->tail) {
add_wait_queue(&list->hidraw->wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
dev = hidraw_table[minor];
if (!dev->open++) {
+ if (dev->hid->ll_driver->power) {
+ err = dev->hid->ll_driver->power(dev->hid, PM_HINT_FULLON);
+ if (err < 0)
+ goto out_unlock;
+ }
err = dev->hid->ll_driver->open(dev->hid);
- if (err < 0)
+ if (err < 0) {
+ if (dev->hid->ll_driver->power)
+ dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL);
dev->open--;
+ }
}
out_unlock:
list_del(&list->node);
dev = hidraw_table[minor];
- if (!dev->open--) {
- if (list->hidraw->exist)
+ if (!--dev->open) {
+ if (list->hidraw->exist) {
+ if (dev->hid->ll_driver->power)
+ dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL);
dev->hid->ll_driver->close(dev->hid);
- else
+ } else {
kfree(list->hidraw);
+ }
}
kfree(list);
default:
{
struct hid_device *hid = dev->hid;
- if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
- return -EINVAL;
+ if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) {
+ ret = -EINVAL;
+ break;
+ }
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
int len;
- if (!hid->name)
- return 0;
+ if (!hid->name) {
+ ret = 0;
+ break;
+ }
len = strlen(hid->name) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
- return copy_to_user(user_arg, hid->name, len) ?
+ ret = copy_to_user(user_arg, hid->name, len) ?
-EFAULT : len;
+ break;
}
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
int len;
- if (!hid->phys)
- return 0;
+ if (!hid->phys) {
+ ret = 0;
+ break;
+ }
len = strlen(hid->phys) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
- return copy_to_user(user_arg, hid->phys, len) ?
+ ret = copy_to_user(user_arg, hid->phys, len) ?
-EFAULT : len;
+ break;
}
}
- ret = -ENOTTY;
+ ret = -ENOTTY;
}
unlock_kernel();
return ret;
int minor, result;
struct hidraw *dev;
- /* TODO currently we accept any HID device. This should later
- * probably be fixed to accept only those devices which provide
- * non-input applications
- */
+ /* we accept any HID device, no matter the applications */
dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
if (!dev)
goto out;
}
- dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
+ dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor),
NULL, "%s%d", "hidraw", minor);
if (IS_ERR(dev->dev)) {