Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: roccat: add support for Ryos MK keyboards

Added support for 3 keyboards with increasing illumination capabilities

Signed-off-by: Stefan Achatz <erazor_de@users.sourceforge.net>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by

Stefan Achatz and committed by
Jiri Kosina
6f3a1936 71304f5a

+426 -1
+178
Documentation/ABI/testing/sysfs-driver-hid-roccat-ryos
··· 1 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/control 2 + Date: October 2013 3 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 4 + Description: When written, this file lets one select which data from which 5 + profile will be read next. The data has to be 3 bytes long. 6 + This file is writeonly. 7 + Users: http://roccat.sourceforge.net 8 + 9 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/profile 10 + Date: October 2013 11 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 12 + Description: The mouse can store 5 profiles which can be switched by the 13 + press of a button. profile holds index of actual profile. 14 + This value is persistent, so its value determines the profile 15 + that's active when the device is powered on next time. 16 + When written, the device activates the set profile immediately. 17 + The data has to be 3 bytes long. 18 + The device will reject invalid data. 19 + Users: http://roccat.sourceforge.net 20 + 21 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_primary 22 + Date: October 2013 23 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 24 + Description: When written, this file lets one set the default of all keys for 25 + a specific profile. Profile index is included in written data. 26 + The data has to be 125 bytes long. 27 + Before reading this file, control has to be written to select 28 + which profile to read. 29 + Users: http://roccat.sourceforge.net 30 + 31 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_function 32 + Date: October 2013 33 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 34 + Description: When written, this file lets one set the function of the 35 + function keys for a specific profile. Profile index is included 36 + in written data. The data has to be 95 bytes long. 37 + Before reading this file, control has to be written to select 38 + which profile to read. 39 + Users: http://roccat.sourceforge.net 40 + 41 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_macro 42 + Date: October 2013 43 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 44 + Description: When written, this file lets one set the function of the macro 45 + keys for a specific profile. Profile index is included in 46 + written data. The data has to be 35 bytes long. 47 + Before reading this file, control has to be written to select 48 + which profile to read. 49 + Users: http://roccat.sourceforge.net 50 + 51 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_thumbster 52 + Date: October 2013 53 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 54 + Description: When written, this file lets one set the function of the 55 + thumbster keys for a specific profile. Profile index is included 56 + in written data. The data has to be 23 bytes long. 57 + Before reading this file, control has to be written to select 58 + which profile to read. 59 + Users: http://roccat.sourceforge.net 60 + 61 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_extra 62 + Date: October 2013 63 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 64 + Description: When written, this file lets one set the function of the 65 + capslock and function keys for a specific profile. Profile index 66 + is included in written data. The data has to be 8 bytes long. 67 + Before reading this file, control has to be written to select 68 + which profile to read. 69 + Users: http://roccat.sourceforge.net 70 + 71 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/keys_easyzone 72 + Date: October 2013 73 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 74 + Description: When written, this file lets one set the function of the 75 + easyzone keys for a specific profile. Profile index is included 76 + in written data. The data has to be 294 bytes long. 77 + Before reading this file, control has to be written to select 78 + which profile to read. 79 + Users: http://roccat.sourceforge.net 80 + 81 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/key_mask 82 + Date: October 2013 83 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 84 + Description: When written, this file lets one deactivate certain keys like 85 + windows and application keys, to prevent accidental presses. 86 + Profile index for which this settings occur is included in 87 + written data. The data has to be 6 bytes long. 88 + Before reading this file, control has to be written to select 89 + which profile to read. 90 + Users: http://roccat.sourceforge.net 91 + 92 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/light 93 + Date: October 2013 94 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 95 + Description: When written, this file lets one set the backlight intensity for 96 + a specific profile. Profile index is included in written data. 97 + This attribute is only valid for the glow and pro variant. 98 + The data has to be 16 bytes long. 99 + Before reading this file, control has to be written to select 100 + which profile to read. 101 + Users: http://roccat.sourceforge.net 102 + 103 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/macro 104 + Date: October 2013 105 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 106 + Description: When written, this file lets one store macros with max 480 107 + keystrokes for a specific button for a specific profile. 108 + Button and profile indexes are included in written data. 109 + The data has to be 2002 bytes long. 110 + Before reading this file, control has to be written to select 111 + which profile and key to read. 112 + Users: http://roccat.sourceforge.net 113 + 114 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/info 115 + Date: October 2013 116 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 117 + Description: When read, this file returns general data like firmware version. 118 + The data is 8 bytes long. 119 + This file is readonly. 120 + Users: http://roccat.sourceforge.net 121 + 122 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/reset 123 + Date: October 2013 124 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 125 + Description: When written, this file lets one reset the device. 126 + The data has to be 3 bytes long. 127 + This file is writeonly. 128 + Users: http://roccat.sourceforge.net 129 + 130 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/talk 131 + Date: October 2013 132 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 133 + Description: When written, this file lets one trigger easyshift functionality 134 + from the host. 135 + The data has to be 16 bytes long. 136 + This file is writeonly. 137 + Users: http://roccat.sourceforge.net 138 + 139 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/light_control 140 + Date: October 2013 141 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 142 + Description: When written, this file lets one switch between stored and custom 143 + light settings. 144 + This attribute is only valid for the pro variant. 145 + The data has to be 8 bytes long. 146 + This file is writeonly. 147 + Users: http://roccat.sourceforge.net 148 + 149 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/stored_lights 150 + Date: October 2013 151 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 152 + Description: When written, this file lets one set per-key lighting for different 153 + layers. 154 + This attribute is only valid for the pro variant. 155 + The data has to be 1382 bytes long. 156 + Before reading this file, control has to be written to select 157 + which profile to read. 158 + Users: http://roccat.sourceforge.net 159 + 160 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/custom_lights 161 + Date: October 2013 162 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 163 + Description: When written, this file lets one set the actual per-key lighting. 164 + This attribute is only valid for the pro variant. 165 + The data has to be 20 bytes long. 166 + This file is writeonly. 167 + Users: http://roccat.sourceforge.net 168 + 169 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/ryos/roccatryos<minor>/light_macro 170 + Date: October 2013 171 + Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 172 + Description: When written, this file lets one set a light macro that is looped 173 + whenever the device gets in dimness mode. 174 + This attribute is only valid for the pro variant. 175 + The data has to be 2002 bytes long. 176 + Before reading this file, control has to be written to select 177 + which profile to read. 178 + Users: http://roccat.sourceforge.net
+1 -1
drivers/hid/Makefile
··· 95 95 obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ 96 96 hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ 97 97 hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \ 98 - hid-roccat-lua.o hid-roccat-pyra.o hid-roccat-savu.o 98 + hid-roccat-lua.o hid-roccat-pyra.o hid-roccat-ryos.o hid-roccat-savu.o 99 99 obj-$(CONFIG_HID_SAITEK) += hid-saitek.o 100 100 obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o 101 101 obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
+3
drivers/hid/hid-core.c
··· 1811 1811 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) }, 1812 1812 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, 1813 1813 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, 1814 + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK) }, 1815 + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_GLOW) }, 1816 + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO) }, 1814 1817 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, 1815 1818 #endif 1816 1819 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) },
+3
drivers/hid/hid-ids.h
··· 726 726 #define USB_DEVICE_ID_ROCCAT_LUA 0x2c2e 727 727 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 728 728 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 729 + #define USB_DEVICE_ID_ROCCAT_RYOS_MK 0x3138 730 + #define USB_DEVICE_ID_ROCCAT_RYOS_MK_GLOW 0x31ce 731 + #define USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO 0x3232 729 732 #define USB_DEVICE_ID_ROCCAT_SAVU 0x2d5a 730 733 731 734 #define USB_VENDOR_ID_SAITEK 0x06a3
+241
drivers/hid/hid-roccat-ryos.c
··· 1 + /* 2 + * Roccat Ryos driver for Linux 3 + * 4 + * Copyright (c) 2013 Stefan Achatz <erazor_de@users.sourceforge.net> 5 + */ 6 + 7 + /* 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the Free 10 + * Software Foundation; either version 2 of the License, or (at your option) 11 + * any later version. 12 + */ 13 + 14 + #include <linux/types.h> 15 + #include <linux/device.h> 16 + #include <linux/input.h> 17 + #include <linux/hid.h> 18 + #include <linux/module.h> 19 + #include <linux/slab.h> 20 + #include <linux/hid-roccat.h> 21 + #include "hid-ids.h" 22 + #include "hid-roccat-common.h" 23 + 24 + enum { 25 + RYOS_REPORT_NUMBER_SPECIAL = 3, 26 + RYOS_USB_INTERFACE_PROTOCOL = 0, 27 + }; 28 + 29 + struct ryos_report_special { 30 + uint8_t number; /* RYOS_REPORT_NUMBER_SPECIAL */ 31 + uint8_t data[4]; 32 + } __packed; 33 + 34 + static struct class *ryos_class; 35 + 36 + ROCCAT_COMMON2_BIN_ATTRIBUTE_W(control, 0x04, 0x03); 37 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(profile, 0x05, 0x03); 38 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_primary, 0x06, 0x7d); 39 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_function, 0x07, 0x5f); 40 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_macro, 0x08, 0x23); 41 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_thumbster, 0x09, 0x17); 42 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_extra, 0x0a, 0x08); 43 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(keys_easyzone, 0x0b, 0x126); 44 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(key_mask, 0x0c, 0x06); 45 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(light, 0x0d, 0x10); 46 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(macro, 0x0e, 0x7d2); 47 + ROCCAT_COMMON2_BIN_ATTRIBUTE_R(info, 0x0f, 0x08); 48 + ROCCAT_COMMON2_BIN_ATTRIBUTE_W(reset, 0x11, 0x03); 49 + ROCCAT_COMMON2_BIN_ATTRIBUTE_W(light_control, 0x13, 0x08); 50 + ROCCAT_COMMON2_BIN_ATTRIBUTE_W(talk, 0x16, 0x10); 51 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(stored_lights, 0x17, 0x0566); 52 + ROCCAT_COMMON2_BIN_ATTRIBUTE_W(custom_lights, 0x18, 0x14); 53 + ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(light_macro, 0x19, 0x07d2); 54 + 55 + static struct bin_attribute *ryos_bin_attrs[] = { 56 + &bin_attr_control, 57 + &bin_attr_profile, 58 + &bin_attr_keys_primary, 59 + &bin_attr_keys_function, 60 + &bin_attr_keys_macro, 61 + &bin_attr_keys_thumbster, 62 + &bin_attr_keys_extra, 63 + &bin_attr_keys_easyzone, 64 + &bin_attr_key_mask, 65 + &bin_attr_light, 66 + &bin_attr_macro, 67 + &bin_attr_info, 68 + &bin_attr_reset, 69 + &bin_attr_light_control, 70 + &bin_attr_talk, 71 + &bin_attr_stored_lights, 72 + &bin_attr_custom_lights, 73 + &bin_attr_light_macro, 74 + NULL, 75 + }; 76 + 77 + static const struct attribute_group ryos_group = { 78 + .bin_attrs = ryos_bin_attrs, 79 + }; 80 + 81 + static const struct attribute_group *ryos_groups[] = { 82 + &ryos_group, 83 + NULL, 84 + }; 85 + 86 + static int ryos_init_specials(struct hid_device *hdev) 87 + { 88 + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 89 + struct usb_device *usb_dev = interface_to_usbdev(intf); 90 + struct roccat_common2_device *ryos; 91 + int retval; 92 + 93 + if (intf->cur_altsetting->desc.bInterfaceProtocol 94 + != RYOS_USB_INTERFACE_PROTOCOL) { 95 + hid_set_drvdata(hdev, NULL); 96 + return 0; 97 + } 98 + 99 + ryos = kzalloc(sizeof(*ryos), GFP_KERNEL); 100 + if (!ryos) { 101 + hid_err(hdev, "can't alloc device descriptor\n"); 102 + return -ENOMEM; 103 + } 104 + hid_set_drvdata(hdev, ryos); 105 + 106 + retval = roccat_common2_device_init_struct(usb_dev, ryos); 107 + if (retval) { 108 + hid_err(hdev, "couldn't init Ryos device\n"); 109 + goto exit_free; 110 + } 111 + 112 + retval = roccat_connect(ryos_class, hdev, 113 + sizeof(struct ryos_report_special)); 114 + if (retval < 0) { 115 + hid_err(hdev, "couldn't init char dev\n"); 116 + } else { 117 + ryos->chrdev_minor = retval; 118 + ryos->roccat_claimed = 1; 119 + } 120 + 121 + return 0; 122 + exit_free: 123 + kfree(ryos); 124 + return retval; 125 + } 126 + 127 + static void ryos_remove_specials(struct hid_device *hdev) 128 + { 129 + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 130 + struct roccat_common2_device *ryos; 131 + 132 + if (intf->cur_altsetting->desc.bInterfaceProtocol 133 + != RYOS_USB_INTERFACE_PROTOCOL) 134 + return; 135 + 136 + ryos = hid_get_drvdata(hdev); 137 + if (ryos->roccat_claimed) 138 + roccat_disconnect(ryos->chrdev_minor); 139 + kfree(ryos); 140 + } 141 + 142 + static int ryos_probe(struct hid_device *hdev, 143 + const struct hid_device_id *id) 144 + { 145 + int retval; 146 + 147 + retval = hid_parse(hdev); 148 + if (retval) { 149 + hid_err(hdev, "parse failed\n"); 150 + goto exit; 151 + } 152 + 153 + retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 154 + if (retval) { 155 + hid_err(hdev, "hw start failed\n"); 156 + goto exit; 157 + } 158 + 159 + retval = ryos_init_specials(hdev); 160 + if (retval) { 161 + hid_err(hdev, "couldn't install mouse\n"); 162 + goto exit_stop; 163 + } 164 + 165 + return 0; 166 + 167 + exit_stop: 168 + hid_hw_stop(hdev); 169 + exit: 170 + return retval; 171 + } 172 + 173 + static void ryos_remove(struct hid_device *hdev) 174 + { 175 + ryos_remove_specials(hdev); 176 + hid_hw_stop(hdev); 177 + } 178 + 179 + static int ryos_raw_event(struct hid_device *hdev, 180 + struct hid_report *report, u8 *data, int size) 181 + { 182 + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 183 + struct roccat_common2_device *ryos = hid_get_drvdata(hdev); 184 + 185 + if (intf->cur_altsetting->desc.bInterfaceProtocol 186 + != RYOS_USB_INTERFACE_PROTOCOL) 187 + return 0; 188 + 189 + if (data[0] != RYOS_REPORT_NUMBER_SPECIAL) 190 + return 0; 191 + 192 + if (ryos != NULL && ryos->roccat_claimed) 193 + roccat_report_event(ryos->chrdev_minor, data); 194 + 195 + return 0; 196 + } 197 + 198 + static const struct hid_device_id ryos_devices[] = { 199 + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK) }, 200 + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_GLOW) }, 201 + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO) }, 202 + { } 203 + }; 204 + 205 + MODULE_DEVICE_TABLE(hid, ryos_devices); 206 + 207 + static struct hid_driver ryos_driver = { 208 + .name = "ryos", 209 + .id_table = ryos_devices, 210 + .probe = ryos_probe, 211 + .remove = ryos_remove, 212 + .raw_event = ryos_raw_event 213 + }; 214 + 215 + static int __init ryos_init(void) 216 + { 217 + int retval; 218 + 219 + ryos_class = class_create(THIS_MODULE, "ryos"); 220 + if (IS_ERR(ryos_class)) 221 + return PTR_ERR(ryos_class); 222 + ryos_class->dev_groups = ryos_groups; 223 + 224 + retval = hid_register_driver(&ryos_driver); 225 + if (retval) 226 + class_destroy(ryos_class); 227 + return retval; 228 + } 229 + 230 + static void __exit ryos_exit(void) 231 + { 232 + hid_unregister_driver(&ryos_driver); 233 + class_destroy(ryos_class); 234 + } 235 + 236 + module_init(ryos_init); 237 + module_exit(ryos_exit); 238 + 239 + MODULE_AUTHOR("Stefan Achatz"); 240 + MODULE_DESCRIPTION("USB Roccat Ryos MK/Glow/Pro driver"); 241 + MODULE_LICENSE("GPL v2");