.. | .. |
---|
7 | 7 | |
---|
8 | 8 | #include <linux/hid.h> |
---|
9 | 9 | #include <linux/module.h> |
---|
| 10 | +#include <linux/printk.h> |
---|
10 | 11 | |
---|
11 | 12 | #include "hid-ids.h" |
---|
12 | 13 | |
---|
.. | .. |
---|
15 | 16 | MODULE_LICENSE("GPL"); |
---|
16 | 17 | MODULE_INFO(key_mappings, "G1-G6 are mapped to F13-F18"); |
---|
17 | 18 | |
---|
18 | | -static int cougar_g6_is_space = 1; |
---|
19 | | -module_param_named(g6_is_space, cougar_g6_is_space, int, 0600); |
---|
| 19 | +static bool g6_is_space = true; |
---|
20 | 20 | MODULE_PARM_DESC(g6_is_space, |
---|
21 | | - "If set, G6 programmable key sends SPACE instead of F18 (0=off, 1=on) (default=1)"); |
---|
22 | | - |
---|
| 21 | + "If true, G6 programmable key sends SPACE instead of F18 (default=true)"); |
---|
23 | 22 | |
---|
24 | 23 | #define COUGAR_VENDOR_USAGE 0xff00ff00 |
---|
25 | 24 | |
---|
.. | .. |
---|
82 | 81 | static LIST_HEAD(cougar_udev_list); |
---|
83 | 82 | static DEFINE_MUTEX(cougar_udev_list_lock); |
---|
84 | 83 | |
---|
85 | | -static void cougar_fix_g6_mapping(struct hid_device *hdev) |
---|
| 84 | +/** |
---|
| 85 | + * cougar_fix_g6_mapping - configure the mapping for key G6/Spacebar |
---|
| 86 | + */ |
---|
| 87 | +static void cougar_fix_g6_mapping(void) |
---|
86 | 88 | { |
---|
87 | 89 | int i; |
---|
88 | 90 | |
---|
89 | 91 | for (i = 0; cougar_mapping[i][0]; i++) { |
---|
90 | 92 | if (cougar_mapping[i][0] == COUGAR_KEY_G6) { |
---|
91 | 93 | cougar_mapping[i][1] = |
---|
92 | | - cougar_g6_is_space ? KEY_SPACE : KEY_F18; |
---|
93 | | - hid_info(hdev, "G6 mapped to %s\n", |
---|
94 | | - cougar_g6_is_space ? "space" : "F18"); |
---|
| 94 | + g6_is_space ? KEY_SPACE : KEY_F18; |
---|
| 95 | + pr_info("cougar: G6 mapped to %s\n", |
---|
| 96 | + g6_is_space ? "space" : "F18"); |
---|
95 | 97 | return; |
---|
96 | 98 | } |
---|
97 | 99 | } |
---|
98 | | - hid_warn(hdev, "no mapping defined for G6/spacebar"); |
---|
| 100 | + pr_warn("cougar: no mappings defined for G6/spacebar"); |
---|
99 | 101 | } |
---|
100 | 102 | |
---|
101 | 103 | /* |
---|
.. | .. |
---|
154 | 156 | * Bind the device group's shared data to this cougar struct. |
---|
155 | 157 | * If no shared data exists for this group, create and initialize it. |
---|
156 | 158 | */ |
---|
157 | | -static int cougar_bind_shared_data(struct hid_device *hdev, struct cougar *cougar) |
---|
| 159 | +static int cougar_bind_shared_data(struct hid_device *hdev, |
---|
| 160 | + struct cougar *cougar) |
---|
158 | 161 | { |
---|
159 | 162 | struct cougar_shared *shared; |
---|
160 | 163 | int error = 0; |
---|
.. | .. |
---|
204 | 207 | error = hid_parse(hdev); |
---|
205 | 208 | if (error) { |
---|
206 | 209 | hid_err(hdev, "parse failed\n"); |
---|
207 | | - goto fail; |
---|
| 210 | + return error; |
---|
208 | 211 | } |
---|
209 | 212 | |
---|
210 | 213 | if (hdev->collection->usage == COUGAR_VENDOR_USAGE) { |
---|
.. | .. |
---|
216 | 219 | error = hid_hw_start(hdev, connect_mask); |
---|
217 | 220 | if (error) { |
---|
218 | 221 | hid_err(hdev, "hw start failed\n"); |
---|
219 | | - goto fail; |
---|
| 222 | + return error; |
---|
220 | 223 | } |
---|
221 | 224 | |
---|
222 | 225 | error = cougar_bind_shared_data(hdev, cougar); |
---|
.. | .. |
---|
228 | 231 | * to it. |
---|
229 | 232 | */ |
---|
230 | 233 | if (hdev->collection->usage == HID_GD_KEYBOARD) { |
---|
231 | | - cougar_fix_g6_mapping(hdev); |
---|
232 | 234 | list_for_each_entry_safe(hidinput, next, &hdev->inputs, list) { |
---|
233 | 235 | if (hidinput->registered && hidinput->input != NULL) { |
---|
234 | 236 | cougar->shared->input = hidinput->input; |
---|
.. | .. |
---|
237 | 239 | } |
---|
238 | 240 | } |
---|
239 | 241 | } else if (hdev->collection->usage == COUGAR_VENDOR_USAGE) { |
---|
| 242 | + /* Preinit the mapping table */ |
---|
| 243 | + cougar_fix_g6_mapping(); |
---|
240 | 244 | error = hid_hw_open(hdev); |
---|
241 | 245 | if (error) |
---|
242 | 246 | goto fail_stop_and_cleanup; |
---|
.. | .. |
---|
245 | 249 | |
---|
246 | 250 | fail_stop_and_cleanup: |
---|
247 | 251 | hid_hw_stop(hdev); |
---|
248 | | -fail: |
---|
249 | | - hid_set_drvdata(hdev, NULL); |
---|
250 | 252 | return error; |
---|
251 | 253 | } |
---|
252 | 254 | |
---|
.. | .. |
---|
257 | 259 | u8 *data, int size) |
---|
258 | 260 | { |
---|
259 | 261 | struct cougar *cougar; |
---|
| 262 | + struct cougar_shared *shared; |
---|
260 | 263 | unsigned char code, action; |
---|
261 | 264 | int i; |
---|
262 | 265 | |
---|
263 | 266 | cougar = hid_get_drvdata(hdev); |
---|
264 | | - if (!cougar->special_intf || !cougar->shared || |
---|
265 | | - !cougar->shared->input || !cougar->shared->enabled) |
---|
| 267 | + shared = cougar->shared; |
---|
| 268 | + if (!cougar->special_intf || !shared) |
---|
266 | 269 | return 0; |
---|
| 270 | + |
---|
| 271 | + if (!shared->enabled || !shared->input) |
---|
| 272 | + return -EPERM; |
---|
267 | 273 | |
---|
268 | 274 | code = data[COUGAR_FIELD_CODE]; |
---|
269 | 275 | action = data[COUGAR_FIELD_ACTION]; |
---|
270 | 276 | for (i = 0; cougar_mapping[i][0]; i++) { |
---|
271 | 277 | if (code == cougar_mapping[i][0]) { |
---|
272 | | - input_event(cougar->shared->input, EV_KEY, |
---|
| 278 | + input_event(shared->input, EV_KEY, |
---|
273 | 279 | cougar_mapping[i][1], action); |
---|
274 | | - input_sync(cougar->shared->input); |
---|
275 | | - return 0; |
---|
| 280 | + input_sync(shared->input); |
---|
| 281 | + return -EPERM; |
---|
276 | 282 | } |
---|
277 | 283 | } |
---|
278 | | - hid_warn(hdev, "unmapped special key code %x: ignoring\n", code); |
---|
279 | | - return 0; |
---|
| 284 | + /* Avoid warnings on the same unmapped key twice */ |
---|
| 285 | + if (action != 0) |
---|
| 286 | + hid_warn(hdev, "unmapped special key code %0x: ignoring\n", code); |
---|
| 287 | + return -EPERM; |
---|
280 | 288 | } |
---|
281 | 289 | |
---|
282 | 290 | static void cougar_remove(struct hid_device *hdev) |
---|
.. | .. |
---|
293 | 301 | hid_hw_stop(hdev); |
---|
294 | 302 | } |
---|
295 | 303 | |
---|
296 | | -static struct hid_device_id cougar_id_table[] = { |
---|
| 304 | +static int cougar_param_set_g6_is_space(const char *val, |
---|
| 305 | + const struct kernel_param *kp) |
---|
| 306 | +{ |
---|
| 307 | + int ret; |
---|
| 308 | + |
---|
| 309 | + ret = param_set_bool(val, kp); |
---|
| 310 | + if (ret) |
---|
| 311 | + return ret; |
---|
| 312 | + |
---|
| 313 | + cougar_fix_g6_mapping(); |
---|
| 314 | + |
---|
| 315 | + return 0; |
---|
| 316 | +} |
---|
| 317 | + |
---|
| 318 | +static const struct kernel_param_ops cougar_g6_is_space_ops = { |
---|
| 319 | + .set = cougar_param_set_g6_is_space, |
---|
| 320 | + .get = param_get_bool, |
---|
| 321 | +}; |
---|
| 322 | +module_param_cb(g6_is_space, &cougar_g6_is_space_ops, &g6_is_space, 0644); |
---|
| 323 | + |
---|
| 324 | +static const struct hid_device_id cougar_id_table[] = { |
---|
297 | 325 | { HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR, |
---|
298 | 326 | USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD) }, |
---|
| 327 | + { HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR, |
---|
| 328 | + USB_DEVICE_ID_COUGAR_700K_GAMING_KEYBOARD) }, |
---|
299 | 329 | {} |
---|
300 | 330 | }; |
---|
301 | 331 | MODULE_DEVICE_TABLE(hid, cougar_id_table); |
---|