aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-roccat-kone111
-rw-r--r--drivers/hid/Kconfig7
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-core.c1
-rw-r--r--drivers/hid/hid-ids.h3
-rw-r--r--drivers/hid/hid-roccat-kone.c1006
-rw-r--r--drivers/hid/hid-roccat-kone.h214
7 files changed, 1343 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
new file mode 100644
index 000000000000..88340a23ce91
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
@@ -0,0 +1,111 @@
1What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_dpi
2Date: March 2010
3Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
4Description: It is possible to switch the dpi setting of the mouse with the
5 press of a button.
6 When read, this file returns the raw number of the actual dpi
7 setting reported by the mouse. This number has to be further
8 processed to receive the real dpi value.
9
10 VALUE DPI
11 1 800
12 2 1200
13 3 1600
14 4 2000
15 5 2400
16 6 3200
17
18 This file is readonly.
19
20What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_profile
21Date: March 2010
22Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
23Description: When read, this file returns the number of the actual profile.
24 This file is readonly.
25
26What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/firmware_version
27Date: March 2010
28Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
29Description: When read, this file returns the raw integer version number of the
30 firmware reported by the mouse. Using the integer value eases
31 further usage in other programs. To receive the real version
32 number the decimal point has to be shifted 2 positions to the
33 left. E.g. a returned value of 138 means 1.38
34 This file is readonly.
35
36What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/kone_driver_version
37Date: March 2010
38Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
39Description: When read, this file returns the driver version.
40 The format of the string is "v<major>.<minor>.<patchlevel>".
41 This attribute is used by the userland tools to find the sysfs-
42 paths of installed kone-mice and determine the capabilites of
43 the driver. Versions of this driver for old kernels replace
44 usbhid instead of generic-usb. The way to scan for this file
45 has been chosen to provide a consistent way for all supported
46 kernel versions.
47 This file is readonly.
48
49What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]
50Date: March 2010
51Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
52Description: The mouse can store 5 profiles which can be switched by the
53 press of a button. A profile holds informations like button
54 mappings, sensitivity, the colors of the 5 leds and light
55 effects.
56 When read, these files return the respective profile. The
57 returned data is 975 bytes in size.
58 When written, this file lets one write the respective profile
59 data back to the mouse. The data has to be 975 bytes long.
60 The mouse will reject invalid data, whereas the profile number
61 stored in the profile doesn't need to fit the number of the
62 store.
63
64What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/settings
65Date: March 2010
66Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
67Description: When read, this file returns the settings stored in the mouse.
68 The size of the data is 36 bytes and holds information like the
69 startup_profile, tcu state and calibration_data.
70 When written, this file lets write settings back to the mouse.
71 The data has to be 36 bytes long. The mouse will reject invalid
72 data.
73
74What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/startup_profile
75Date: March 2010
76Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
77Description: The integer value of this attribute ranges from 1 to 5.
78 When read, this attribute returns the number of the profile
79 that's active when the mouse is powered on.
80 When written, this file sets the number of the startup profile
81 and the mouse activates this profile immediately.
82
83What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/tcu
84Date: March 2010
85Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
86Description: The mouse has a "Tracking Control Unit" which lets the user
87 calibrate the laser power to fit the mousepad surface.
88 When read, this file returns the current state of the TCU,
89 where 0 means off and 1 means on.
90 Writing 0 in this file will switch the TCU off.
91 Writing 1 in this file will start the calibration which takes
92 around 6 seconds to complete and activates the TCU.
93
94What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/weight
95Date: March 2010
96Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
97Description: The mouse can be equipped with one of four supplied weights
98 ranging from 5 to 20 grams which are recognized by the mouse
99 and its value can be read out. When read, this file returns the
100 raw value returned by the mouse which eases further processing
101 in other software.
102 The values map to the weights as follows:
103
104 VALUE WEIGHT
105 0 none
106 1 5g
107 2 10g
108 3 15g
109 4 20g
110
111 This file is readonly.
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 71d4c0703629..d819b0271b41 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -268,6 +268,13 @@ config HID_QUANTA
268 ---help--- 268 ---help---
269 Support for Quanta Optical Touch dual-touch panels. 269 Support for Quanta Optical Touch dual-touch panels.
270 270
271config HID_ROCCAT_KONE
272 tristate "Roccat Kone" if EMBEDDED
273 depends on USB_HID
274 default !EMBEDDED
275 ---help---
276 Support for Roccat Kone mouse.
277
271config HID_SAMSUNG 278config HID_SAMSUNG
272 tristate "Samsung" if EMBEDDED 279 tristate "Samsung" if EMBEDDED
273 depends on USB_HID 280 depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 0b2618f092ca..08b83ccd9d1b 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_HID_ORTEK) += hid-ortek.o
44obj-$(CONFIG_HID_QUANTA) += hid-quanta.o 44obj-$(CONFIG_HID_QUANTA) += hid-quanta.o
45obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o 45obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
46obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o 46obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
47obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o
47obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o 48obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
48obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o 49obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
49obj-$(CONFIG_HID_SONY) += hid-sony.o 50obj-$(CONFIG_HID_SONY) += hid-sony.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 2e2aa759d230..5c5a821cd4cb 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1346,6 +1346,7 @@ static const struct hid_device_id hid_blacklist[] = {
1346 { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, 1346 { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
1347 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, 1347 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
1348 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, 1348 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
1349 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
1349 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, 1350 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
1350 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, 1351 { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
1351 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, 1352 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 797e06470356..014acfcde562 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -399,6 +399,9 @@
399#define USB_VENDOR_ID_PRODIGE 0x05af 399#define USB_VENDOR_ID_PRODIGE 0x05af
400#define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062 400#define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062
401 401
402#define USB_VENDOR_ID_ROCCAT 0x1e7d
403#define USB_DEVICE_ID_ROCCAT_KONE 0x2ced
404
402#define USB_VENDOR_ID_SAITEK 0x06a3 405#define USB_VENDOR_ID_SAITEK 0x06a3
403#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 406#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
404 407
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
new file mode 100644
index 000000000000..2b1412e4ff6f
--- /dev/null
+++ b/drivers/hid/hid-roccat-kone.c
@@ -0,0 +1,1006 @@
1/*
2 * Roccat Kone driver for Linux
3 *
4 * Copyright (c) 2010 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/*
15 * Roccat Kone is a gamer mouse which consists of a mouse part and a keyboard
16 * part. The keyboard part enables the mouse to execute stored macros with mixed
17 * key- and button-events.
18 *
19 * TODO implement on-the-fly polling-rate change
20 * The windows driver has the ability to change the polling rate of the
21 * device on the press of a mousebutton.
22 * Is it possible to remove and reinstall the urb in raw-event- or any
23 * other handler, or to defer this action to be executed somewhere else?
24 *
25 * TODO implement notification mechanism for overlong macro execution
26 * If user wants to execute an overlong macro only the names of macroset
27 * and macro are given. Should userland tap hidraw or is there an
28 * additional streaming mechanism?
29 *
30 * TODO is it possible to overwrite group for sysfs attributes via udev?
31 */
32
33#include <linux/device.h>
34#include <linux/input.h>
35#include <linux/hid.h>
36#include <linux/usb.h>
37#include <linux/module.h>
38#include "hid-ids.h"
39#include "hid-roccat-kone.h"
40
41static void kone_set_settings_checksum(struct kone_settings *settings)
42{
43 uint16_t checksum = 0;
44 unsigned char *address = (unsigned char *)settings;
45 int i;
46
47 for (i = 0; i < sizeof(struct kone_settings) - 2; ++i, ++address)
48 checksum += *address;
49 settings->checksum = cpu_to_le16(checksum);
50}
51
52/*
53 * Checks success after writing data to mouse
54 * On success returns 0
55 * On failure returns errno
56 */
57static int kone_check_write(struct usb_device *usb_dev)
58{
59 int len;
60 unsigned char *data;
61
62 data = kmalloc(1, GFP_KERNEL);
63 if (!data)
64 return -ENOMEM;
65
66 do {
67 /*
68 * Mouse needs 50 msecs until it says ok, but there are
69 * 30 more msecs needed for next write to work.
70 */
71 msleep(80);
72
73 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
74 USB_REQ_CLEAR_FEATURE,
75 USB_TYPE_CLASS | USB_RECIP_INTERFACE |
76 USB_DIR_IN,
77 kone_command_confirm_write, 0, data, 1,
78 USB_CTRL_SET_TIMEOUT);
79
80 if (len != 1) {
81 kfree(data);
82 return -EIO;
83 }
84
85 /*
86 * value of 3 seems to mean something like
87 * "not finished yet, but it looks good"
88 * So check again after a moment.
89 */
90 } while (*data == 3);
91
92 if (*data == 1) { /* everything alright */
93 kfree(data);
94 return 0;
95 } else { /* unknown answer */
96 dev_err(&usb_dev->dev, "got retval %d when checking write\n",
97 *data);
98 kfree(data);
99 return -EIO;
100 }
101}
102
103/*
104 * Reads settings from mouse and stores it in @buf
105 * @buf has to be alloced with GFP_KERNEL
106 * On success returns 0
107 * On failure returns errno
108 */
109static int kone_get_settings(struct usb_device *usb_dev,
110 struct kone_settings *buf)
111{
112 int len;
113
114 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
115 USB_REQ_CLEAR_FEATURE,
116 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
117 kone_command_settings, 0, buf,
118 sizeof(struct kone_settings), USB_CTRL_SET_TIMEOUT);
119
120 if (len != sizeof(struct kone_settings))
121 return -EIO;
122
123 return 0;
124}
125
126/*
127 * Writes settings from @buf to mouse
128 * On success returns 0
129 * On failure returns errno
130 */
131static int kone_set_settings(struct usb_device *usb_dev,
132 struct kone_settings const *settings)
133{
134 int len;
135
136 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
137 USB_REQ_SET_CONFIGURATION,
138 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
139 kone_command_settings, 0, (char *)settings,
140 sizeof(struct kone_settings),
141 USB_CTRL_SET_TIMEOUT);
142
143 if (len != sizeof(struct kone_settings))
144 return -EIO;
145
146 if (kone_check_write(usb_dev))
147 return -EIO;
148
149 return 0;
150}
151
152/*
153 * Reads profile data from mouse and stores it in @buf
154 * @number: profile number to read
155 * On success returns 0
156 * On failure returns errno
157 */
158static int kone_get_profile(struct usb_device *usb_dev,
159 struct kone_profile *buf, int number)
160{
161 int len;
162
163 if (number < 1 || number > 5)
164 return -EINVAL;
165
166 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
167 USB_REQ_CLEAR_FEATURE,
168 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
169 kone_command_profile, number, buf,
170 sizeof(struct kone_profile), USB_CTRL_SET_TIMEOUT);
171
172 if (len != sizeof(struct kone_profile))
173 return -EIO;
174
175 return 0;
176}
177
178/*
179 * Writes profile data to mouse.
180 * @number: profile number to write
181 * On success returns 0
182 * On failure returns errno
183 */
184static int kone_set_profile(struct usb_device *usb_dev,
185 struct kone_profile const *profile, int number)
186{
187 int len;
188
189 if (number < 1 || number > 5)
190 return -EINVAL;
191
192 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
193 USB_REQ_SET_CONFIGURATION,
194 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
195 kone_command_profile, number, (char *)profile,
196 sizeof(struct kone_profile),
197 USB_CTRL_SET_TIMEOUT);
198
199 if (len != sizeof(struct kone_profile))
200 return len;
201
202 if (kone_check_write(usb_dev))
203 return -EIO;
204
205 return 0;
206}
207
208/*
209 * Reads value of "fast-clip-weight" and stores it in @result
210 * On success returns 0
211 * On failure returns errno
212 */
213static int kone_get_weight(struct usb_device *usb_dev, int *result)
214{
215 int len;
216 uint8_t *data;
217
218 data = kmalloc(1, GFP_KERNEL);
219 if (!data)
220 return -ENOMEM;
221
222 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
223 USB_REQ_CLEAR_FEATURE,
224 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
225 kone_command_weight, 0, data, 1, USB_CTRL_SET_TIMEOUT);
226
227 if (len != 1) {
228 kfree(data);
229 return -EIO;
230 }
231 *result = (int)*data;
232 kfree(data);
233 return 0;
234}
235
236/*
237 * Reads firmware_version of mouse and stores it in @result
238 * On success returns 0
239 * On failure returns errno
240 */
241static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
242{
243 int len;
244 unsigned char *data;
245
246 data = kmalloc(2, GFP_KERNEL);
247 if (!data)
248 return -ENOMEM;
249
250 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
251 USB_REQ_CLEAR_FEATURE,
252 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
253 kone_command_firmware_version, 0, data, 2,
254 USB_CTRL_SET_TIMEOUT);
255
256 if (len != 2) {
257 kfree(data);
258 return -EIO;
259 }
260 *result = le16_to_cpu(*data);
261 kfree(data);
262 return 0;
263}
264
265static ssize_t kone_sysfs_read_settings(struct kobject *kobj,
266 struct bin_attribute *attr, char *buf,
267 loff_t off, size_t count) {
268 struct device *dev = container_of(kobj, struct device, kobj);
269 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
270
271 if (off >= sizeof(struct kone_settings))
272 return 0;
273
274 if (off + count > sizeof(struct kone_settings))
275 count = sizeof(struct kone_settings) - off;
276
277 mutex_lock(&kone->kone_lock);
278 memcpy(buf, &kone->settings + off, count);
279 mutex_unlock(&kone->kone_lock);
280
281 return count;
282}
283
284/*
285 * Writing settings automatically activates startup_profile.
286 * This function keeps values in kone_device up to date and assumes that in
287 * case of error the old data is still valid
288 */
289static ssize_t kone_sysfs_write_settings(struct kobject *kobj,
290 struct bin_attribute *attr, char *buf,
291 loff_t off, size_t count) {
292 struct device *dev = container_of(kobj, struct device, kobj);
293 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
294 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
295 int retval = 0, difference;
296
297 /* I need to get my data in one piece */
298 if (off != 0 || count != sizeof(struct kone_settings))
299 return -EINVAL;
300
301 mutex_lock(&kone->kone_lock);
302 difference = memcmp(buf, &kone->settings, sizeof(struct kone_settings));
303 if (difference) {
304 retval = kone_set_settings(usb_dev,
305 (struct kone_settings const *)buf);
306 if (!retval)
307 memcpy(&kone->settings, buf,
308 sizeof(struct kone_settings));
309 }
310 mutex_unlock(&kone->kone_lock);
311
312 if (retval)
313 return retval;
314
315 /*
316 * If we get here, treat settings as okay and update actual values
317 * according to startup_profile
318 */
319 kone->actual_profile = kone->settings.startup_profile;
320 kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
321
322 return sizeof(struct kone_settings);
323}
324
325static ssize_t kone_sysfs_read_profilex(struct kobject *kobj,
326 struct bin_attribute *attr, char *buf,
327 loff_t off, size_t count, int number) {
328 struct device *dev = container_of(kobj, struct device, kobj);
329 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
330
331 if (off >= sizeof(struct kone_profile))
332 return 0;
333
334 if (off + count > sizeof(struct kone_profile))
335 count = sizeof(struct kone_profile) - off;
336
337 mutex_lock(&kone->kone_lock);
338 memcpy(buf, &kone->profiles[number - 1], sizeof(struct kone_profile));
339 mutex_unlock(&kone->kone_lock);
340
341 return count;
342}
343
344static ssize_t kone_sysfs_read_profile1(struct kobject *kobj,
345 struct bin_attribute *attr, char *buf,
346 loff_t off, size_t count) {
347 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 1);
348}
349
350static ssize_t kone_sysfs_read_profile2(struct kobject *kobj,
351 struct bin_attribute *attr, char *buf,
352 loff_t off, size_t count) {
353 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 2);
354}
355
356static ssize_t kone_sysfs_read_profile3(struct kobject *kobj,
357 struct bin_attribute *attr, char *buf,
358 loff_t off, size_t count) {
359 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 3);
360}
361
362static ssize_t kone_sysfs_read_profile4(struct kobject *kobj,
363 struct bin_attribute *attr, char *buf,
364 loff_t off, size_t count) {
365 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 4);
366}
367
368static ssize_t kone_sysfs_read_profile5(struct kobject *kobj,
369 struct bin_attribute *attr, char *buf,
370 loff_t off, size_t count) {
371 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 5);
372}
373
374/* Writes data only if different to stored data */
375static ssize_t kone_sysfs_write_profilex(struct kobject *kobj,
376 struct bin_attribute *attr, char *buf,
377 loff_t off, size_t count, int number) {
378 struct device *dev = container_of(kobj, struct device, kobj);
379 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
380 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
381 struct kone_profile *profile;
382 int retval = 0, difference;
383
384 /* I need to get my data in one piece */
385 if (off != 0 || count != sizeof(struct kone_profile))
386 return -EINVAL;
387
388 profile = &kone->profiles[number - 1];
389
390 mutex_lock(&kone->kone_lock);
391 difference = memcmp(buf, profile, sizeof(struct kone_profile));
392 if (difference) {
393 retval = kone_set_profile(usb_dev,
394 (struct kone_profile const *)buf, number);
395 if (!retval)
396 memcpy(profile, buf, sizeof(struct kone_profile));
397 }
398 mutex_unlock(&kone->kone_lock);
399
400 if (retval)
401 return retval;
402
403 return sizeof(struct kone_profile);
404}
405
406static ssize_t kone_sysfs_write_profile1(struct kobject *kobj,
407 struct bin_attribute *attr, char *buf,
408 loff_t off, size_t count) {
409 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 1);
410}
411
412static ssize_t kone_sysfs_write_profile2(struct kobject *kobj,
413 struct bin_attribute *attr, char *buf,
414 loff_t off, size_t count) {
415 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 2);
416}
417
418static ssize_t kone_sysfs_write_profile3(struct kobject *kobj,
419 struct bin_attribute *attr, char *buf,
420 loff_t off, size_t count) {
421 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 3);
422}
423
424static ssize_t kone_sysfs_write_profile4(struct kobject *kobj,
425 struct bin_attribute *attr, char *buf,
426 loff_t off, size_t count) {
427 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 4);
428}
429
430static ssize_t kone_sysfs_write_profile5(struct kobject *kobj,
431 struct bin_attribute *attr, char *buf,
432 loff_t off, size_t count) {
433 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 5);
434}
435
436static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
437 struct device_attribute *attr, char *buf)
438{
439 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
440 return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile);
441}
442
443static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
444 struct device_attribute *attr, char *buf)
445{
446 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
447 return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi);
448}
449
450/* weight is read each time, since we don't get informed when it's changed */
451static ssize_t kone_sysfs_show_weight(struct device *dev,
452 struct device_attribute *attr, char *buf)
453{
454 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
455 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
456 int weight = 0;
457 int retval;
458
459 mutex_lock(&kone->kone_lock);
460 retval = kone_get_weight(usb_dev, &weight);
461 mutex_unlock(&kone->kone_lock);
462
463 if (retval)
464 return retval;
465 return snprintf(buf, PAGE_SIZE, "%d\n", weight);
466}
467
468static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
469 struct device_attribute *attr, char *buf)
470{
471 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
472 return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version);
473}
474
475static ssize_t kone_sysfs_show_tcu(struct device *dev,
476 struct device_attribute *attr, char *buf)
477{
478 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
479 return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.tcu);
480}
481
482static int kone_tcu_command(struct usb_device *usb_dev, int number)
483{
484 int len;
485 char *value;
486
487 value = kmalloc(1, GFP_KERNEL);
488 if (!value)
489 return -ENOMEM;
490
491 *value = number;
492
493 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
494 USB_REQ_SET_CONFIGURATION,
495 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
496 kone_command_calibrate, 0, value, 1,
497 USB_CTRL_SET_TIMEOUT);
498
499 kfree(value);
500 return ((len != 1) ? -EIO : 0);
501}
502
503/*
504 * Calibrating the tcu is the only action that changes settings data inside the
505 * mouse, so this data needs to be reread
506 */
507static ssize_t kone_sysfs_set_tcu(struct device *dev,
508 struct device_attribute *attr, char const *buf, size_t size)
509{
510 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
511 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
512 int retval;
513 unsigned long state;
514
515 retval = strict_strtoul(buf, 10, &state);
516 if (retval)
517 return retval;
518
519 if (state != 0 && state != 1)
520 return -EINVAL;
521
522 mutex_lock(&kone->kone_lock);
523
524 if (state == 1) { /* state activate */
525 retval = kone_tcu_command(usb_dev, 1);
526 if (retval)
527 goto exit_unlock;
528 retval = kone_tcu_command(usb_dev, 2);
529 if (retval)
530 goto exit_unlock;
531 ssleep(5); /* tcu needs this time for calibration */
532 retval = kone_tcu_command(usb_dev, 3);
533 if (retval)
534 goto exit_unlock;
535 retval = kone_tcu_command(usb_dev, 0);
536 if (retval)
537 goto exit_unlock;
538 retval = kone_tcu_command(usb_dev, 4);
539 if (retval)
540 goto exit_unlock;
541 /*
542 * Kone needs this time to settle things.
543 * Reading settings too early will result in invalid data.
544 * Roccat's driver waits 1 sec, maybe this time could be
545 * shortened.
546 */
547 ssleep(1);
548 }
549
550 /* calibration changes values in settings, so reread */
551 retval = kone_get_settings(usb_dev, &kone->settings);
552 if (retval)
553 goto exit_no_settings;
554
555 /* only write settings back if activation state is different */
556 if (kone->settings.tcu != state) {
557 kone->settings.tcu = state;
558 kone_set_settings_checksum(&kone->settings);
559
560 retval = kone_set_settings(usb_dev, &kone->settings);
561 if (retval) {
562 dev_err(&usb_dev->dev, "couldn't set tcu state\n");
563 /*
564 * try to reread valid settings into buffer overwriting
565 * first error code
566 */
567 retval = kone_get_settings(usb_dev, &kone->settings);
568 if (retval)
569 goto exit_no_settings;
570 goto exit_unlock;
571 }
572 }
573
574 retval = size;
575exit_no_settings:
576 dev_err(&usb_dev->dev, "couldn't read settings\n");
577exit_unlock:
578 mutex_unlock(&kone->kone_lock);
579 return retval;
580}
581
582static ssize_t kone_sysfs_show_startup_profile(struct device *dev,
583 struct device_attribute *attr, char *buf)
584{
585 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
586 return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.startup_profile);
587}
588
589static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
590 struct device_attribute *attr, char const *buf, size_t size)
591{
592 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
593 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
594 int retval;
595 unsigned long new_startup_profile;
596
597 retval = strict_strtoul(buf, 10, &new_startup_profile);
598 if (retval)
599 return retval;
600
601 if (new_startup_profile < 1 || new_startup_profile > 5)
602 return -EINVAL;
603
604 mutex_lock(&kone->kone_lock);
605
606 kone->settings.startup_profile = new_startup_profile;
607 kone_set_settings_checksum(&kone->settings);
608
609 retval = kone_set_settings(usb_dev, &kone->settings);
610
611 mutex_unlock(&kone->kone_lock);
612
613 if (retval)
614 return retval;
615
616 /* changing the startup profile immediately activates this profile */
617 kone->actual_profile = new_startup_profile;
618 kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
619
620 return size;
621}
622
623/*
624 * This file is used by userland software to find devices that are handled by
625 * this driver. This provides a consistent way for actual and older kernels
626 * where this driver replaced usbhid instead of generic-usb.
627 * Driver capabilities are determined by version number.
628 */
629static ssize_t kone_sysfs_show_driver_version(struct device *dev,
630 struct device_attribute *attr, char *buf)
631{
632 return snprintf(buf, PAGE_SIZE, DRIVER_VERSION "\n");
633}
634
635/*
636 * Read actual dpi settings.
637 * Returns raw value for further processing. Refer to enum kone_polling_rates to
638 * get real value.
639 */
640static DEVICE_ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL);
641
642static DEVICE_ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL);
643
644/*
645 * The mouse can be equipped with one of four supplied weights from 5 to 20
646 * grams which are recognized and its value can be read out.
647 * This returns the raw value reported by the mouse for easy evaluation by
648 * software. Refer to enum kone_weights to get corresponding real weight.
649 */
650static DEVICE_ATTR(weight, 0440, kone_sysfs_show_weight, NULL);
651
652/*
653 * Prints firmware version stored in mouse as integer.
654 * The raw value reported by the mouse is returned for easy evaluation, to get
655 * the real version number the decimal point has to be shifted 2 positions to
656 * the left. E.g. a value of 138 means 1.38.
657 */
658static DEVICE_ATTR(firmware_version, 0440,
659 kone_sysfs_show_firmware_version, NULL);
660
661/*
662 * Prints state of Tracking Control Unit as number where 0 = off and 1 = on
663 * Writing 0 deactivates tcu and writing 1 calibrates and activates the tcu
664 */
665static DEVICE_ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu);
666
667/* Prints and takes the number of the profile the mouse starts with */
668static DEVICE_ATTR(startup_profile, 0660,
669 kone_sysfs_show_startup_profile,
670 kone_sysfs_set_startup_profile);
671
672static DEVICE_ATTR(kone_driver_version, 0440,
673 kone_sysfs_show_driver_version, NULL);
674
675static struct attribute *kone_attributes[] = {
676 &dev_attr_actual_dpi.attr,
677 &dev_attr_actual_profile.attr,
678 &dev_attr_weight.attr,
679 &dev_attr_firmware_version.attr,
680 &dev_attr_tcu.attr,
681 &dev_attr_startup_profile.attr,
682 &dev_attr_kone_driver_version.attr,
683 NULL
684};
685
686static struct attribute_group kone_attribute_group = {
687 .attrs = kone_attributes
688};
689
690static struct bin_attribute kone_settings_attr = {
691 .attr = { .name = "settings", .mode = 0660 },
692 .size = sizeof(struct kone_settings),
693 .read = kone_sysfs_read_settings,
694 .write = kone_sysfs_write_settings
695};
696
697static struct bin_attribute kone_profile1_attr = {
698 .attr = { .name = "profile1", .mode = 0660 },
699 .size = sizeof(struct kone_profile),
700 .read = kone_sysfs_read_profile1,
701 .write = kone_sysfs_write_profile1
702};
703
704static struct bin_attribute kone_profile2_attr = {
705 .attr = { .name = "profile2", .mode = 0660 },
706 .size = sizeof(struct kone_profile),
707 .read = kone_sysfs_read_profile2,
708 .write = kone_sysfs_write_profile2
709};
710
711static struct bin_attribute kone_profile3_attr = {
712 .attr = { .name = "profile3", .mode = 0660 },
713 .size = sizeof(struct kone_profile),
714 .read = kone_sysfs_read_profile3,
715 .write = kone_sysfs_write_profile3
716};
717
718static struct bin_attribute kone_profile4_attr = {
719 .attr = { .name = "profile4", .mode = 0660 },
720 .size = sizeof(struct kone_profile),
721 .read = kone_sysfs_read_profile4,
722 .write = kone_sysfs_write_profile4
723};
724
725static struct bin_attribute kone_profile5_attr = {
726 .attr = { .name = "profile5", .mode = 0660 },
727 .size = sizeof(struct kone_profile),
728 .read = kone_sysfs_read_profile5,
729 .write = kone_sysfs_write_profile5
730};
731
732static int kone_create_sysfs_attributes(struct usb_interface *intf)
733{
734 int retval;
735
736 retval = sysfs_create_group(&intf->dev.kobj, &kone_attribute_group);
737 if (retval)
738 goto exit_1;
739
740 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_settings_attr);
741 if (retval)
742 goto exit_2;
743
744 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile1_attr);
745 if (retval)
746 goto exit_3;
747
748 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile2_attr);
749 if (retval)
750 goto exit_4;
751
752 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile3_attr);
753 if (retval)
754 goto exit_5;
755
756 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile4_attr);
757 if (retval)
758 goto exit_6;
759
760 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile5_attr);
761 if (retval)
762 goto exit_7;
763
764 return 0;
765
766exit_7:
767 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr);
768exit_6:
769 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr);
770exit_5:
771 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr);
772exit_4:
773 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr);
774exit_3:
775 sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr);
776exit_2:
777 sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group);
778exit_1:
779 return retval;
780}
781
782static void kone_remove_sysfs_attributes(struct usb_interface *intf)
783{
784 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile5_attr);
785 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr);
786 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr);
787 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr);
788 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr);
789 sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr);
790 sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group);
791}
792
793static int kone_init_kone_device_struct(struct usb_device *usb_dev,
794 struct kone_device *kone)
795{
796 uint i;
797 int retval;
798
799 mutex_init(&kone->kone_lock);
800
801 for (i = 0; i < 5; ++i) {
802 retval = kone_get_profile(usb_dev, &kone->profiles[i], i + 1);
803 if (retval)
804 return retval;
805 }
806
807 retval = kone_get_settings(usb_dev, &kone->settings);
808 if (retval)
809 return retval;
810
811 retval = kone_get_firmware_version(usb_dev, &kone->firmware_version);
812 if (retval)
813 return retval;
814
815 kone->actual_profile = kone->settings.startup_profile;
816 kone->actual_dpi = kone->profiles[kone->actual_profile].startup_dpi;
817
818 return 0;
819}
820
821/*
822 * Since IGNORE_MOUSE quirk moved to hid-apple, there is no way to bind only to
823 * mousepart if usb_hid is compiled into the kernel and kone is compiled as
824 * module.
825 * Secial behaviour is bound only to mousepart since only mouseevents contain
826 * additional notifications.
827 */
828static int kone_init_specials(struct hid_device *hdev)
829{
830 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
831 struct usb_device *usb_dev = interface_to_usbdev(intf);
832 struct kone_device *kone;
833 int retval;
834
835 if (intf->cur_altsetting->desc.bInterfaceProtocol
836 == USB_INTERFACE_PROTOCOL_MOUSE) {
837
838 kone = kzalloc(sizeof(*kone), GFP_KERNEL);
839 if (!kone) {
840 dev_err(&hdev->dev, "can't alloc device descriptor\n");
841 return -ENOMEM;
842 }
843 hid_set_drvdata(hdev, kone);
844
845 retval = kone_init_kone_device_struct(usb_dev, kone);
846 if (retval) {
847 dev_err(&hdev->dev,
848 "couldn't init struct kone_device\n");
849 goto exit_free;
850 }
851 retval = kone_create_sysfs_attributes(intf);
852 if (retval) {
853 dev_err(&hdev->dev, "cannot create sysfs files\n");
854 goto exit_free;
855 }
856 } else {
857 hid_set_drvdata(hdev, NULL);
858 }
859
860 return 0;
861exit_free:
862 kfree(kone);
863 return retval;
864}
865
866
867static void kone_remove_specials(struct hid_device *hdev)
868{
869 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
870
871 if (intf->cur_altsetting->desc.bInterfaceProtocol
872 == USB_INTERFACE_PROTOCOL_MOUSE) {
873 kone_remove_sysfs_attributes(intf);
874 kfree(hid_get_drvdata(hdev));
875 }
876}
877
878static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id)
879{
880 int retval;
881
882 retval = hid_parse(hdev);
883 if (retval) {
884 dev_err(&hdev->dev, "parse failed\n");
885 goto exit;
886 }
887
888 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
889 if (retval) {
890 dev_err(&hdev->dev, "hw start failed\n");
891 goto exit;
892 }
893
894 retval = kone_init_specials(hdev);
895 if (retval) {
896 dev_err(&hdev->dev, "couldn't install mouse\n");
897 goto exit_stop;
898 }
899
900 return 0;
901
902exit_stop:
903 hid_hw_stop(hdev);
904exit:
905 return retval;
906}
907
908static void kone_remove(struct hid_device *hdev)
909{
910 kone_remove_specials(hdev);
911 hid_hw_stop(hdev);
912}
913
914/*
915 * Is called for keyboard- and mousepart.
916 * Only mousepart gets informations about special events in its extended event
917 * structure.
918 */
919static int kone_raw_event(struct hid_device *hdev, struct hid_report *report,
920 u8 *data, int size)
921{
922 struct kone_device *kone = hid_get_drvdata(hdev);
923 struct kone_mouse_event *event = (struct kone_mouse_event *)data;
924
925 /* keyboard events are always processed by default handler */
926 if (size != sizeof(struct kone_mouse_event))
927 return 0;
928
929 /*
930 * Firmware 1.38 introduced new behaviour for tilt buttons.
931 * Pressed tilt button is reported in each movement event.
932 * Workaround sends only one event per press.
933 */
934 if (kone->last_tilt_state == event->tilt)
935 event->tilt = 0;
936 else
937 kone->last_tilt_state = event->tilt;
938
939 /*
940 * handle special events and keep actual profile and dpi values
941 * up to date
942 */
943 switch (event->event) {
944 case kone_mouse_event_osd_dpi:
945 dev_dbg(&hdev->dev, "osd dpi event. actual dpi %d\n",
946 event->value);
947 return 1; /* return 1 if event was handled */
948 case kone_mouse_event_switch_dpi:
949 kone->actual_dpi = event->value;
950 dev_dbg(&hdev->dev, "switched dpi to %d\n", event->value);
951 return 1;
952 case kone_mouse_event_osd_profile:
953 dev_dbg(&hdev->dev, "osd profile event. actual profile %d\n",
954 event->value);
955 return 1;
956 case kone_mouse_event_switch_profile:
957 kone->actual_profile = event->value;
958 kone->actual_dpi = kone->profiles[kone->actual_profile - 1].
959 startup_dpi;
960 dev_dbg(&hdev->dev, "switched profile to %d\n", event->value);
961 return 1;
962 case kone_mouse_event_call_overlong_macro:
963 dev_dbg(&hdev->dev, "overlong macro called, button %d %s/%s\n",
964 event->macro_key,
965 kone->profiles[kone->actual_profile - 1].
966 button_infos[event->macro_key].macro_set_name,
967 kone->profiles[kone->actual_profile - 1].
968 button_infos[event->macro_key].macro_name
969 );
970 return 1;
971 }
972
973 return 0; /* do further processing */
974}
975
976static const struct hid_device_id kone_devices[] = {
977 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
978 { }
979};
980
981MODULE_DEVICE_TABLE(hid, kone_devices);
982
983static struct hid_driver kone_driver = {
984 .name = "kone",
985 .id_table = kone_devices,
986 .probe = kone_probe,
987 .remove = kone_remove,
988 .raw_event = kone_raw_event
989};
990
991static int kone_init(void)
992{
993 return hid_register_driver(&kone_driver);
994}
995
996static void kone_exit(void)
997{
998 hid_unregister_driver(&kone_driver);
999}
1000
1001module_init(kone_init);
1002module_exit(kone_exit);
1003
1004MODULE_AUTHOR(DRIVER_AUTHOR);
1005MODULE_DESCRIPTION(DRIVER_DESC);
1006MODULE_LICENSE(DRIVER_LICENSE);
diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h
new file mode 100644
index 000000000000..ee6898c9d92c
--- /dev/null
+++ b/drivers/hid/hid-roccat-kone.h
@@ -0,0 +1,214 @@
1#ifndef __HID_ROCCAT_KONE_H
2#define __HID_ROCCAT_KONE_H
3
4/*
5 * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net>
6 */
7
8/*
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 */
14
15#include <linux/types.h>
16
17#define DRIVER_VERSION "v0.3.0"
18#define DRIVER_AUTHOR "Stefan Achatz"
19#define DRIVER_DESC "USB Roccat Kone driver"
20#define DRIVER_LICENSE "GPL v2"
21
22#pragma pack(push)
23#pragma pack(1)
24
25struct kone_keystroke {
26 uint8_t key;
27 uint8_t action;
28 uint16_t period; /* in milliseconds */
29};
30
31enum kone_keystroke_buttons {
32 kone_keystroke_button_1 = 0xf0, /* left mouse button */
33 kone_keystroke_button_2 = 0xf1, /* right mouse button */
34 kone_keystroke_button_3 = 0xf2, /* wheel */
35 kone_keystroke_button_9 = 0xf3, /* side button up */
36 kone_keystroke_button_8 = 0xf4 /* side button down */
37};
38
39enum kone_keystroke_actions {
40 kone_keystroke_action_press = 0,
41 kone_keystroke_action_release = 1
42};
43
44struct kone_button_info {
45 uint8_t number; /* range 1-8 */
46 uint8_t type;
47 uint8_t macro_type; /* 0 = short, 1 = overlong */
48 uint8_t macro_set_name[16]; /* can be max 15 chars long */
49 uint8_t macro_name[16]; /* can be max 15 chars long */
50 uint8_t count;
51 struct kone_keystroke keystrokes[20];
52};
53
54enum kone_button_info_types {
55 /* valid button types until firmware 1.32 */
56 kone_button_info_type_button_1 = 0x1, /* click (left mouse button) */
57 kone_button_info_type_button_2 = 0x2, /* menu (right mouse button)*/
58 kone_button_info_type_button_3 = 0x3, /* scroll (wheel) */
59 kone_button_info_type_double_click = 0x4,
60 kone_button_info_type_key = 0x5,
61 kone_button_info_type_macro = 0x6,
62 kone_button_info_type_off = 0x7,
63 /* TODO clarify function and rename */
64 kone_button_info_type_osd_xy_prescaling = 0x8,
65 kone_button_info_type_osd_dpi = 0x9,
66 kone_button_info_type_osd_profile = 0xa,
67 kone_button_info_type_button_9 = 0xb, /* ie forward */
68 kone_button_info_type_button_8 = 0xc, /* ie backward */
69 kone_button_info_type_dpi_up = 0xd, /* internal */
70 kone_button_info_type_dpi_down = 0xe, /* internal */
71 kone_button_info_type_button_7 = 0xf, /* tilt left */
72 kone_button_info_type_button_6 = 0x10, /* tilt right */
73 kone_button_info_type_profile_up = 0x11, /* internal */
74 kone_button_info_type_profile_down = 0x12, /* internal */
75 /* additional valid button types since firmware 1.38 */
76 kone_button_info_type_multimedia_open_player = 0x20,
77 kone_button_info_type_multimedia_next_track = 0x21,
78 kone_button_info_type_multimedia_prev_track = 0x22,
79 kone_button_info_type_multimedia_play_pause = 0x23,
80 kone_button_info_type_multimedia_stop = 0x24,
81 kone_button_info_type_multimedia_mute = 0x25,
82 kone_button_info_type_multimedia_volume_up = 0x26,
83 kone_button_info_type_multimedia_volume_down = 0x27
84};
85
86struct kone_light_info {
87 uint8_t number; /* number of light 1-5 */
88 uint8_t mod; /* 1 = on, 2 = off */
89 uint8_t red; /* range 0x00-0xff */
90 uint8_t green; /* range 0x00-0xff */
91 uint8_t blue; /* range 0x00-0xff */
92};
93
94struct kone_profile {
95 uint16_t size; /* always 975 */
96 uint16_t unused; /* always 0 */
97
98 /*
99 * range 1-5
100 * This number does not need to correspond with location where profile
101 * saved
102 */
103 uint8_t profile; /* range 1-5 */
104
105 uint16_t main_sensitivity; /* range 100-1000 */
106 uint8_t xy_sensitivity_enabled; /* 1 = on, 2 = off */
107 uint16_t x_sensitivity; /* range 100-1000 */
108 uint16_t y_sensitivity; /* range 100-1000 */
109 uint8_t dpi_rate; /* bit 1 = 800, ... */
110 uint8_t startup_dpi; /* range 1-6 */
111 uint8_t polling_rate; /* 1 = 125Hz, 2 = 500Hz, 3 = 1000Hz */
112 /* kone has no dcu
113 * value is always 2 in firmwares <= 1.32 and
114 * 1 in firmwares > 1.32
115 */
116 uint8_t dcu_flag;
117 uint8_t light_effect_1; /* range 1-3 */
118 uint8_t light_effect_2; /* range 1-5 */
119 uint8_t light_effect_3; /* range 1-4 */
120 uint8_t light_effect_speed; /* range 0-255 */
121
122 struct kone_light_info light_infos[5];
123 struct kone_button_info button_infos[8];
124
125 uint16_t checksum; /* \brief holds checksum of struct */
126};
127
128enum kone_polling_rates {
129 kone_polling_rate_125 = 1,
130 kone_polling_rate_500 = 2,
131 kone_polling_rate_1000 = 3
132};
133
134struct kone_settings {
135 uint16_t size; /* always 36 */
136 uint8_t startup_profile; /* 1-5 */
137 uint8_t unknown1;
138 uint8_t tcu; /* 0 = off, 1 = on */
139 uint8_t unknown2[23];
140 uint8_t calibration_data[4];
141 uint8_t unknown3[2];
142 uint16_t checksum;
143};
144
145/*
146 * 12 byte mouse event read by interrupt_read
147 */
148struct kone_mouse_event {
149 uint8_t report_number; /* always 1 */
150 uint8_t button;
151 uint16_t x;
152 uint16_t y;
153 uint8_t wheel; /* up = 1, down = -1 */
154 uint8_t tilt; /* right = 1, left = -1 */
155 uint8_t unknown;
156 uint8_t event;
157 uint8_t value; /* press = 0, release = 1 */
158 uint8_t macro_key; /* 0 to 8 */
159};
160
161enum kone_mouse_events {
162 /* osd events are thought to be display on screen */
163 kone_mouse_event_osd_dpi = 0xa0,
164 kone_mouse_event_osd_profile = 0xb0,
165 /* TODO clarify meaning and occurence of kone_mouse_event_calibration */
166 kone_mouse_event_calibration = 0xc0,
167 kone_mouse_event_call_overlong_macro = 0xe0,
168 /* switch events notify if user changed values wiht mousebutton click */
169 kone_mouse_event_switch_dpi = 0xf0,
170 kone_mouse_event_switch_profile = 0xf1
171};
172
173enum kone_commands {
174 kone_command_profile = 0x5a,
175 kone_command_settings = 0x15a,
176 kone_command_firmware_version = 0x25a,
177 kone_command_weight = 0x45a,
178 kone_command_calibrate = 0x55a,
179 kone_command_confirm_write = 0x65a,
180 kone_command_firmware = 0xe5a
181};
182
183#pragma pack(pop)
184
185struct kone_device {
186 /*
187 * Storing actual values when we get informed about changes since there
188 * is no way of getting this information from the device on demand
189 */
190 int actual_profile, actual_dpi;
191 /* Used for neutralizing abnormal tilt button behaviour */
192 int last_tilt_state;
193 /*
194 * It's unlikely that multiple sysfs attributes are accessed at a time,
195 * so only one mutex is used to secure hardware access and profiles and
196 * settings of this struct.
197 */
198 struct mutex kone_lock;
199
200 /*
201 * Storing the data here reduces IO and ensures that data is available
202 * when its needed (E.g. interrupt handler).
203 */
204 struct kone_profile profiles[5];
205 struct kone_settings settings;
206
207 /*
208 * firmware doesn't change unless firmware update is implemented,
209 * so it's read only once
210 */
211 int firmware_version;
212};
213
214#endif