diff options
Diffstat (limited to 'drivers/hid/hidraw.c')
-rw-r--r-- | drivers/hid/hidraw.c | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 0c6b4d4e7e27..c40f0403edaf 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -105,6 +105,7 @@ out: | |||
105 | static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 105 | static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
106 | { | 106 | { |
107 | unsigned int minor = iminor(file->f_path.dentry->d_inode); | 107 | unsigned int minor = iminor(file->f_path.dentry->d_inode); |
108 | /* FIXME: What stops hidraw_table going NULL */ | ||
108 | struct hid_device *dev = hidraw_table[minor]->hid; | 109 | struct hid_device *dev = hidraw_table[minor]->hid; |
109 | __u8 *buf; | 110 | __u8 *buf; |
110 | int ret = 0; | 111 | int ret = 0; |
@@ -211,38 +212,43 @@ static int hidraw_release(struct inode * inode, struct file * file) | |||
211 | kfree(list->hidraw); | 212 | kfree(list->hidraw); |
212 | } | 213 | } |
213 | 214 | ||
215 | kfree(list); | ||
216 | |||
214 | return 0; | 217 | return 0; |
215 | } | 218 | } |
216 | 219 | ||
217 | static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 220 | static long hidraw_ioctl(struct file *file, unsigned int cmd, |
221 | unsigned long arg) | ||
218 | { | 222 | { |
223 | struct inode *inode = file->f_path.dentry->d_inode; | ||
219 | unsigned int minor = iminor(inode); | 224 | unsigned int minor = iminor(inode); |
225 | long ret = 0; | ||
226 | /* FIXME: What stops hidraw_table going NULL */ | ||
220 | struct hidraw *dev = hidraw_table[minor]; | 227 | struct hidraw *dev = hidraw_table[minor]; |
221 | void __user *user_arg = (void __user*) arg; | 228 | void __user *user_arg = (void __user*) arg; |
222 | 229 | ||
230 | lock_kernel(); | ||
223 | switch (cmd) { | 231 | switch (cmd) { |
224 | case HIDIOCGRDESCSIZE: | 232 | case HIDIOCGRDESCSIZE: |
225 | if (put_user(dev->hid->rsize, (int __user *)arg)) | 233 | if (put_user(dev->hid->rsize, (int __user *)arg)) |
226 | return -EFAULT; | 234 | ret = -EFAULT; |
227 | return 0; | 235 | break; |
228 | 236 | ||
229 | case HIDIOCGRDESC: | 237 | case HIDIOCGRDESC: |
230 | { | 238 | { |
231 | __u32 len; | 239 | __u32 len; |
232 | 240 | ||
233 | if (get_user(len, (int __user *)arg)) | 241 | if (get_user(len, (int __user *)arg)) |
234 | return -EFAULT; | 242 | ret = -EFAULT; |
235 | 243 | else if (len > HID_MAX_DESCRIPTOR_SIZE - 1) | |
236 | if (len > HID_MAX_DESCRIPTOR_SIZE - 1) | 244 | ret = -EINVAL; |
237 | return -EINVAL; | 245 | else if (copy_to_user(user_arg + offsetof( |
238 | 246 | struct hidraw_report_descriptor, | |
239 | if (copy_to_user(user_arg + offsetof( | 247 | value[0]), |
240 | struct hidraw_report_descriptor, | 248 | dev->hid->rdesc, |
241 | value[0]), | 249 | min(dev->hid->rsize, len))) |
242 | dev->hid->rdesc, | 250 | ret = -EFAULT; |
243 | min(dev->hid->rsize, len))) | 251 | break; |
244 | return -EFAULT; | ||
245 | return 0; | ||
246 | } | 252 | } |
247 | case HIDIOCGRAWINFO: | 253 | case HIDIOCGRAWINFO: |
248 | { | 254 | { |
@@ -252,15 +258,13 @@ static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
252 | dinfo.vendor = dev->hid->vendor; | 258 | dinfo.vendor = dev->hid->vendor; |
253 | dinfo.product = dev->hid->product; | 259 | dinfo.product = dev->hid->product; |
254 | if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) | 260 | if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) |
255 | return -EFAULT; | 261 | ret = -EFAULT; |
256 | 262 | break; | |
257 | return 0; | ||
258 | } | 263 | } |
259 | default: | 264 | default: |
260 | printk(KERN_EMERG "hidraw: unsupported ioctl() %x\n", | 265 | ret = -ENOTTY; |
261 | cmd); | ||
262 | } | 266 | } |
263 | return -EINVAL; | 267 | return ret; |
264 | } | 268 | } |
265 | 269 | ||
266 | static const struct file_operations hidraw_ops = { | 270 | static const struct file_operations hidraw_ops = { |
@@ -270,7 +274,7 @@ static const struct file_operations hidraw_ops = { | |||
270 | .poll = hidraw_poll, | 274 | .poll = hidraw_poll, |
271 | .open = hidraw_open, | 275 | .open = hidraw_open, |
272 | .release = hidraw_release, | 276 | .release = hidraw_release, |
273 | .ioctl = hidraw_ioctl, | 277 | .unlocked_ioctl = hidraw_ioctl, |
274 | }; | 278 | }; |
275 | 279 | ||
276 | void hidraw_report_event(struct hid_device *hid, u8 *data, int len) | 280 | void hidraw_report_event(struct hid_device *hid, u8 *data, int len) |