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.c46
1 files changed, 24 insertions, 22 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 0c6b4d4e7e27..1018f380de35 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;
@@ -214,35 +215,38 @@ static int hidraw_release(struct inode * inode, struct file * file)
214 return 0; 215 return 0;
215} 216}
216 217
217static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 218static long hidraw_ioctl(struct file *file, unsigned int cmd,
219 unsigned long arg)
218{ 220{
221 struct inode *inode = file->f_path.dentry->d_inode;
219 unsigned int minor = iminor(inode); 222 unsigned int minor = iminor(inode);
223 long ret = 0;
224 /* FIXME: What stops hidraw_table going NULL */
220 struct hidraw *dev = hidraw_table[minor]; 225 struct hidraw *dev = hidraw_table[minor];
221 void __user *user_arg = (void __user*) arg; 226 void __user *user_arg = (void __user*) arg;
222 227
228 lock_kernel();
223 switch (cmd) { 229 switch (cmd) {
224 case HIDIOCGRDESCSIZE: 230 case HIDIOCGRDESCSIZE:
225 if (put_user(dev->hid->rsize, (int __user *)arg)) 231 if (put_user(dev->hid->rsize, (int __user *)arg))
226 return -EFAULT; 232 ret = -EFAULT;
227 return 0; 233 break;
228 234
229 case HIDIOCGRDESC: 235 case HIDIOCGRDESC:
230 { 236 {
231 __u32 len; 237 __u32 len;
232 238
233 if (get_user(len, (int __user *)arg)) 239 if (get_user(len, (int __user *)arg))
234 return -EFAULT; 240 ret = -EFAULT;
235 241 else if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
236 if (len > HID_MAX_DESCRIPTOR_SIZE - 1) 242 ret = -EINVAL;
237 return -EINVAL; 243 else if (copy_to_user(user_arg + offsetof(
238 244 struct hidraw_report_descriptor,
239 if (copy_to_user(user_arg + offsetof( 245 value[0]),
240 struct hidraw_report_descriptor, 246 dev->hid->rdesc,
241 value[0]), 247 min(dev->hid->rsize, len)))
242 dev->hid->rdesc, 248 ret = -EFAULT;
243 min(dev->hid->rsize, len))) 249 break;
244 return -EFAULT;
245 return 0;
246 } 250 }
247 case HIDIOCGRAWINFO: 251 case HIDIOCGRAWINFO:
248 { 252 {
@@ -252,15 +256,13 @@ static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd
252 dinfo.vendor = dev->hid->vendor; 256 dinfo.vendor = dev->hid->vendor;
253 dinfo.product = dev->hid->product; 257 dinfo.product = dev->hid->product;
254 if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) 258 if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
255 return -EFAULT; 259 ret = -EFAULT;
256 260 break;
257 return 0;
258 } 261 }
259 default: 262 default:
260 printk(KERN_EMERG "hidraw: unsupported ioctl() %x\n", 263 ret = -ENOTTY;
261 cmd);
262 } 264 }
263 return -EINVAL; 265 return ret;
264} 266}
265 267
266static const struct file_operations hidraw_ops = { 268static const struct file_operations hidraw_ops = {
@@ -270,7 +272,7 @@ static const struct file_operations hidraw_ops = {
270 .poll = hidraw_poll, 272 .poll = hidraw_poll,
271 .open = hidraw_open, 273 .open = hidraw_open,
272 .release = hidraw_release, 274 .release = hidraw_release,
273 .ioctl = hidraw_ioctl, 275 .unlocked_ioctl = hidraw_ioctl,
274}; 276};
275 277
276void hidraw_report_event(struct hid_device *hid, u8 *data, int len) 278void hidraw_report_event(struct hid_device *hid, u8 *data, int len)