From e68cc603b063416c85f3e408184219fb71d4a9ff Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Thu, 6 Jan 2011 09:00:34 +0100 Subject: HID: roccat: Add support for Roccat Arvo keyboard This patch add support for Roccat Arvo keyboard. Arvo has 5 additional configurable buttons and the ability to deactivate certain keys. Userland tools can soon be found at http://sourceforge.net/projects/roccat Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina --- .../ABI/testing/sysfs-driver-hid-roccat-arvo | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo b/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo new file mode 100644 index 000000000000..d54827d98afd --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo @@ -0,0 +1,48 @@ +What: /sys/bus/usb/devices/-:./::./arvo/roccatarvo/actual_profile +Date: Januar 2011 +Contact: Stefan Achatz +Description: The integer value of this attribute ranges from 1-5. + When read, this attribute returns the number of the actual + profile which is also the profile that's active on device startup. + When written this attribute activates the selected profile + immediately. + +What: /sys/bus/usb/devices/-:./::./arvo/roccatarvo/button +Date: Januar 2011 +Contact: Stefan Achatz +Description: The keyboard can store short macros with consist of 1 button with + several modifier keys internally. + When written, this file lets one set the sequence for a specific + button for a specific profile. Button and profile numbers are + included in written data. The data has to be 24 bytes long. + This file is writeonly. + +What: /sys/bus/usb/devices/-:./::./arvo/roccatarvo/info +Date: Januar 2011 +Contact: Stefan Achatz +Description: When read, this file returns some info about the device like the + installed firmware version. + The size of the data is 8 bytes in size. + This file is readonly. + +What: /sys/bus/usb/devices/-:./::./arvo/roccatarvo/key_mask +Date: Januar 2011 +Contact: Stefan Achatz +Description: The keyboard lets the user deactivate 5 certain keys like the + windows and application keys, to protect the user from the outcome + of accidentally pressing them. + The integer value of this attribute has bits 0-4 set depending + on the state of the corresponding key. + When read, this file returns the current state of the buttons. + When written, the given buttons are activated/deactivated + immediately. + +What: /sys/bus/usb/devices/-:./::./arvo/roccatarvo/mode_key +Date: Januar 2011 +Contact: Stefan Achatz +Description: The keyboard has a condensed layout without num-lock key. + Instead it uses a mode-key which activates a gaming mode where + the assignment of the number block changes. + The integer value of this attribute ranges from 0 (OFF) to 1 (ON). + When read, this file returns the actual state of the key. + When written, the key is activated/deactivated immediately. \ No newline at end of file -- cgit v1.2.3 From 0e70f97f257edcef4daa92ab9371a9aac0c851ed Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Sun, 30 Jan 2011 13:38:24 +0100 Subject: HID: roccat: Add support for Kova[+] mouse This patch adds support for Roccat Kova[+] mouse. Userland tools can soon be found at http://sourceforge.net/projects/roccat Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina --- .../ABI/testing/sysfs-driver-hid-roccat-kovaplus | 91 +++ drivers/hid/Kconfig | 8 + drivers/hid/Makefile | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-roccat-kovaplus.c | 715 +++++++++++++++++++++ drivers/hid/hid-roccat-kovaplus.h | 157 +++++ 7 files changed, 974 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus create mode 100644 drivers/hid/hid-roccat-kovaplus.c create mode 100644 drivers/hid/hid-roccat-kovaplus.h (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus new file mode 100644 index 000000000000..9e54af4c8fc0 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus @@ -0,0 +1,91 @@ +What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/actual_cpi +Date: January 2011 +Contact: Stefan Achatz +Description: The integer value of this attribute ranges from 1-4. + When read, this attribute returns the number of the active + cpi level. + This file is readonly. + +What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/actual_profile +Date: January 2011 +Contact: Stefan Achatz +Description: The integer value of this attribute ranges from 0-4. + When read, this attribute returns the number of the active + profile. + When written, the mouse activates this profile immediately. + The profile that's active when powered down is the same that's + active when the mouse is powered on. + +What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/actual_sensitivity_x +Date: January 2011 +Contact: Stefan Achatz +Description: The integer value of this attribute ranges from 1-10. + When read, this attribute returns the number of the actual + sensitivity in x direction. + This file is readonly. + +What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/actual_sensitivity_y +Date: January 2011 +Contact: Stefan Achatz +Description: The integer value of this attribute ranges from 1-10. + When read, this attribute returns the number of the actual + sensitivity in y direction. + This file is readonly. + +What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/firmware_version +Date: January 2011 +Contact: Stefan Achatz +Description: When read, this file returns the raw integer version number of the + firmware reported by the mouse. Using the integer value eases + further usage in other programs. To receive the real version + number the decimal point has to be shifted 2 positions to the + left. E.g. a returned value of 121 means 1.21 + This file is readonly. + +What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/profile_buttons +Date: January 2011 +Contact: Stefan Achatz +Description: The mouse can store 5 profiles which can be switched by the + press of a button. A profile is split in settings and buttons. + profile_buttons holds informations about button layout. + When written, this file lets one write the respective profile + buttons back to the mouse. The data has to be 23 bytes long. + The mouse will reject invalid data. + Which profile to write is determined by the profile number + contained in the data. + This file is writeonly. + +What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/profile[1-5]_buttons +Date: January 2011 +Contact: Stefan Achatz +Description: The mouse can store 5 profiles which can be switched by the + press of a button. A profile is split in settings and buttons. + profile_buttons holds informations about button layout. + When read, these files return the respective profile buttons. + The returned data is 23 bytes in size. + This file is readonly. + +What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/profile_settings +Date: January 2011 +Contact: Stefan Achatz +Description: The mouse can store 5 profiles which can be switched by the + press of a button. A profile is split in settings and buttons. + profile_settings holds informations like resolution, sensitivity + and light effects. + When written, this file lets one write the respective profile + settings back to the mouse. The data has to be 16 bytes long. + The mouse will reject invalid data. + Which profile to write is determined by the profile number + contained in the data. + This file is writeonly. + +What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/profile[1-5]_settings +Date: January 2011 +Contact: Stefan Achatz +Description: The mouse can store 5 profiles which can be switched by the + press of a button. A profile is split in settings and buttons. + profile_settings holds informations like resolution, sensitivity + and light effects. + When read, these files return the respective profile settings. + The returned data is 16 bytes in size. + This file is readonly. diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 795236963066..022515fdd6fe 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -444,6 +444,14 @@ config HID_ROCCAT_KONEPLUS ---help--- Support for Roccat Kone[+] mouse. +config HID_ROCCAT_KOVAPLUS + tristate "Roccat Kova[+] mouse support" + depends on USB_HID + select HID_ROCCAT + select HID_ROCCAT_COMMON + ---help--- + Support for Roccat Kova[+] mouse. + config HID_ROCCAT_PYRA tristate "Roccat Pyra mouse support" depends on USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 086cf62184eb..cb80181da905 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_HID_ROCCAT_COMMON) += hid-roccat-common.o obj-$(CONFIG_HID_ROCCAT_ARVO) += hid-roccat-arvo.o obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o obj-$(CONFIG_HID_ROCCAT_KONEPLUS) += hid-roccat-koneplus.o +obj-$(CONFIG_HID_ROCCAT_KOVAPLUS) += hid-roccat-kovaplus.o obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 6178025a95f6..0180f20d4fa7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1407,6 +1407,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 92e0fa1856c6..75f2e1430a55 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -499,6 +499,7 @@ #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced #define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 +#define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c new file mode 100644 index 000000000000..1f547a2b39de --- /dev/null +++ b/drivers/hid/hid-roccat-kovaplus.c @@ -0,0 +1,715 @@ +/* + * Roccat Kova[+] driver for Linux + * + * Copyright (c) 2011 Stefan Achatz + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/* + * Roccat Kova[+] is a bigger version of the Pyra with two more side buttons. + */ + +#include +#include +#include +#include +#include +#include "hid-ids.h" +#include "hid-roccat.h" +#include "hid-roccat-common.h" +#include "hid-roccat-kovaplus.h" + +static uint profile_numbers[5] = {0, 1, 2, 3, 4}; + +static struct class *kovaplus_class; + +static uint kovaplus_convert_event_cpi(uint value) +{ + return (value == 7 ? 4 : (value == 4 ? 3 : value)); +} + +static void kovaplus_profile_activated(struct kovaplus_device *kovaplus, + uint new_profile_index) +{ + kovaplus->actual_profile = new_profile_index; + kovaplus->actual_cpi = kovaplus->profile_settings[new_profile_index].cpi_startup_level; + kovaplus->actual_x_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_x; + kovaplus->actual_y_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_y; +} + +static int kovaplus_send_control(struct usb_device *usb_dev, uint value, + enum kovaplus_control_requests request) +{ + int retval; + struct kovaplus_control control; + + if ((request == KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || + request == KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && + value > 4) + return -EINVAL; + + control.command = KOVAPLUS_COMMAND_CONTROL; + control.value = value; + control.request = request; + + retval = roccat_common_send(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL, + &control, sizeof(struct kovaplus_control)); + + return retval; +} + +static int kovaplus_receive_control_status(struct usb_device *usb_dev) +{ + int retval; + struct kovaplus_control control; + + do { + retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL, + &control, sizeof(struct kovaplus_control)); + + /* check if we get a completely wrong answer */ + if (retval) + return retval; + + if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OK) + return 0; + + /* indicates that hardware needs some more time to complete action */ + if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT) { + msleep(500); /* windows driver uses 1000 */ + continue; + } + + /* seems to be critical - replug necessary */ + if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) + return -EINVAL; + + hid_err(usb_dev, "kovaplus_receive_control_status: " + "unknown response value 0x%x\n", control.value); + return -EINVAL; + } while (1); +} + +static int kovaplus_send(struct usb_device *usb_dev, uint command, + void const *buf, uint size) +{ + int retval; + + retval = roccat_common_send(usb_dev, command, buf, size); + if (retval) + return retval; + + msleep(100); + + return kovaplus_receive_control_status(usb_dev); +} + +static int kovaplus_select_profile(struct usb_device *usb_dev, uint number, + enum kovaplus_control_requests request) +{ + return kovaplus_send_control(usb_dev, number, request); +} + +static int kovaplus_get_info(struct usb_device *usb_dev, + struct kovaplus_info *buf) +{ + return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_INFO, + buf, sizeof(struct kovaplus_info)); +} + +static int kovaplus_get_profile_settings(struct usb_device *usb_dev, + struct kovaplus_profile_settings *buf, uint number) +{ + int retval; + + retval = kovaplus_select_profile(usb_dev, number, + KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); + if (retval) + return retval; + + return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS, + buf, sizeof(struct kovaplus_profile_settings)); +} + +static int kovaplus_set_profile_settings(struct usb_device *usb_dev, + struct kovaplus_profile_settings const *settings) +{ + return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS, + settings, sizeof(struct kovaplus_profile_settings)); +} + +static int kovaplus_get_profile_buttons(struct usb_device *usb_dev, + struct kovaplus_profile_buttons *buf, int number) +{ + int retval; + + retval = kovaplus_select_profile(usb_dev, number, + KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); + if (retval) + return retval; + + return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS, + buf, sizeof(struct kovaplus_profile_buttons)); +} + +static int kovaplus_set_profile_buttons(struct usb_device *usb_dev, + struct kovaplus_profile_buttons const *buttons) +{ + return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS, + buttons, sizeof(struct kovaplus_profile_buttons)); +} + +/* retval is 0-4 on success, < 0 on error */ +static int kovaplus_get_actual_profile(struct usb_device *usb_dev) +{ + struct kovaplus_actual_profile buf; + int retval; + + retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE, + &buf, sizeof(struct kovaplus_actual_profile)); + + return retval ? retval : buf.actual_profile; +} + +static int kovaplus_set_actual_profile(struct usb_device *usb_dev, + int new_profile) +{ + struct kovaplus_actual_profile buf; + + buf.command = KOVAPLUS_COMMAND_ACTUAL_PROFILE; + buf.size = sizeof(struct kovaplus_actual_profile); + buf.actual_profile = new_profile; + + return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE, + &buf, sizeof(struct kovaplus_actual_profile)); +} + +static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); + + if (off >= sizeof(struct kovaplus_profile_settings)) + return 0; + + if (off + count > sizeof(struct kovaplus_profile_settings)) + count = sizeof(struct kovaplus_profile_settings) - off; + + mutex_lock(&kovaplus->kovaplus_lock); + memcpy(buf, ((char const *)&kovaplus->profile_settings[*(uint *)(attr->private)]) + off, + count); + mutex_unlock(&kovaplus->kovaplus_lock); + + return count; +} + +static ssize_t kovaplus_sysfs_write_profile_settings(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); + int retval = 0; + int difference; + int profile_index; + struct kovaplus_profile_settings *profile_settings; + + if (off != 0 || count != sizeof(struct kovaplus_profile_settings)) + return -EINVAL; + + profile_index = ((struct kovaplus_profile_settings const *)buf)->profile_index; + profile_settings = &kovaplus->profile_settings[profile_index]; + + mutex_lock(&kovaplus->kovaplus_lock); + difference = memcmp(buf, profile_settings, + sizeof(struct kovaplus_profile_settings)); + if (difference) { + retval = kovaplus_set_profile_settings(usb_dev, + (struct kovaplus_profile_settings const *)buf); + if (!retval) + memcpy(profile_settings, buf, + sizeof(struct kovaplus_profile_settings)); + } + mutex_unlock(&kovaplus->kovaplus_lock); + + if (retval) + return retval; + + return sizeof(struct kovaplus_profile_settings); +} + +static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); + + if (off >= sizeof(struct kovaplus_profile_buttons)) + return 0; + + if (off + count > sizeof(struct kovaplus_profile_buttons)) + count = sizeof(struct kovaplus_profile_buttons) - off; + + mutex_lock(&kovaplus->kovaplus_lock); + memcpy(buf, ((char const *)&kovaplus->profile_buttons[*(uint *)(attr->private)]) + off, + count); + mutex_unlock(&kovaplus->kovaplus_lock); + + return count; +} + +static ssize_t kovaplus_sysfs_write_profile_buttons(struct file *fp, + struct kobject *kobj, struct bin_attribute *attr, char *buf, + loff_t off, size_t count) +{ + struct device *dev = + container_of(kobj, struct device, kobj)->parent->parent; + struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); + int retval = 0; + int difference; + uint profile_index; + struct kovaplus_profile_buttons *profile_buttons; + + if (off != 0 || count != sizeof(struct kovaplus_profile_buttons)) + return -EINVAL; + + profile_index = ((struct kovaplus_profile_buttons const *)buf)->profile_index; + profile_buttons = &kovaplus->profile_buttons[profile_index]; + + mutex_lock(&kovaplus->kovaplus_lock); + difference = memcmp(buf, profile_buttons, + sizeof(struct kovaplus_profile_buttons)); + if (difference) { + retval = kovaplus_set_profile_buttons(usb_dev, + (struct kovaplus_profile_buttons const *)buf); + if (!retval) + memcpy(profile_buttons, buf, + sizeof(struct kovaplus_profile_buttons)); + } + mutex_unlock(&kovaplus->kovaplus_lock); + + if (retval) + return retval; + + return sizeof(struct kovaplus_profile_buttons); +} + +static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kovaplus_device *kovaplus = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); + return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_profile); +} + +static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev, + struct device_attribute *attr, char const *buf, size_t size) +{ + struct kovaplus_device *kovaplus; + struct usb_device *usb_dev; + unsigned long profile; + int retval; + + dev = dev->parent->parent; + kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); + usb_dev = interface_to_usbdev(to_usb_interface(dev)); + + retval = strict_strtoul(buf, 10, &profile); + if (retval) + return retval; + + if (profile >= 5) + return -EINVAL; + + mutex_lock(&kovaplus->kovaplus_lock); + retval = kovaplus_set_actual_profile(usb_dev, profile); + kovaplus->actual_profile = profile; + mutex_unlock(&kovaplus->kovaplus_lock); + if (retval) + return retval; + + return size; +} + +static ssize_t kovaplus_sysfs_show_actual_cpi(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kovaplus_device *kovaplus = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); + return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_cpi); +} + +static ssize_t kovaplus_sysfs_show_actual_sensitivity_x(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kovaplus_device *kovaplus = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); + return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_x_sensitivity); +} + +static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kovaplus_device *kovaplus = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); + return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_y_sensitivity); +} + +static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kovaplus_device *kovaplus = + hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); + return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->info.firmware_version); +} + +static struct device_attribute kovaplus_attributes[] = { + __ATTR(actual_cpi, 0440, + kovaplus_sysfs_show_actual_cpi, NULL), + __ATTR(firmware_version, 0440, + kovaplus_sysfs_show_firmware_version, NULL), + __ATTR(actual_profile, 0660, + kovaplus_sysfs_show_actual_profile, + kovaplus_sysfs_set_actual_profile), + __ATTR(actual_sensitivity_x, 0440, + kovaplus_sysfs_show_actual_sensitivity_x, NULL), + __ATTR(actual_sensitivity_y, 0440, + kovaplus_sysfs_show_actual_sensitivity_y, NULL), + __ATTR_NULL +}; + +static struct bin_attribute kovaplus_bin_attributes[] = { + { + .attr = { .name = "profile_settings", .mode = 0220 }, + .size = sizeof(struct kovaplus_profile_settings), + .write = kovaplus_sysfs_write_profile_settings + }, + { + .attr = { .name = "profile1_settings", .mode = 0440 }, + .size = sizeof(struct kovaplus_profile_settings), + .read = kovaplus_sysfs_read_profilex_settings, + .private = &profile_numbers[0] + }, + { + .attr = { .name = "profile2_settings", .mode = 0440 }, + .size = sizeof(struct kovaplus_profile_settings), + .read = kovaplus_sysfs_read_profilex_settings, + .private = &profile_numbers[1] + }, + { + .attr = { .name = "profile3_settings", .mode = 0440 }, + .size = sizeof(struct kovaplus_profile_settings), + .read = kovaplus_sysfs_read_profilex_settings, + .private = &profile_numbers[2] + }, + { + .attr = { .name = "profile4_settings", .mode = 0440 }, + .size = sizeof(struct kovaplus_profile_settings), + .read = kovaplus_sysfs_read_profilex_settings, + .private = &profile_numbers[3] + }, + { + .attr = { .name = "profile5_settings", .mode = 0440 }, + .size = sizeof(struct kovaplus_profile_settings), + .read = kovaplus_sysfs_read_profilex_settings, + .private = &profile_numbers[4] + }, + { + .attr = { .name = "profile_buttons", .mode = 0220 }, + .size = sizeof(struct kovaplus_profile_buttons), + .write = kovaplus_sysfs_write_profile_buttons + }, + { + .attr = { .name = "profile1_buttons", .mode = 0440 }, + .size = sizeof(struct kovaplus_profile_buttons), + .read = kovaplus_sysfs_read_profilex_buttons, + .private = &profile_numbers[0] + }, + { + .attr = { .name = "profile2_buttons", .mode = 0440 }, + .size = sizeof(struct kovaplus_profile_buttons), + .read = kovaplus_sysfs_read_profilex_buttons, + .private = &profile_numbers[1] + }, + { + .attr = { .name = "profile3_buttons", .mode = 0440 }, + .size = sizeof(struct kovaplus_profile_buttons), + .read = kovaplus_sysfs_read_profilex_buttons, + .private = &profile_numbers[2] + }, + { + .attr = { .name = "profile4_buttons", .mode = 0440 }, + .size = sizeof(struct kovaplus_profile_buttons), + .read = kovaplus_sysfs_read_profilex_buttons, + .private = &profile_numbers[3] + }, + { + .attr = { .name = "profile5_buttons", .mode = 0440 }, + .size = sizeof(struct kovaplus_profile_buttons), + .read = kovaplus_sysfs_read_profilex_buttons, + .private = &profile_numbers[4] + }, + __ATTR_NULL +}; + +static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev, + struct kovaplus_device *kovaplus) +{ + int retval, i; + static uint wait = 70; /* device will freeze with just 60 */ + + mutex_init(&kovaplus->kovaplus_lock); + + retval = kovaplus_get_info(usb_dev, &kovaplus->info); + if (retval) + return retval; + + for (i = 0; i < 5; ++i) { + msleep(wait); + retval = kovaplus_get_profile_settings(usb_dev, + &kovaplus->profile_settings[i], i); + if (retval) + return retval; + + msleep(wait); + retval = kovaplus_get_profile_buttons(usb_dev, + &kovaplus->profile_buttons[i], i); + if (retval) + return retval; + } + + msleep(wait); + retval = kovaplus_get_actual_profile(usb_dev); + if (retval < 0) + return retval; + kovaplus_profile_activated(kovaplus, retval); + + return 0; +} + +static int kovaplus_init_specials(struct hid_device *hdev) +{ + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + struct usb_device *usb_dev = interface_to_usbdev(intf); + struct kovaplus_device *kovaplus; + int retval; + + if (intf->cur_altsetting->desc.bInterfaceProtocol + == USB_INTERFACE_PROTOCOL_MOUSE) { + + kovaplus = kzalloc(sizeof(*kovaplus), GFP_KERNEL); + if (!kovaplus) { + hid_err(hdev, "can't alloc device descriptor\n"); + return -ENOMEM; + } + hid_set_drvdata(hdev, kovaplus); + + retval = kovaplus_init_kovaplus_device_struct(usb_dev, kovaplus); + if (retval) { + hid_err(hdev, "couldn't init struct kovaplus_device\n"); + goto exit_free; + } + + retval = roccat_connect(kovaplus_class, hdev); + if (retval < 0) { + hid_err(hdev, "couldn't init char dev\n"); + } else { + kovaplus->chrdev_minor = retval; + kovaplus->roccat_claimed = 1; + } + + } else { + hid_set_drvdata(hdev, NULL); + } + + return 0; +exit_free: + kfree(kovaplus); + return retval; +} + +static void kovaplus_remove_specials(struct hid_device *hdev) +{ + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + struct kovaplus_device *kovaplus; + + if (intf->cur_altsetting->desc.bInterfaceProtocol + == USB_INTERFACE_PROTOCOL_MOUSE) { + kovaplus = hid_get_drvdata(hdev); + if (kovaplus->roccat_claimed) + roccat_disconnect(kovaplus->chrdev_minor); + kfree(kovaplus); + } +} + +static int kovaplus_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + int retval; + + retval = hid_parse(hdev); + if (retval) { + hid_err(hdev, "parse failed\n"); + goto exit; + } + + retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (retval) { + hid_err(hdev, "hw start failed\n"); + goto exit; + } + + retval = kovaplus_init_specials(hdev); + if (retval) { + hid_err(hdev, "couldn't install mouse\n"); + goto exit_stop; + } + + return 0; + +exit_stop: + hid_hw_stop(hdev); +exit: + return retval; +} + +static void kovaplus_remove(struct hid_device *hdev) +{ + kovaplus_remove_specials(hdev); + hid_hw_stop(hdev); +} + +static void kovaplus_keep_values_up_to_date(struct kovaplus_device *kovaplus, + u8 const *data) +{ + struct kovaplus_mouse_report_button const *button_report; + + if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON) + return; + + button_report = (struct kovaplus_mouse_report_button const *)data; + + switch (button_report->type) { + case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1: + kovaplus_profile_activated(kovaplus, button_report->data1 - 1); + break; + case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI: + kovaplus->actual_cpi = kovaplus_convert_event_cpi(button_report->data1); + case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY: + kovaplus->actual_x_sensitivity = button_report->data1; + kovaplus->actual_y_sensitivity = button_report->data2; + } +} + +static void kovaplus_report_to_chrdev(struct kovaplus_device const *kovaplus, + u8 const *data) +{ + struct kovaplus_roccat_report roccat_report; + struct kovaplus_mouse_report_button const *button_report; + + if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON) + return; + + button_report = (struct kovaplus_mouse_report_button const *)data; + + if (button_report->type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2) + return; + + roccat_report.type = button_report->type; + roccat_report.profile = kovaplus->actual_profile + 1; + + if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO || + roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT || + roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH || + roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) + roccat_report.button = button_report->data1; + else + roccat_report.button = 0; + + if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI) + roccat_report.data1 = kovaplus_convert_event_cpi(button_report->data1); + else + roccat_report.data1 = button_report->data1; + + roccat_report.data2 = button_report->data2; + + roccat_report_event(kovaplus->chrdev_minor, + (uint8_t const *)&roccat_report, + sizeof(struct kovaplus_roccat_report)); +} + +static int kovaplus_raw_event(struct hid_device *hdev, + struct hid_report *report, u8 *data, int size) +{ + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); + struct kovaplus_device *kovaplus = hid_get_drvdata(hdev); + + if (intf->cur_altsetting->desc.bInterfaceProtocol + != USB_INTERFACE_PROTOCOL_MOUSE) + return 0; + + kovaplus_keep_values_up_to_date(kovaplus, data); + + if (kovaplus->roccat_claimed) + kovaplus_report_to_chrdev(kovaplus, data); + + return 0; +} + +static const struct hid_device_id kovaplus_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, + { } +}; + +MODULE_DEVICE_TABLE(hid, kovaplus_devices); + +static struct hid_driver kovaplus_driver = { + .name = "kovaplus", + .id_table = kovaplus_devices, + .probe = kovaplus_probe, + .remove = kovaplus_remove, + .raw_event = kovaplus_raw_event +}; + +static int __init kovaplus_init(void) +{ + int retval; + + kovaplus_class = class_create(THIS_MODULE, "kovaplus"); + if (IS_ERR(kovaplus_class)) + return PTR_ERR(kovaplus_class); + kovaplus_class->dev_attrs = kovaplus_attributes; + kovaplus_class->dev_bin_attrs = kovaplus_bin_attributes; + + retval = hid_register_driver(&kovaplus_driver); + if (retval) + class_destroy(kovaplus_class); + return retval; +} + +static void __exit kovaplus_exit(void) +{ + class_destroy(kovaplus_class); + hid_unregister_driver(&kovaplus_driver); +} + +module_init(kovaplus_init); +module_exit(kovaplus_exit); + +MODULE_AUTHOR("Stefan Achatz"); +MODULE_DESCRIPTION("USB Roccat Kova[+] driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/hid/hid-roccat-kovaplus.h b/drivers/hid/hid-roccat-kovaplus.h new file mode 100644 index 000000000000..ce40607d21c7 --- /dev/null +++ b/drivers/hid/hid-roccat-kovaplus.h @@ -0,0 +1,157 @@ +#ifndef __HID_ROCCAT_KOVAPLUS_H +#define __HID_ROCCAT_KOVAPLUS_H + +/* + * Copyright (c) 2010 Stefan Achatz + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include + +struct kovaplus_control { + uint8_t command; /* KOVAPLUS_COMMAND_CONTROL */ + uint8_t value; + uint8_t request; +} __packed; + +enum kovaplus_control_requests { + /* read after write; value = 1 */ + KOVAPLUS_CONTROL_REQUEST_STATUS = 0x0, + /* write; value = profile number range 0-4 */ + KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, + /* write; value = profile number range 0-4 */ + KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20, +}; + +enum kovaplus_control_values { + KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0, /* supposed */ + KOVAPLUS_CONTROL_REQUEST_STATUS_OK = 1, + KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, /* supposed */ +}; + +struct kovaplus_actual_profile { + uint8_t command; /* KOVAPLUS_COMMAND_ACTUAL_PROFILE */ + uint8_t size; /* always 3 */ + uint8_t actual_profile; /* Range 0-4! */ +} __packed; + +struct kovaplus_profile_settings { + uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_SETTINGS */ + uint8_t size; /* 16 */ + uint8_t profile_index; /* range 0-4 */ + uint8_t unknown1; + uint8_t sensitivity_x; /* range 1-10 */ + uint8_t sensitivity_y; /* range 1-10 */ + uint8_t cpi_levels_enabled; + uint8_t cpi_startup_level; /* range 1-4 */ + uint8_t data[8]; +} __packed; + +struct kovaplus_profile_buttons { + uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_BUTTONS */ + uint8_t size; /* 23 */ + uint8_t profile_index; /* range 0-4 */ + uint8_t data[20]; +} __packed; + +struct kovaplus_info { + uint8_t command; /* KOVAPLUS_COMMAND_INFO */ + uint8_t size; /* 6 */ + uint8_t firmware_version; + uint8_t unknown[3]; +} __packed; + +/* writes 1 on plugin */ +struct kovaplus_a { + uint8_t command; /* KOVAPLUS_COMMAND_A */ + uint8_t size; /* 3 */ + uint8_t unknown; +} __packed; + +enum kovaplus_commands { + KOVAPLUS_COMMAND_CONTROL = 0x4, + KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5, + KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6, + KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7, + KOVAPLUS_COMMAND_INFO = 0x9, + KOVAPLUS_COMMAND_A = 0xa, +}; + +enum kovaplus_usb_commands { + KOVAPLUS_USB_COMMAND_CONTROL = 0x304, + KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305, + KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306, + KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307, + KOVAPLUS_USB_COMMAND_INFO = 0x309, + KOVAPLUS_USB_COMMAND_A = 0x30a, +}; + +enum kovaplus_mouse_report_numbers { + KOVAPLUS_MOUSE_REPORT_NUMBER_MOUSE = 1, + KOVAPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2, + KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3, + KOVAPLUS_MOUSE_REPORT_NUMBER_KBD = 4, +}; + +struct kovaplus_mouse_report_button { + uint8_t report_number; /* KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON */ + uint8_t unknown1; + uint8_t type; + uint8_t data1; + uint8_t data2; +} __packed; + +enum kovaplus_mouse_report_button_types { + /* data1 = profile_number range 1-5; no release event */ + KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1 = 0x20, + /* data1 = profile_number range 1-5; no release event */ + KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2 = 0x30, + /* data1 = button_number range 1-18; data2 = action */ + KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO = 0x40, + /* data1 = button_number range 1-18; data2 = action */ + KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT = 0x50, + /* data1 = button_number range 1-18; data2 = action */ + KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60, + /* data1 = button_number range 1-18; data2 = action */ + KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80, + /* data1 = 1 = 400, 2 = 800, 4 = 1600, 7 = 3200; no release event */ + KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0, + /* data1 + data2 = sense range 1-10; no release event */ + KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0, + /* data1 = type as in profile_buttons; data2 = action */ + KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0, +}; + +enum kovaplus_mouse_report_button_actions { + KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0, + KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1, +}; + +struct kovaplus_roccat_report { + uint8_t type; + uint8_t profile; + uint8_t button; + uint8_t data1; + uint8_t data2; +} __packed; + +struct kovaplus_device { + int actual_profile; + int actual_cpi; + int actual_x_sensitivity; + int actual_y_sensitivity; + int roccat_claimed; + int chrdev_minor; + struct mutex kovaplus_lock; + struct kovaplus_info info; + struct kovaplus_profile_settings profile_settings[5]; + struct kovaplus_profile_buttons profile_buttons[5]; +}; + +#endif -- cgit v1.2.3 From 8211e46004518c977f70f2661da961d5ba617399 Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Sun, 30 Jan 2011 13:38:25 +0100 Subject: 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 Signed-off-by: Jiri Kosina --- Documentation/ioctl/ioctl-number.txt | 1 + drivers/hid/hid-roccat-arvo.c | 9 ++++--- drivers/hid/hid-roccat-kone.c | 11 ++++----- drivers/hid/hid-roccat-koneplus.c | 8 +++--- drivers/hid/hid-roccat-kovaplus.c | 8 +++--- drivers/hid/hid-roccat-pyra.c | 11 ++++----- drivers/hid/hid-roccat.c | 48 ++++++++++++++++++++++++++++-------- drivers/hid/hid-roccat.h | 22 ----------------- include/linux/roccat.h | 29 ++++++++++++++++++++++ 9 files changed, 91 insertions(+), 56 deletions(-) delete mode 100644 drivers/hid/hid-roccat.h create mode 100644 include/linux/roccat.h (limited to 'Documentation') diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index ac293e955308..b0f1fa0770d1 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -133,6 +133,7 @@ Code Seq#(hex) Include File Comments 'H' C0-DF net/bluetooth/hidp/hidp.h conflict! 'H' C0-DF net/bluetooth/cmtp/cmtp.h conflict! 'H' C0-DF net/bluetooth/bnep/bnep.h conflict! +'H' F1 linux/roccat.h 'I' all linux/isdn.h conflict! 'I' 00-0F drivers/isdn/divert/isdn_divert.h conflict! 'I' 40-4F linux/mISDNif.h conflict! diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c index d72ee4186d11..7b9a992611bc 100644 --- a/drivers/hid/hid-roccat-arvo.c +++ b/drivers/hid/hid-roccat-arvo.c @@ -21,8 +21,8 @@ #include #include #include +#include #include "hid-ids.h" -#include "hid-roccat.h" #include "hid-roccat-common.h" #include "hid-roccat-arvo.h" @@ -303,7 +303,8 @@ static int arvo_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(arvo_class, hdev); + retval = roccat_connect(arvo_class, hdev, + sizeof(struct arvo_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); } else { @@ -386,8 +387,8 @@ static void arvo_report_to_chrdev(struct arvo_device const *arvo, else roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_RELEASE; - roccat_report_event(arvo->chrdev_minor, (uint8_t const *)&roccat_report, - sizeof(struct arvo_roccat_report)); + roccat_report_event(arvo->chrdev_minor, + (uint8_t const *)&roccat_report); } static int arvo_raw_event(struct hid_device *hdev, diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 551665359eba..5cdb282dad11 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -30,8 +30,8 @@ #include #include #include +#include #include "hid-ids.h" -#include "hid-roccat.h" #include "hid-roccat-common.h" #include "hid-roccat-kone.h" @@ -660,7 +660,8 @@ static int kone_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(kone_class, hdev); + retval = roccat_connect(kone_class, hdev, + sizeof(struct kone_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); /* be tolerant about not getting chrdev */ @@ -760,8 +761,7 @@ static void kone_report_to_chrdev(struct kone_device const *kone, roccat_report.value = event->value; roccat_report.key = 0; roccat_report_event(kone->chrdev_minor, - (uint8_t *)&roccat_report, - sizeof(struct kone_roccat_report)); + (uint8_t *)&roccat_report); break; case kone_mouse_event_call_overlong_macro: if (event->value == kone_keystroke_action_press) { @@ -769,8 +769,7 @@ static void kone_report_to_chrdev(struct kone_device const *kone, roccat_report.value = kone->actual_profile; roccat_report.key = event->macro_key; roccat_report_event(kone->chrdev_minor, - (uint8_t *)&roccat_report, - sizeof(struct kone_roccat_report)); + (uint8_t *)&roccat_report); } break; } diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c index df85ed8a3397..7367e4edfa6c 100644 --- a/drivers/hid/hid-roccat-koneplus.c +++ b/drivers/hid/hid-roccat-koneplus.c @@ -21,8 +21,8 @@ #include #include #include +#include #include "hid-ids.h" -#include "hid-roccat.h" #include "hid-roccat-common.h" #include "hid-roccat-koneplus.h" @@ -612,7 +612,8 @@ static int koneplus_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(koneplus_class, hdev); + retval = roccat_connect(koneplus_class, hdev, + sizeof(struct koneplus_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); } else { @@ -718,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, diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c index 1f547a2b39de..7664e2ce2886 100644 --- a/drivers/hid/hid-roccat-kovaplus.c +++ b/drivers/hid/hid-roccat-kovaplus.c @@ -20,8 +20,8 @@ #include #include #include +#include #include "hid-ids.h" -#include "hid-roccat.h" #include "hid-roccat-common.h" #include "hid-roccat-kovaplus.h" @@ -524,7 +524,8 @@ static int kovaplus_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(kovaplus_class, hdev); + retval = roccat_connect(kovaplus_class, hdev, + sizeof(struct kovaplus_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); } else { @@ -648,8 +649,7 @@ static void kovaplus_report_to_chrdev(struct kovaplus_device const *kovaplus, roccat_report.data2 = button_report->data2; roccat_report_event(kovaplus->chrdev_minor, - (uint8_t const *)&roccat_report, - sizeof(struct kovaplus_roccat_report)); + (uint8_t const *)&roccat_report); } static int kovaplus_raw_event(struct hid_device *hdev, diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c index abe77d3e6d8b..be4daa96f7c2 100644 --- a/drivers/hid/hid-roccat-pyra.c +++ b/drivers/hid/hid-roccat-pyra.c @@ -22,8 +22,8 @@ #include #include #include +#include #include "hid-ids.h" -#include "hid-roccat.h" #include "hid-roccat-common.h" #include "hid-roccat-pyra.h" @@ -506,7 +506,8 @@ static int pyra_init_specials(struct hid_device *hdev) goto exit_free; } - retval = roccat_connect(pyra_class, hdev); + retval = roccat_connect(pyra_class, hdev, + sizeof(struct pyra_roccat_report)); if (retval < 0) { hid_err(hdev, "couldn't init char dev\n"); } else { @@ -610,8 +611,7 @@ static void pyra_report_to_chrdev(struct pyra_device const *pyra, roccat_report.value = button_event->data1; roccat_report.key = 0; roccat_report_event(pyra->chrdev_minor, - (uint8_t const *)&roccat_report, - sizeof(struct pyra_roccat_report)); + (uint8_t const *)&roccat_report); break; case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO: case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT: @@ -625,8 +625,7 @@ static void pyra_report_to_chrdev(struct pyra_device const *pyra, */ roccat_report.value = pyra->actual_profile + 1; roccat_report_event(pyra->chrdev_minor, - (uint8_t const *)&roccat_report, - sizeof(struct pyra_roccat_report)); + (uint8_t const *)&roccat_report); } break; } 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 @@ #include #include #include - -#include "hid-roccat.h" +#include #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) diff --git a/drivers/hid/hid-roccat.h b/drivers/hid/hid-roccat.h deleted file mode 100644 index c7393372df7c..000000000000 --- a/drivers/hid/hid-roccat.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __HID_ROCCAT_H -#define __HID_ROCCAT_H - -/* - * Copyright (c) 2010 Stefan Achatz - */ - -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - */ - -#include -#include - -int roccat_connect(struct class *klass, struct hid_device *hid); -void roccat_disconnect(int minor); -int roccat_report_event(int minor, u8 const *data, int len); - -#endif diff --git a/include/linux/roccat.h b/include/linux/roccat.h new file mode 100644 index 000000000000..24e1ca01f9a0 --- /dev/null +++ b/include/linux/roccat.h @@ -0,0 +1,29 @@ +#ifndef __HID_ROCCAT_H +#define __HID_ROCCAT_H + +/* + * Copyright (c) 2010 Stefan Achatz + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include +#include + +#define ROCCATIOCGREPSIZE _IOR('H', 0xf1, int) + +#ifdef __KERNEL__ + +int roccat_connect(struct class *klass, struct hid_device *hid, + int report_size); +void roccat_disconnect(int minor); +int roccat_report_event(int minor, u8 const *data); + +#endif + +#endif -- cgit v1.2.3 From 5dc0c9835fb96c75c8dbf657393764bd0abbac04 Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Thu, 3 Feb 2011 16:14:43 +0100 Subject: HID: roccat: Rename header roccat.h -> hid-roccat.h It was desired that the header roccat.h should be named hid-roccat.h Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina --- Documentation/ioctl/ioctl-number.txt | 2 +- drivers/hid/hid-roccat-arvo.c | 2 +- drivers/hid/hid-roccat-kone.c | 2 +- drivers/hid/hid-roccat-koneplus.c | 2 +- drivers/hid/hid-roccat-kovaplus.c | 2 +- drivers/hid/hid-roccat-pyra.c | 2 +- drivers/hid/hid-roccat.c | 2 +- include/linux/hid-roccat.h | 29 +++++++++++++++++++++++++++++ include/linux/roccat.h | 29 ----------------------------- 9 files changed, 36 insertions(+), 36 deletions(-) create mode 100644 include/linux/hid-roccat.h delete mode 100644 include/linux/roccat.h (limited to 'Documentation') diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index b0f1fa0770d1..e68543f767d5 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -133,7 +133,7 @@ Code Seq#(hex) Include File Comments 'H' C0-DF net/bluetooth/hidp/hidp.h conflict! 'H' C0-DF net/bluetooth/cmtp/cmtp.h conflict! 'H' C0-DF net/bluetooth/bnep/bnep.h conflict! -'H' F1 linux/roccat.h +'H' F1 linux/hid-roccat.h 'I' all linux/isdn.h conflict! 'I' 00-0F drivers/isdn/divert/isdn_divert.h conflict! 'I' 40-4F linux/mISDNif.h conflict! diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c index 75f532f4d4cc..2307471d96dc 100644 --- a/drivers/hid/hid-roccat-arvo.c +++ b/drivers/hid/hid-roccat-arvo.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include "hid-ids.h" #include "hid-roccat-common.h" #include "hid-roccat-arvo.h" diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index d7497964a5b3..a57838d15267 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "hid-ids.h" #include "hid-roccat-common.h" #include "hid-roccat-kone.h" diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c index ac2010732495..a8e2117756ac 100644 --- a/drivers/hid/hid-roccat-koneplus.c +++ b/drivers/hid/hid-roccat-koneplus.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include "hid-ids.h" #include "hid-roccat-common.h" #include "hid-roccat-koneplus.h" diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c index 4eeb62fb4e75..984be2f8967e 100644 --- a/drivers/hid/hid-roccat-kovaplus.c +++ b/drivers/hid/hid-roccat-kovaplus.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include "hid-ids.h" #include "hid-roccat-common.h" #include "hid-roccat-kovaplus.h" diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c index 02a72433a712..160f481344f6 100644 --- a/drivers/hid/hid-roccat-pyra.c +++ b/drivers/hid/hid-roccat-pyra.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include "hid-ids.h" #include "hid-roccat-common.h" #include "hid-roccat-pyra.h" diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index bbe294c0dd9b..5666e7587b18 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #define ROCCAT_FIRST_MINOR 0 #define ROCCAT_MAX_DEVICES 8 diff --git a/include/linux/hid-roccat.h b/include/linux/hid-roccat.h new file mode 100644 index 000000000000..24e1ca01f9a0 --- /dev/null +++ b/include/linux/hid-roccat.h @@ -0,0 +1,29 @@ +#ifndef __HID_ROCCAT_H +#define __HID_ROCCAT_H + +/* + * Copyright (c) 2010 Stefan Achatz + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include +#include + +#define ROCCATIOCGREPSIZE _IOR('H', 0xf1, int) + +#ifdef __KERNEL__ + +int roccat_connect(struct class *klass, struct hid_device *hid, + int report_size); +void roccat_disconnect(int minor); +int roccat_report_event(int minor, u8 const *data); + +#endif + +#endif diff --git a/include/linux/roccat.h b/include/linux/roccat.h deleted file mode 100644 index 24e1ca01f9a0..000000000000 --- a/include/linux/roccat.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __HID_ROCCAT_H -#define __HID_ROCCAT_H - -/* - * Copyright (c) 2010 Stefan Achatz - */ - -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - */ - -#include -#include - -#define ROCCATIOCGREPSIZE _IOR('H', 0xf1, int) - -#ifdef __KERNEL__ - -int roccat_connect(struct class *klass, struct hid_device *hid, - int report_size); -void roccat_disconnect(int minor); -int roccat_report_event(int minor, u8 const *data); - -#endif - -#endif -- cgit v1.2.3 From 759ae89a6e29472cde17b80778a690430252049a Mon Sep 17 00:00:00 2001 From: Stefan Achatz Date: Thu, 3 Feb 2011 17:10:30 +0100 Subject: HID: roccat: Add 'Users:' tag to sysfs documentation Added 'Users:' tag to sysfs documentation of roccat device drivers pointing to project website at sourceforge. Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina --- Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo | 7 ++++++- Documentation/ABI/testing/sysfs-driver-hid-roccat-kone | 8 ++++++++ Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus | 11 +++++++++++ Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus | 9 +++++++++ Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra | 9 +++++++++ 5 files changed, 43 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo b/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo index d54827d98afd..55e281b0071a 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo @@ -6,6 +6,7 @@ Description: The integer value of this attribute ranges from 1-5. profile which is also the profile that's active on device startup. When written this attribute activates the selected profile immediately. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./arvo/roccatarvo/button Date: Januar 2011 @@ -16,6 +17,7 @@ Description: The keyboard can store short macros with consist of 1 button with button for a specific profile. Button and profile numbers are included in written data. The data has to be 24 bytes long. This file is writeonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./arvo/roccatarvo/info Date: Januar 2011 @@ -24,6 +26,7 @@ Description: When read, this file returns some info about the device like the installed firmware version. The size of the data is 8 bytes in size. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./arvo/roccatarvo/key_mask Date: Januar 2011 @@ -36,6 +39,7 @@ Description: The keyboard lets the user deactivate 5 certain keys like the When read, this file returns the current state of the buttons. When written, the given buttons are activated/deactivated immediately. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./arvo/roccatarvo/mode_key Date: Januar 2011 @@ -45,4 +49,5 @@ Description: The keyboard has a condensed layout without num-lock key. the assignment of the number block changes. The integer value of this attribute ranges from 0 (OFF) to 1 (ON). When read, this file returns the actual state of the key. - When written, the key is activated/deactivated immediately. \ No newline at end of file + When written, the key is activated/deactivated immediately. +Users: http://roccat.sourceforge.net diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone index 698b8081c473..b4c4f158ab9c 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone @@ -16,12 +16,14 @@ Description: It is possible to switch the dpi setting of the mouse with the 6 3200 This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kone/roccatkone/actual_profile Date: March 2010 Contact: Stefan Achatz Description: When read, this file returns the number of the actual profile. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kone/roccatkone/firmware_version Date: March 2010 @@ -32,6 +34,7 @@ Description: When read, this file returns the raw integer version number of the number the decimal point has to be shifted 2 positions to the left. E.g. a returned value of 138 means 1.38 This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kone/roccatkone/profile[1-5] Date: March 2010 @@ -47,6 +50,7 @@ Description: The mouse can store 5 profiles which can be switched by the The mouse will reject invalid data, whereas the profile number stored in the profile doesn't need to fit the number of the store. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kone/roccatkone/settings Date: March 2010 @@ -57,6 +61,7 @@ Description: When read, this file returns the settings stored in the mouse. When written, this file lets write settings back to the mouse. The data has to be 36 bytes long. The mouse will reject invalid data. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kone/roccatkone/startup_profile Date: March 2010 @@ -66,6 +71,7 @@ Description: The integer value of this attribute ranges from 1 to 5. that's active when the mouse is powered on. When written, this file sets the number of the startup profile and the mouse activates this profile immediately. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kone/roccatkone/tcu Date: March 2010 @@ -77,6 +83,7 @@ Description: The mouse has a "Tracking Control Unit" which lets the user Writing 0 in this file will switch the TCU off. Writing 1 in this file will start the calibration which takes around 6 seconds to complete and activates the TCU. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kone/roccatkone/weight Date: March 2010 @@ -96,3 +103,4 @@ Description: The mouse can be equipped with one of four supplied weights 4 20g This file is readonly. +Users: http://roccat.sourceforge.net diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus index 0f9f30eb1742..00efced73969 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus @@ -4,6 +4,7 @@ Contact: Stefan Achatz Description: When read, this file returns the number of the actual profile in range 0-4. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./koneplus/roccatkoneplus/firmware_version Date: October 2010 @@ -14,6 +15,7 @@ Description: When read, this file returns the raw integer version number of the number the decimal point has to be shifted 2 positions to the left. E.g. a returned value of 121 means 1.21 This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./koneplus/roccatkoneplus/macro Date: October 2010 @@ -24,6 +26,7 @@ Description: The mouse can store a macro with max 500 key/button strokes button for a specific profile. Button and profile numbers are included in written data. The data has to be 2082 bytes long. This file is writeonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./koneplus/roccatkoneplus/profile_buttons Date: August 2010 @@ -37,6 +40,7 @@ Description: The mouse can store 5 profiles which can be switched by the Which profile to write is determined by the profile number contained in the data. This file is writeonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./koneplus/roccatkoneplus/profile[1-5]_buttons Date: August 2010 @@ -47,6 +51,7 @@ Description: The mouse can store 5 profiles which can be switched by the When read, these files return the respective profile buttons. The returned data is 77 bytes in size. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./koneplus/roccatkoneplus/profile_settings Date: October 2010 @@ -61,6 +66,7 @@ Description: The mouse can store 5 profiles which can be switched by the Which profile to write is determined by the profile number contained in the data. This file is writeonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./koneplus/roccatkoneplus/profile[1-5]_settings Date: August 2010 @@ -72,6 +78,7 @@ Description: The mouse can store 5 profiles which can be switched by the When read, these files return the respective profile settings. The returned data is 43 bytes in size. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./koneplus/roccatkoneplus/sensor Date: October 2010 @@ -80,6 +87,7 @@ Description: The mouse has a tracking- and a distance-control-unit. These can be activated/deactivated and the lift-off distance can be set. The data has to be 6 bytes long. This file is writeonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./koneplus/roccatkoneplus/startup_profile Date: October 2010 @@ -89,6 +97,7 @@ Description: The integer value of this attribute ranges from 0-4. that's active when the mouse is powered on. When written, this file sets the number of the startup profile and the mouse activates this profile immediately. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./koneplus/roccatkoneplus/tcu Date: October 2010 @@ -97,6 +106,7 @@ Description: When written a calibration process for the tracking control unit can be initiated/cancelled. The data has to be 3 bytes long. This file is writeonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./koneplus/roccatkoneplus/tcu_image Date: October 2010 @@ -106,3 +116,4 @@ Description: When read the mouse returns a 30x30 pixel image of the calibration process initiated with tcu. The returned data is 1028 bytes in size. This file is readonly. +Users: http://roccat.sourceforge.net diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus index 9e54af4c8fc0..fdfa16f8189b 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus @@ -5,6 +5,7 @@ Description: The integer value of this attribute ranges from 1-4. When read, this attribute returns the number of the active cpi level. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/actual_profile Date: January 2011 @@ -15,6 +16,7 @@ Description: The integer value of this attribute ranges from 0-4. When written, the mouse activates this profile immediately. The profile that's active when powered down is the same that's active when the mouse is powered on. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/actual_sensitivity_x Date: January 2011 @@ -23,6 +25,7 @@ Description: The integer value of this attribute ranges from 1-10. When read, this attribute returns the number of the actual sensitivity in x direction. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/actual_sensitivity_y Date: January 2011 @@ -31,6 +34,7 @@ Description: The integer value of this attribute ranges from 1-10. When read, this attribute returns the number of the actual sensitivity in y direction. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/firmware_version Date: January 2011 @@ -41,6 +45,7 @@ Description: When read, this file returns the raw integer version number of the number the decimal point has to be shifted 2 positions to the left. E.g. a returned value of 121 means 1.21 This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/profile_buttons Date: January 2011 @@ -54,6 +59,7 @@ Description: The mouse can store 5 profiles which can be switched by the Which profile to write is determined by the profile number contained in the data. This file is writeonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/profile[1-5]_buttons Date: January 2011 @@ -64,6 +70,7 @@ Description: The mouse can store 5 profiles which can be switched by the When read, these files return the respective profile buttons. The returned data is 23 bytes in size. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/profile_settings Date: January 2011 @@ -78,6 +85,7 @@ Description: The mouse can store 5 profiles which can be switched by the Which profile to write is determined by the profile number contained in the data. This file is writeonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./kovaplus/roccatkovaplus/profile[1-5]_settings Date: January 2011 @@ -89,3 +97,4 @@ Description: The mouse can store 5 profiles which can be switched by the When read, these files return the respective profile settings. The returned data is 16 bytes in size. This file is readonly. +Users: http://roccat.sourceforge.net diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra index 1c37b823f142..5fab71af3c46 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra @@ -13,6 +13,7 @@ Description: It is possible to switch the cpi setting of the mouse with the 4 1600 This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./pyra/roccatpyra/actual_profile Date: August 2010 @@ -20,6 +21,7 @@ Contact: Stefan Achatz Description: When read, this file returns the number of the actual profile in range 0-4. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./pyra/roccatpyra/firmware_version Date: August 2010 @@ -30,6 +32,7 @@ Description: When read, this file returns the raw integer version number of the number the decimal point has to be shifted 2 positions to the left. E.g. a returned value of 138 means 1.38 This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./pyra/roccatpyra/profile_settings Date: August 2010 @@ -44,6 +47,7 @@ Description: The mouse can store 5 profiles which can be switched by the Which profile to write is determined by the profile number contained in the data. This file is writeonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./pyra/roccatpyra/profile[1-5]_settings Date: August 2010 @@ -55,6 +59,7 @@ Description: The mouse can store 5 profiles which can be switched by the When read, these files return the respective profile settings. The returned data is 13 bytes in size. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./pyra/roccatpyra/profile_buttons Date: August 2010 @@ -68,6 +73,7 @@ Description: The mouse can store 5 profiles which can be switched by the Which profile to write is determined by the profile number contained in the data. This file is writeonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./pyra/roccatpyra/profile[1-5]_buttons Date: August 2010 @@ -78,6 +84,7 @@ Description: The mouse can store 5 profiles which can be switched by the When read, these files return the respective profile buttons. The returned data is 19 bytes in size. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./pyra/roccatpyra/startup_profile Date: August 2010 @@ -86,6 +93,7 @@ Description: The integer value of this attribute ranges from 0-4. When read, this attribute returns the number of the profile that's active when the mouse is powered on. This file is readonly. +Users: http://roccat.sourceforge.net What: /sys/bus/usb/devices/-:./::./pyra/roccatpyra/settings Date: August 2010 @@ -96,3 +104,4 @@ Description: When read, this file returns the settings stored in the mouse. When written, this file lets write settings back to the mouse. The data has to be 3 bytes long. The mouse will reject invalid data. +Users: http://roccat.sourceforge.net -- cgit v1.2.3 From 6d3bfb74341c2c1454fcf5ec9c4dd707011f78e5 Mon Sep 17 00:00:00 2001 From: Alan Ott Date: Sun, 23 Jan 2011 22:50:18 -0500 Subject: HID: Add HID Report Descriptor to sysfs Add a new binary sysfs entry called report_descriptor which contains the HID report descriptor. Signed-off-by: Alan Ott Signed-off-by: Jiri Kosina --- Documentation/ABI/testing/sysfs-driver-hid | 10 +++++++++ drivers/hid/hid-core.c | 33 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-driver-hid (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-driver-hid b/Documentation/ABI/testing/sysfs-driver-hid new file mode 100644 index 000000000000..b6490e14fe83 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid @@ -0,0 +1,10 @@ +What: For USB devices : /sys/bus/usb/devices/-:./::./report_descriptor + For BT devices : /sys/class/bluetooth/hci/::./report_descriptor + Symlink : /sys/class/hidraw/hidraw/device/report_descriptor +Date: Jan 2011 +KernelVersion: 2.0.39 +Contact: Alan Ott +Description: When read, this file returns the device's raw binary HID + report descriptor. + This file cannot be written. +Users: HIDAPI library (http://www.signal11.us/oss/hidapi) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2dcdf9ff02ea..5e0e4eea7065 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1159,6 +1159,32 @@ static bool hid_hiddev(struct hid_device *hdev) return !!hid_match_id(hdev, hid_hiddev_list); } + +static ssize_t +read_report_descriptor(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct hid_device *hdev = container_of(dev, struct hid_device, dev); + + if (off >= hdev->rsize) + return 0; + + if (off + count > hdev->rsize) + count = hdev->rsize - off; + + memcpy(buf, hdev->rdesc + off, count); + + return count; +} + +static struct bin_attribute dev_bin_attr_report_desc = { + .attr = { .name = "report_descriptor", .mode = 0444 }, + .read = read_report_descriptor, + .size = HID_MAX_DESCRIPTOR_SIZE, +}; + int hid_connect(struct hid_device *hdev, unsigned int connect_mask) { static const char *types[] = { "Device", "Pointer", "Mouse", "Device", @@ -1169,6 +1195,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) char buf[64]; unsigned int i; int len; + int ret; if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE) connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV); @@ -1230,6 +1257,11 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) bus = ""; } + ret = device_create_bin_file(&hdev->dev, &dev_bin_attr_report_desc); + if (ret) + hid_warn(hdev, + "can't create sysfs report descriptor attribute err: %d\n", ret); + hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n", buf, bus, hdev->version >> 8, hdev->version & 0xff, type, hdev->name, hdev->phys); @@ -1240,6 +1272,7 @@ EXPORT_SYMBOL_GPL(hid_connect); void hid_disconnect(struct hid_device *hdev) { + device_remove_bin_file(&hdev->dev, &dev_bin_attr_report_desc); if (hdev->claimed & HID_CLAIMED_INPUT) hidinput_disconnect(hdev); if (hdev->claimed & HID_CLAIMED_HIDDEV) -- cgit v1.2.3