aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-roccat.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-roccat.c')
-rw-r--r--drivers/hid/hid-roccat.c53
1 files changed, 42 insertions, 11 deletions
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index a14c579ea781..5666e7587b18 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/hid-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
38struct roccat_report { 37struct roccat_report {
39 uint8_t *value; 38 uint8_t *value;
40 int len;
41}; 39};
42 40
43struct roccat_device { 41struct 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 */
251int roccat_report_event(int minor, u8 const *data, int len) 250int 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 */
298int roccat_connect(struct class *klass, struct hid_device *hid) 296int 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}
@@ -357,13 +356,16 @@ void roccat_disconnect(int minor)
357 356
358 mutex_lock(&devices_lock); 357 mutex_lock(&devices_lock);
359 device = devices[minor]; 358 device = devices[minor];
360 devices[minor] = NULL;
361 mutex_unlock(&devices_lock); 359 mutex_unlock(&devices_lock);
362 360
363 device->exist = 0; /* TODO exist maybe not needed */ 361 device->exist = 0; /* TODO exist maybe not needed */
364 362
365 device_destroy(device->dev->class, MKDEV(roccat_major, minor)); 363 device_destroy(device->dev->class, MKDEV(roccat_major, minor));
366 364
365 mutex_lock(&devices_lock);
366 devices[minor] = NULL;
367 mutex_unlock(&devices_lock);
368
367 if (device->open) { 369 if (device->open) {
368 hid_hw_close(device->hid); 370 hid_hw_close(device->hid);
369 wake_up_interruptible(&device->wait); 371 wake_up_interruptible(&device->wait);
@@ -373,6 +375,34 @@ void roccat_disconnect(int minor)
373} 375}
374EXPORT_SYMBOL_GPL(roccat_disconnect); 376EXPORT_SYMBOL_GPL(roccat_disconnect);
375 377
378static long roccat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
379{
380 struct inode *inode = file->f_path.dentry->d_inode;
381 struct roccat_device *device;
382 unsigned int minor = iminor(inode);
383 long retval = 0;
384
385 mutex_lock(&devices_lock);
386
387 device = devices[minor];
388 if (!device) {
389 retval = -ENODEV;
390 goto out;
391 }
392
393 switch (cmd) {
394 case ROCCATIOCGREPSIZE:
395 if (put_user(device->report_size, (int __user *)arg))
396 retval = -EFAULT;
397 break;
398 default:
399 retval = -ENOTTY;
400 }
401out:
402 mutex_unlock(&devices_lock);
403 return retval;
404}
405
376static const struct file_operations roccat_ops = { 406static const struct file_operations roccat_ops = {
377 .owner = THIS_MODULE, 407 .owner = THIS_MODULE,
378 .read = roccat_read, 408 .read = roccat_read,
@@ -380,6 +410,7 @@ static const struct file_operations roccat_ops = {
380 .open = roccat_open, 410 .open = roccat_open,
381 .release = roccat_release, 411 .release = roccat_release,
382 .llseek = noop_llseek, 412 .llseek = noop_llseek,
413 .unlocked_ioctl = roccat_ioctl,
383}; 414};
384 415
385static int __init roccat_init(void) 416static int __init roccat_init(void)