aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hidraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hidraw.c')
-rw-r--r--drivers/hid/hidraw.c50
1 files changed, 27 insertions, 23 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 6eadf1a9b3cc..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))
@@ -311,11 +315,11 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
311 -EFAULT : len; 315 -EFAULT : len;
312 break; 316 break;
313 } 317 }
314 } 318 }
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