diff options
author | Stefan Achatz <erazor_de@users.sourceforge.net> | 2011-01-30 07:38:25 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-02-03 10:37:28 -0500 |
commit | 8211e46004518c977f70f2661da961d5ba617399 (patch) | |
tree | b2ae1cdc75fad9dbdece7b1dd5fc23ce0624f3c2 /drivers/hid/hid-roccat.c | |
parent | 432762e28b8146d0feff61cc8063b26c517acf26 (diff) |
HID: roccat: Add ioctl command to retreive report size from chardev
Roccat chardev was reworked to support only a defined report size per
device and this can be retreived by an ioctl now to enable future changes
in report definitions.
Header was moved/renamed from drivers/hid to include/linux for accessibility.
Signed-off-by: Stefan Achatz <erazor_de@users.sourceforge.net>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-roccat.c')
-rw-r--r-- | drivers/hid/hid-roccat.c | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index a14c579ea781..0fa23dead5e1 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c | |||
@@ -26,8 +26,7 @@ | |||
26 | #include <linux/cdev.h> | 26 | #include <linux/cdev.h> |
27 | #include <linux/poll.h> | 27 | #include <linux/poll.h> |
28 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
29 | 29 | #include <linux/roccat.h> | |
30 | #include "hid-roccat.h" | ||
31 | 30 | ||
32 | #define ROCCAT_FIRST_MINOR 0 | 31 | #define ROCCAT_FIRST_MINOR 0 |
33 | #define ROCCAT_MAX_DEVICES 8 | 32 | #define ROCCAT_MAX_DEVICES 8 |
@@ -37,11 +36,11 @@ | |||
37 | 36 | ||
38 | struct roccat_report { | 37 | struct roccat_report { |
39 | uint8_t *value; | 38 | uint8_t *value; |
40 | int len; | ||
41 | }; | 39 | }; |
42 | 40 | ||
43 | struct roccat_device { | 41 | struct roccat_device { |
44 | unsigned int minor; | 42 | unsigned int minor; |
43 | int report_size; | ||
45 | int open; | 44 | int open; |
46 | int exist; | 45 | int exist; |
47 | wait_queue_head_t wait; | 46 | wait_queue_head_t wait; |
@@ -123,7 +122,7 @@ static ssize_t roccat_read(struct file *file, char __user *buffer, | |||
123 | * If report is larger than requested amount of data, rest of report | 122 | * If report is larger than requested amount of data, rest of report |
124 | * is lost! | 123 | * is lost! |
125 | */ | 124 | */ |
126 | len = report->len > count ? count : report->len; | 125 | len = device->report_size > count ? count : device->report_size; |
127 | 126 | ||
128 | if (copy_to_user(buffer, report->value, len)) { | 127 | if (copy_to_user(buffer, report->value, len)) { |
129 | retval = -EFAULT; | 128 | retval = -EFAULT; |
@@ -248,26 +247,25 @@ static int roccat_release(struct inode *inode, struct file *file) | |||
248 | * | 247 | * |
249 | * This is called from interrupt handler. | 248 | * This is called from interrupt handler. |
250 | */ | 249 | */ |
251 | int roccat_report_event(int minor, u8 const *data, int len) | 250 | int roccat_report_event(int minor, u8 const *data) |
252 | { | 251 | { |
253 | struct roccat_device *device; | 252 | struct roccat_device *device; |
254 | struct roccat_reader *reader; | 253 | struct roccat_reader *reader; |
255 | struct roccat_report *report; | 254 | struct roccat_report *report; |
256 | uint8_t *new_value; | 255 | uint8_t *new_value; |
257 | 256 | ||
258 | new_value = kmemdup(data, len, GFP_ATOMIC); | 257 | device = devices[minor]; |
258 | |||
259 | new_value = kmemdup(data, device->report_size, GFP_ATOMIC); | ||
259 | if (!new_value) | 260 | if (!new_value) |
260 | return -ENOMEM; | 261 | return -ENOMEM; |
261 | 262 | ||
262 | device = devices[minor]; | ||
263 | |||
264 | report = &device->cbuf[device->cbuf_end]; | 263 | report = &device->cbuf[device->cbuf_end]; |
265 | 264 | ||
266 | /* passing NULL is safe */ | 265 | /* passing NULL is safe */ |
267 | kfree(report->value); | 266 | kfree(report->value); |
268 | 267 | ||
269 | report->value = new_value; | 268 | report->value = new_value; |
270 | report->len = len; | ||
271 | device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE; | 269 | device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE; |
272 | 270 | ||
273 | list_for_each_entry(reader, &device->readers, node) { | 271 | list_for_each_entry(reader, &device->readers, node) { |
@@ -295,7 +293,7 @@ EXPORT_SYMBOL_GPL(roccat_report_event); | |||
295 | * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on | 293 | * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on |
296 | * success, a negative error code on failure. | 294 | * success, a negative error code on failure. |
297 | */ | 295 | */ |
298 | int roccat_connect(struct class *klass, struct hid_device *hid) | 296 | int roccat_connect(struct class *klass, struct hid_device *hid, int report_size) |
299 | { | 297 | { |
300 | unsigned int minor; | 298 | unsigned int minor; |
301 | struct roccat_device *device; | 299 | struct roccat_device *device; |
@@ -343,6 +341,7 @@ int roccat_connect(struct class *klass, struct hid_device *hid) | |||
343 | device->hid = hid; | 341 | device->hid = hid; |
344 | device->exist = 1; | 342 | device->exist = 1; |
345 | device->cbuf_end = 0; | 343 | device->cbuf_end = 0; |
344 | device->report_size = report_size; | ||
346 | 345 | ||
347 | return minor; | 346 | return minor; |
348 | } | 347 | } |
@@ -373,6 +372,34 @@ void roccat_disconnect(int minor) | |||
373 | } | 372 | } |
374 | EXPORT_SYMBOL_GPL(roccat_disconnect); | 373 | EXPORT_SYMBOL_GPL(roccat_disconnect); |
375 | 374 | ||
375 | static long roccat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
376 | { | ||
377 | struct inode *inode = file->f_path.dentry->d_inode; | ||
378 | struct roccat_device *device; | ||
379 | unsigned int minor = iminor(inode); | ||
380 | long retval = 0; | ||
381 | |||
382 | mutex_lock(&devices_lock); | ||
383 | |||
384 | device = devices[minor]; | ||
385 | if (!device) { | ||
386 | retval = -ENODEV; | ||
387 | goto out; | ||
388 | } | ||
389 | |||
390 | switch (cmd) { | ||
391 | case ROCCATIOCGREPSIZE: | ||
392 | if (put_user(device->report_size, (int __user *)arg)) | ||
393 | retval = -EFAULT; | ||
394 | break; | ||
395 | default: | ||
396 | retval = -ENOTTY; | ||
397 | } | ||
398 | out: | ||
399 | mutex_unlock(&devices_lock); | ||
400 | return retval; | ||
401 | } | ||
402 | |||
376 | static const struct file_operations roccat_ops = { | 403 | static const struct file_operations roccat_ops = { |
377 | .owner = THIS_MODULE, | 404 | .owner = THIS_MODULE, |
378 | .read = roccat_read, | 405 | .read = roccat_read, |
@@ -380,6 +407,7 @@ static const struct file_operations roccat_ops = { | |||
380 | .open = roccat_open, | 407 | .open = roccat_open, |
381 | .release = roccat_release, | 408 | .release = roccat_release, |
382 | .llseek = noop_llseek, | 409 | .llseek = noop_llseek, |
410 | .unlocked_ioctl = roccat_ioctl, | ||
383 | }; | 411 | }; |
384 | 412 | ||
385 | static int __init roccat_init(void) | 413 | static int __init roccat_init(void) |