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.c48
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:
105static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) 105static 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
217static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 220static 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
266static const struct file_operations hidraw_ops = { 270static 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
276void hidraw_report_event(struct hid_device *hid, u8 *data, int len) 280void hidraw_report_event(struct hid_device *hid, u8 *data, int len)