diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 13:51:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 13:51:03 -0400 |
commit | 8b108c609adefd98577c35f0a41497a610041a6c (patch) | |
tree | f1552fdc5bf0ebcc484a88f01cd3864113adf25c /drivers/hid/hidraw.c | |
parent | 7ce1418f95e918cfc5ad36e3ec3431145c768cd0 (diff) | |
parent | 73d5e8f77e88a4d3a154dfdbb4ed2cf461b7bf21 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (59 commits)
HID: fix up 'EMBEDDED' mess in Kconfig
HID: roccat: cleanup preprocessor macros
HID: roccat: refactor special event handling
HID: roccat: fix special button support
HID: roccat: Correctly mark init and exit functions
HID: hidraw: Use Interrupt Endpoint for OUT Transfers if Available
HID: hid-samsung: remove redundant key mappings
HID: add omitted hid-zydacron.c file
HID: hid-samsung: add support for Creative Desktop Wireless 6000
HID: picolcd: Eliminate use after free
HID: Zydacron Remote Control driver
HID: Use kmemdup
HID: magicmouse: fix input registration
HID: make Prodikeys driver standalone config option
HID: Prodikeys PC-MIDI HID Driver
HID: hidraw: fix indentation
HID: ntrig: add filtering module parameters
HID: ntrig: add sysfs access to filter parameters
HID: ntrig: add sensitivity and responsiveness support
HID: add multi-input quirk for eGalax Touchcontroller
...
Diffstat (limited to 'drivers/hid/hidraw.c')
-rw-r--r-- | drivers/hid/hidraw.c | 50 |
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: | |||
106 | static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 106 | static 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); |
139 | out: | 147 | out_free: |
140 | kfree(buf); | 148 | kfree(buf); |
149 | out: | ||
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 | ||
198 | out_unlock: | 205 | out_unlock: |
199 | mutex_unlock(&minors_lock); | 206 | mutex_unlock(&minors_lock); |
200 | unlock_kernel(); | ||
201 | out: | 207 | out: |
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 | ||