|
@@ -26,8 +26,7 @@
|
|
|
#include <linux/cdev.h>
|
|
|
#include <linux/poll.h>
|
|
|
#include <linux/sched.h>
|
|
|
-
|
|
|
-#include "hid-roccat.h"
|
|
|
+#include <linux/roccat.h>
|
|
|
|
|
|
#define ROCCAT_FIRST_MINOR 0
|
|
|
#define ROCCAT_MAX_DEVICES 8
|
|
@@ -37,11 +36,11 @@
|
|
|
|
|
|
struct roccat_report {
|
|
|
uint8_t *value;
|
|
|
- int len;
|
|
|
};
|
|
|
|
|
|
struct roccat_device {
|
|
|
unsigned int minor;
|
|
|
+ int report_size;
|
|
|
int open;
|
|
|
int exist;
|
|
|
wait_queue_head_t wait;
|
|
@@ -123,7 +122,7 @@ static ssize_t roccat_read(struct file *file, char __user *buffer,
|
|
|
* If report is larger than requested amount of data, rest of report
|
|
|
* is lost!
|
|
|
*/
|
|
|
- len = report->len > count ? count : report->len;
|
|
|
+ len = device->report_size > count ? count : device->report_size;
|
|
|
|
|
|
if (copy_to_user(buffer, report->value, len)) {
|
|
|
retval = -EFAULT;
|
|
@@ -248,26 +247,25 @@ static int roccat_release(struct inode *inode, struct file *file)
|
|
|
*
|
|
|
* This is called from interrupt handler.
|
|
|
*/
|
|
|
-int roccat_report_event(int minor, u8 const *data, int len)
|
|
|
+int roccat_report_event(int minor, u8 const *data)
|
|
|
{
|
|
|
struct roccat_device *device;
|
|
|
struct roccat_reader *reader;
|
|
|
struct roccat_report *report;
|
|
|
uint8_t *new_value;
|
|
|
|
|
|
- new_value = kmemdup(data, len, GFP_ATOMIC);
|
|
|
+ device = devices[minor];
|
|
|
+
|
|
|
+ new_value = kmemdup(data, device->report_size, GFP_ATOMIC);
|
|
|
if (!new_value)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- device = devices[minor];
|
|
|
-
|
|
|
report = &device->cbuf[device->cbuf_end];
|
|
|
|
|
|
/* passing NULL is safe */
|
|
|
kfree(report->value);
|
|
|
|
|
|
report->value = new_value;
|
|
|
- report->len = len;
|
|
|
device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE;
|
|
|
|
|
|
list_for_each_entry(reader, &device->readers, node) {
|
|
@@ -295,7 +293,7 @@ EXPORT_SYMBOL_GPL(roccat_report_event);
|
|
|
* Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on
|
|
|
* success, a negative error code on failure.
|
|
|
*/
|
|
|
-int roccat_connect(struct class *klass, struct hid_device *hid)
|
|
|
+int roccat_connect(struct class *klass, struct hid_device *hid, int report_size)
|
|
|
{
|
|
|
unsigned int minor;
|
|
|
struct roccat_device *device;
|
|
@@ -343,6 +341,7 @@ int roccat_connect(struct class *klass, struct hid_device *hid)
|
|
|
device->hid = hid;
|
|
|
device->exist = 1;
|
|
|
device->cbuf_end = 0;
|
|
|
+ device->report_size = report_size;
|
|
|
|
|
|
return minor;
|
|
|
}
|
|
@@ -373,6 +372,34 @@ void roccat_disconnect(int minor)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(roccat_disconnect);
|
|
|
|
|
|
+static long roccat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
|
+{
|
|
|
+ struct inode *inode = file->f_path.dentry->d_inode;
|
|
|
+ struct roccat_device *device;
|
|
|
+ unsigned int minor = iminor(inode);
|
|
|
+ long retval = 0;
|
|
|
+
|
|
|
+ mutex_lock(&devices_lock);
|
|
|
+
|
|
|
+ device = devices[minor];
|
|
|
+ if (!device) {
|
|
|
+ retval = -ENODEV;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (cmd) {
|
|
|
+ case ROCCATIOCGREPSIZE:
|
|
|
+ if (put_user(device->report_size, (int __user *)arg))
|
|
|
+ retval = -EFAULT;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ retval = -ENOTTY;
|
|
|
+ }
|
|
|
+out:
|
|
|
+ mutex_unlock(&devices_lock);
|
|
|
+ return retval;
|
|
|
+}
|
|
|
+
|
|
|
static const struct file_operations roccat_ops = {
|
|
|
.owner = THIS_MODULE,
|
|
|
.read = roccat_read,
|
|
@@ -380,6 +407,7 @@ static const struct file_operations roccat_ops = {
|
|
|
.open = roccat_open,
|
|
|
.release = roccat_release,
|
|
|
.llseek = noop_llseek,
|
|
|
+ .unlocked_ioctl = roccat_ioctl,
|
|
|
};
|
|
|
|
|
|
static int __init roccat_init(void)
|