aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorStefan Achatz <erazor_de@users.sourceforge.net>2010-03-18 11:19:43 -0400
committerJiri Kosina <jkosina@suse.cz>2010-03-22 11:31:42 -0400
commit14bf62cde79423a02a590e02664ed29a36facec1 (patch)
tree09f70b52f8e189659337e817bbc56577547bfc1a /drivers/hid
parent39710479303fd3affb3e204e9a7a75cc676977b5 (diff)
HID: add driver for Roccat Kone gaming mouse
This Patch adds support for Kone gaming mouse from Roccat. It provides access to profiles, settings, firmware, weight, actual settings etc. through sysfs attributes. Event handling of this mouse differs from standard hid behaviour in that tilt button press is reported in each move event which results in strange behaviour if not handled by the driver. This is a heavily reworked version of the previously introduced driver. The changes include most of the previously raised concerns, memory leak and other fixes, code cleanups, adoption of additional achieved knowlege about the hardware and is (IMHO) a much better version than before even when I exchanged reduced USB-IO with a bigger memory consumption. I refused to implement one mentioned point: Removing the 'just-because-we-can' attributes. Motivation: Reading the clipped in weight: I'm no gamer and can't determine the usefulness of this feature but if the manufacturer implements such a feature it might make sense to someone and I would unwillingly limit the functionality besides its such a small feature. Reading the actual profile and dpi settings: Here I can testify that one can get lost of the actual settings when switching back and forth. The manufacturers windows driver has the ability for on-screen-display of the values and there is a mouse in the market that has an lcd on the underside of it to show these values. So I think this feature makes sense not only for me and shouldn't be removed. Signed-off-by: Stefan Achatz <erazor_de@users.sourceforge.net> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-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
6 files changed, 1232 insertions, 0 deletions
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