X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fhid%2Fhidraw.c;h=3ccd47850677c48fe1d67b1369485a0c9f3eac03;hb=e854df613fe934c94a0b39eccb4104e72ccbbded;hp=e263d47311790b7e215bfd4dbf119999e87064aa;hpb=0361a28d3f9a4315a100c7b37ba0b55cfe15fe07;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index e263d47..3ccd478 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -28,8 +28,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -47,10 +49,9 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, 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); @@ -105,38 +106,48 @@ out: static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { unsigned int minor = iminor(file->f_path.dentry->d_inode); - /* FIXME: What stops hidraw_table going NULL */ - struct hid_device *dev = hidraw_table[minor]->hid; + struct hid_device *dev; __u8 *buf; int ret = 0; - if (!dev->hid_output_raw_report) - return -ENODEV; + mutex_lock(&minors_lock); + dev = hidraw_table[minor]->hid; + + if (!dev->hid_output_raw_report) { + ret = -ENODEV; + goto out; + } if (count > HID_MAX_BUFFER_SIZE) { printk(KERN_WARNING "hidraw: pid %d passed too large report\n", task_pid_nr(current)); - return -EINVAL; + ret = -EINVAL; + goto out; } if (count < 2) { printk(KERN_WARNING "hidraw: pid %d passed too short report\n", task_pid_nr(current)); - return -EINVAL; + ret = -EINVAL; + goto out; } buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); - if (!buf) - return -ENOMEM; + if (!buf) { + ret = -ENOMEM; + goto out; + } if (copy_from_user(buf, buffer, count)) { ret = -EFAULT; - goto out; + goto out_free; } - ret = dev->hid_output_raw_report(dev, buf, count); -out: + ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT); +out_free: kfree(buf); +out: + mutex_unlock(&minors_lock); return ret; } @@ -164,11 +175,8 @@ static int hidraw_open(struct inode *inode, struct file *file) goto out; } - lock_kernel(); mutex_lock(&minors_lock); if (!hidraw_table[minor]) { - printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", - minor); kfree(list); err = -ENODEV; goto out_unlock; @@ -196,7 +204,6 @@ static int hidraw_open(struct inode *inode, struct file *file) out_unlock: mutex_unlock(&minors_lock); - unlock_kernel(); out: return err; @@ -208,11 +215,8 @@ static int hidraw_release(struct inode * inode, struct file * file) struct hidraw *dev; struct hidraw_list *list = file->private_data; - if (!hidraw_table[minor]) { - printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", - minor); + if (!hidraw_table[minor]) return -ENODEV; - } list_del(&list->node); dev = hidraw_table[minor]; @@ -237,11 +241,12 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, struct inode *inode = file->f_path.dentry->d_inode; unsigned int minor = iminor(inode); long ret = 0; - /* FIXME: What stops hidraw_table going NULL */ - struct hidraw *dev = hidraw_table[minor]; + struct hidraw *dev; void __user *user_arg = (void __user*) arg; - lock_kernel(); + mutex_lock(&minors_lock); + dev = hidraw_table[minor]; + switch (cmd) { case HIDIOCGRDESCSIZE: if (put_user(dev->hid->rsize, (int __user *)arg)) @@ -285,8 +290,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, 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); @@ -297,8 +304,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, 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); @@ -306,11 +315,11 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, -EFAULT : len; break; } - } + } ret = -ENOTTY; } - unlock_kernel(); + mutex_unlock(&minors_lock); return ret; } @@ -345,10 +354,7 @@ int hidraw_connect(struct hid_device *hid) 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)