diff options
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) |
