summaryrefslogtreecommitdiff
path: root/drivers/hid/hid-roccat-koneplus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-roccat-koneplus.c')
-rw-r--r--drivers/hid/hid-roccat-koneplus.c167
1 files changed, 58 insertions, 109 deletions
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index 1608c8d1efd6..33eec74e0615 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -19,11 +19,11 @@
#include <linux/device.h>
#include <linux/input.h>
#include <linux/hid.h>
-#include <linux/usb.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/hid-roccat.h>
#include "hid-ids.h"
-#include "hid-roccat.h"
+#include "hid-roccat-common.h"
#include "hid-roccat-koneplus.h"
static uint profile_numbers[5] = {0, 1, 2, 3, 4};
@@ -39,110 +39,63 @@ static void koneplus_profile_activated(struct koneplus_device *koneplus,
static int koneplus_send_control(struct usb_device *usb_dev, uint value,
enum koneplus_control_requests request)
{
- int len;
- struct koneplus_control *control;
+ struct koneplus_control control;
if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
value > 4)
return -EINVAL;
- control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
- if (!control)
- return -ENOMEM;
+ control.command = KONEPLUS_COMMAND_CONTROL;
+ control.value = value;
+ control.request = request;
- control->command = KONEPLUS_COMMAND_CONTROL;
- control->value = value;
- control->request = request;
-
- len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
- USB_REQ_SET_CONFIGURATION,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
- KONEPLUS_USB_COMMAND_CONTROL, 0, control,
- sizeof(struct koneplus_control),
- USB_CTRL_SET_TIMEOUT);
-
- kfree(control);
-
- if (len != sizeof(struct koneplus_control))
- return len;
-
- return 0;
-}
-
-static int koneplus_receive(struct usb_device *usb_dev, uint usb_command,
- void *buf, uint size) {
- int len;
-
- len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
- USB_REQ_CLEAR_FEATURE,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
- usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
-
- return (len != size) ? -EIO : 0;
+ return roccat_common_send(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
+ &control, sizeof(struct koneplus_control));
}
static int koneplus_receive_control_status(struct usb_device *usb_dev)
{
int retval;
- struct koneplus_control *control;
-
- control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
- if (!control)
- return -ENOMEM;
+ struct koneplus_control control;
do {
- retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
- control, sizeof(struct koneplus_control));
+ retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
+ &control, sizeof(struct koneplus_control));
/* check if we get a completely wrong answer */
if (retval)
- goto out;
+ return retval;
- if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) {
- retval = 0;
- goto out;
- }
+ if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OK)
+ return 0;
/* indicates that hardware needs some more time to complete action */
- if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) {
+ if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) {
msleep(500); /* windows driver uses 1000 */
continue;
}
/* seems to be critical - replug necessary */
- if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) {
- retval = -EINVAL;
- goto out;
- }
-
- dev_err(&usb_dev->dev, "koneplus_receive_control_status: "
- "unknown response value 0x%x\n", control->value);
- retval = -EINVAL;
- goto out;
+ if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD)
+ return -EINVAL;
+ hid_err(usb_dev, "koneplus_receive_control_status: "
+ "unknown response value 0x%x\n", control.value);
+ return -EINVAL;
} while (1);
-out:
- kfree(control);
- return retval;
}
static int koneplus_send(struct usb_device *usb_dev, uint command,
- void *buf, uint size) {
- int len;
-
- len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
- USB_REQ_SET_CONFIGURATION,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
- command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
-
- if (len != size)
- return -EIO;
+ void const *buf, uint size)
+{
+ int retval;
- if (koneplus_receive_control_status(usb_dev))
- return -EIO;
+ retval = roccat_common_send(usb_dev, command, buf, size);
+ if (retval)
+ return retval;
- return 0;
+ return koneplus_receive_control_status(usb_dev);
}
static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
@@ -167,7 +120,7 @@ static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
static int koneplus_get_info(struct usb_device *usb_dev,
struct koneplus_info *buf)
{
- return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
+ return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
buf, sizeof(struct koneplus_info));
}
@@ -181,7 +134,7 @@ static int koneplus_get_profile_settings(struct usb_device *usb_dev,
if (retval)
return retval;
- return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
+ return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
buf, sizeof(struct koneplus_profile_settings));
}
@@ -189,7 +142,7 @@ static int koneplus_set_profile_settings(struct usb_device *usb_dev,
struct koneplus_profile_settings const *settings)
{
return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
- (void *)settings, sizeof(struct koneplus_profile_settings));
+ settings, sizeof(struct koneplus_profile_settings));
}
static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
@@ -202,7 +155,7 @@ static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
if (retval)
return retval;
- return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
+ return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
buf, sizeof(struct koneplus_profile_buttons));
}
@@ -210,27 +163,19 @@ static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
struct koneplus_profile_buttons const *buttons)
{
return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
- (void *)buttons, sizeof(struct koneplus_profile_buttons));
+ buttons, sizeof(struct koneplus_profile_buttons));
}
/* retval is 0-4 on success, < 0 on error */
static int koneplus_get_startup_profile(struct usb_device *usb_dev)
{
- struct koneplus_startup_profile *buf;
+ struct koneplus_startup_profile buf;
int retval;
- buf = kmalloc(sizeof(struct koneplus_startup_profile), GFP_KERNEL);
+ retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
+ &buf, sizeof(struct koneplus_startup_profile));
- retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
- buf, sizeof(struct koneplus_startup_profile));
-
- if (retval)
- goto out;
-
- retval = buf->startup_profile;
-out:
- kfree(buf);
- return retval;
+ return retval ? retval : buf.startup_profile;
}
static int koneplus_set_startup_profile(struct usb_device *usb_dev,
@@ -243,7 +188,7 @@ static int koneplus_set_startup_profile(struct usb_device *usb_dev,
buf.startup_profile = startup_profile;
return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
- (char *)&buf, sizeof(struct koneplus_profile_buttons));
+ &buf, sizeof(struct koneplus_profile_buttons));
}
static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
@@ -256,11 +201,14 @@ static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
+ if (off >= real_size)
+ return 0;
+
if (off != 0 || count != real_size)
return -EINVAL;
mutex_lock(&koneplus->koneplus_lock);
- retval = koneplus_receive(usb_dev, command, buf, real_size);
+ retval = roccat_common_receive(usb_dev, command, buf, real_size);
mutex_unlock(&koneplus->koneplus_lock);
if (retval)
@@ -283,7 +231,7 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
return -EINVAL;
mutex_lock(&koneplus->koneplus_lock);
- retval = koneplus_send(usb_dev, command, (void *)buf, real_size);
+ retval = koneplus_send(usb_dev, command, buf, real_size);
mutex_unlock(&koneplus->koneplus_lock);
if (retval)
@@ -347,7 +295,7 @@ static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
count = sizeof(struct koneplus_profile_settings) - off;
mutex_lock(&koneplus->koneplus_lock);
- memcpy(buf, ((void const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
+ memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
count);
mutex_unlock(&koneplus->koneplus_lock);
@@ -406,7 +354,7 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
count = sizeof(struct koneplus_profile_buttons) - off;
mutex_lock(&koneplus->koneplus_lock);
- memcpy(buf, ((void const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
+ memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
count);
mutex_unlock(&koneplus->koneplus_lock);
@@ -512,7 +460,7 @@ static struct device_attribute koneplus_attributes[] = {
static struct bin_attribute koneplus_bin_attributes[] = {
{
- .attr = { .name = "sensor", .mode = 0220 },
+ .attr = { .name = "sensor", .mode = 0660 },
.size = sizeof(struct koneplus_sensor),
.read = koneplus_sysfs_read_sensor,
.write = koneplus_sysfs_write_sensor
@@ -609,11 +557,13 @@ static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
struct koneplus_device *koneplus)
{
int retval, i;
- static uint wait = 70; /* device will freeze with just 60 */
+ static uint wait = 100; /* device will freeze with just 60 */
mutex_init(&koneplus->koneplus_lock);
koneplus->startup_profile = koneplus_get_startup_profile(usb_dev);
+ if (koneplus->startup_profile < 0)
+ return koneplus->startup_profile;
msleep(wait);
retval = koneplus_get_info(usb_dev, &koneplus->info);
@@ -651,21 +601,21 @@ static int koneplus_init_specials(struct hid_device *hdev)
koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL);
if (!koneplus) {
- dev_err(&hdev->dev, "can't alloc device descriptor\n");
+ hid_err(hdev, "can't alloc device descriptor\n");
return -ENOMEM;
}
hid_set_drvdata(hdev, koneplus);
retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus);
if (retval) {
- dev_err(&hdev->dev,
- "couldn't init struct koneplus_device\n");
+ hid_err(hdev, "couldn't init struct koneplus_device\n");
goto exit_free;
}
- retval = roccat_connect(koneplus_class, hdev);
+ retval = roccat_connect(koneplus_class, hdev,
+ sizeof(struct koneplus_roccat_report));
if (retval < 0) {
- dev_err(&hdev->dev, "couldn't init char dev\n");
+ hid_err(hdev, "couldn't init char dev\n");
} else {
koneplus->chrdev_minor = retval;
koneplus->roccat_claimed = 1;
@@ -701,19 +651,19 @@ static int koneplus_probe(struct hid_device *hdev,
retval = hid_parse(hdev);
if (retval) {
- dev_err(&hdev->dev, "parse failed\n");
+ hid_err(hdev, "parse failed\n");
goto exit;
}
retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (retval) {
- dev_err(&hdev->dev, "hw start failed\n");
+ hid_err(hdev, "hw start failed\n");
goto exit;
}
retval = koneplus_init_specials(hdev);
if (retval) {
- dev_err(&hdev->dev, "couldn't install mouse\n");
+ hid_err(hdev, "couldn't install mouse\n");
goto exit_stop;
}
@@ -769,8 +719,7 @@ static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus,
roccat_report.data2 = button_report->data2;
roccat_report.profile = koneplus->actual_profile + 1;
roccat_report_event(koneplus->chrdev_minor,
- (uint8_t const *)&roccat_report,
- sizeof(struct koneplus_roccat_report));
+ (uint8_t const *)&roccat_report);
}
static int koneplus_raw_event(struct hid_device *hdev,
@@ -825,8 +774,8 @@ static int __init koneplus_init(void)
static void __exit koneplus_exit(void)
{
- class_destroy(koneplus_class);
hid_unregister_driver(&koneplus_driver);
+ class_destroy(koneplus_class);
}
module_init(koneplus_init);