diff options
author | Ping Cheng <pinglinux@gmail.com> | 2014-09-10 15:41:31 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-09-11 04:24:14 -0400 |
commit | 912ca216b548e0fe399f300b4511b0277fb874e4 (patch) | |
tree | 28b90c720432096dd622850c16b4636508200114 /drivers/hid | |
parent | c64d883476812783e0400d37028756151d103e5c (diff) |
HID: wacom - enable LED support for Wireless Intuos5/Pro
And associate all LED/OLED to PAD device
Signed-off-by: Ping Cheng <pingc@wacom.com>
Tested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/wacom_sys.c | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index c6970e6283b4..9e4e1886828d 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #define WAC_MSG_RETRIES 5 | 18 | #define WAC_MSG_RETRIES 5 |
19 | 19 | ||
20 | #define WAC_CMD_WL_LED_CONTROL 0x03 | ||
20 | #define WAC_CMD_LED_CONTROL 0x20 | 21 | #define WAC_CMD_LED_CONTROL 0x20 |
21 | #define WAC_CMD_ICON_START 0x21 | 22 | #define WAC_CMD_ICON_START 0x21 |
22 | #define WAC_CMD_ICON_XFER 0x23 | 23 | #define WAC_CMD_ICON_XFER 0x23 |
@@ -490,8 +491,14 @@ static int wacom_led_control(struct wacom *wacom) | |||
490 | { | 491 | { |
491 | unsigned char *buf; | 492 | unsigned char *buf; |
492 | int retval; | 493 | int retval; |
494 | unsigned char report_id = WAC_CMD_LED_CONTROL; | ||
495 | int buf_size = 9; | ||
493 | 496 | ||
494 | buf = kzalloc(9, GFP_KERNEL); | 497 | if (wacom->wacom_wac.pid) { /* wireless connected */ |
498 | report_id = WAC_CMD_WL_LED_CONTROL; | ||
499 | buf_size = 13; | ||
500 | } | ||
501 | buf = kzalloc(buf_size, GFP_KERNEL); | ||
495 | if (!buf) | 502 | if (!buf) |
496 | return -ENOMEM; | 503 | return -ENOMEM; |
497 | 504 | ||
@@ -505,9 +512,16 @@ static int wacom_led_control(struct wacom *wacom) | |||
505 | int ring_led = wacom->led.select[0] & 0x03; | 512 | int ring_led = wacom->led.select[0] & 0x03; |
506 | int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03; | 513 | int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03; |
507 | int crop_lum = 0; | 514 | int crop_lum = 0; |
508 | 515 | unsigned char led_bits = (crop_lum << 4) | (ring_lum << 2) | (ring_led); | |
509 | buf[0] = WAC_CMD_LED_CONTROL; | 516 | |
510 | buf[1] = (crop_lum << 4) | (ring_lum << 2) | (ring_led); | 517 | buf[0] = report_id; |
518 | if (wacom->wacom_wac.pid) { | ||
519 | wacom_get_report(wacom->hdev, HID_FEATURE_REPORT, | ||
520 | buf, buf_size, WAC_CMD_RETRIES); | ||
521 | buf[0] = report_id; | ||
522 | buf[4] = led_bits; | ||
523 | } else | ||
524 | buf[1] = led_bits; | ||
511 | } | 525 | } |
512 | else { | 526 | else { |
513 | int led = wacom->led.select[0] | 0x4; | 527 | int led = wacom->led.select[0] | 0x4; |
@@ -516,14 +530,14 @@ static int wacom_led_control(struct wacom *wacom) | |||
516 | wacom->wacom_wac.features.type == WACOM_24HD) | 530 | wacom->wacom_wac.features.type == WACOM_24HD) |
517 | led |= (wacom->led.select[1] << 4) | 0x40; | 531 | led |= (wacom->led.select[1] << 4) | 0x40; |
518 | 532 | ||
519 | buf[0] = WAC_CMD_LED_CONTROL; | 533 | buf[0] = report_id; |
520 | buf[1] = led; | 534 | buf[1] = led; |
521 | buf[2] = wacom->led.llv; | 535 | buf[2] = wacom->led.llv; |
522 | buf[3] = wacom->led.hlv; | 536 | buf[3] = wacom->led.hlv; |
523 | buf[4] = wacom->led.img_lum; | 537 | buf[4] = wacom->led.img_lum; |
524 | } | 538 | } |
525 | 539 | ||
526 | retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, 9, | 540 | retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, buf, buf_size, |
527 | WAC_CMD_RETRIES); | 541 | WAC_CMD_RETRIES); |
528 | kfree(buf); | 542 | kfree(buf); |
529 | 543 | ||
@@ -1036,6 +1050,7 @@ static void wacom_unregister_inputs(struct wacom *wacom) | |||
1036 | input_unregister_device(wacom->wacom_wac.pad_input); | 1050 | input_unregister_device(wacom->wacom_wac.pad_input); |
1037 | wacom->wacom_wac.input = NULL; | 1051 | wacom->wacom_wac.input = NULL; |
1038 | wacom->wacom_wac.pad_input = NULL; | 1052 | wacom->wacom_wac.pad_input = NULL; |
1053 | wacom_destroy_leds(wacom); | ||
1039 | } | 1054 | } |
1040 | 1055 | ||
1041 | static int wacom_register_inputs(struct wacom *wacom) | 1056 | static int wacom_register_inputs(struct wacom *wacom) |
@@ -1073,10 +1088,17 @@ static int wacom_register_inputs(struct wacom *wacom) | |||
1073 | error = input_register_device(pad_input_dev); | 1088 | error = input_register_device(pad_input_dev); |
1074 | if (error) | 1089 | if (error) |
1075 | goto fail3; | 1090 | goto fail3; |
1091 | |||
1092 | error = wacom_initialize_leds(wacom); | ||
1093 | if (error) | ||
1094 | goto fail4; | ||
1076 | } | 1095 | } |
1077 | 1096 | ||
1078 | return 0; | 1097 | return 0; |
1079 | 1098 | ||
1099 | fail4: | ||
1100 | input_unregister_device(pad_input_dev); | ||
1101 | pad_input_dev = NULL; | ||
1080 | fail3: | 1102 | fail3: |
1081 | input_unregister_device(input_dev); | 1103 | input_unregister_device(input_dev); |
1082 | input_dev = NULL; | 1104 | input_dev = NULL; |
@@ -1151,6 +1173,7 @@ static void wacom_wireless_work(struct work_struct *work) | |||
1151 | wacom_wac1->features.name); | 1173 | wacom_wac1->features.name); |
1152 | wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max; | 1174 | wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max; |
1153 | wacom_wac1->shared->type = wacom_wac1->features.type; | 1175 | wacom_wac1->shared->type = wacom_wac1->features.type; |
1176 | wacom_wac1->pid = wacom_wac->pid; | ||
1154 | error = wacom_register_inputs(wacom1); | 1177 | error = wacom_register_inputs(wacom1); |
1155 | if (error) | 1178 | if (error) |
1156 | goto fail; | 1179 | goto fail; |
@@ -1171,6 +1194,7 @@ static void wacom_wireless_work(struct work_struct *work) | |||
1171 | "%s (WL) Pad",wacom_wac2->features.name); | 1194 | "%s (WL) Pad",wacom_wac2->features.name); |
1172 | snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX, | 1195 | snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX, |
1173 | "%s (WL) Pad", wacom_wac2->features.name); | 1196 | "%s (WL) Pad", wacom_wac2->features.name); |
1197 | wacom_wac2->pid = wacom_wac->pid; | ||
1174 | error = wacom_register_inputs(wacom2); | 1198 | error = wacom_register_inputs(wacom2); |
1175 | if (error) | 1199 | if (error) |
1176 | goto fail; | 1200 | goto fail; |
@@ -1353,21 +1377,17 @@ static int wacom_probe(struct hid_device *hdev, | |||
1353 | goto fail1; | 1377 | goto fail1; |
1354 | } | 1378 | } |
1355 | 1379 | ||
1356 | error = wacom_initialize_leds(wacom); | ||
1357 | if (error) | ||
1358 | goto fail2; | ||
1359 | |||
1360 | if (!(features->quirks & WACOM_QUIRK_MONITOR) && | 1380 | if (!(features->quirks & WACOM_QUIRK_MONITOR) && |
1361 | (features->quirks & WACOM_QUIRK_BATTERY)) { | 1381 | (features->quirks & WACOM_QUIRK_BATTERY)) { |
1362 | error = wacom_initialize_battery(wacom); | 1382 | error = wacom_initialize_battery(wacom); |
1363 | if (error) | 1383 | if (error) |
1364 | goto fail3; | 1384 | goto fail2; |
1365 | } | 1385 | } |
1366 | 1386 | ||
1367 | if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { | 1387 | if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) { |
1368 | error = wacom_register_inputs(wacom); | 1388 | error = wacom_register_inputs(wacom); |
1369 | if (error) | 1389 | if (error) |
1370 | goto fail4; | 1390 | goto fail3; |
1371 | } | 1391 | } |
1372 | 1392 | ||
1373 | if (hdev->bus == BUS_BLUETOOTH) { | 1393 | if (hdev->bus == BUS_BLUETOOTH) { |
@@ -1385,7 +1405,7 @@ static int wacom_probe(struct hid_device *hdev, | |||
1385 | error = hid_hw_start(hdev, HID_CONNECT_HIDRAW); | 1405 | error = hid_hw_start(hdev, HID_CONNECT_HIDRAW); |
1386 | if (error) { | 1406 | if (error) { |
1387 | hid_err(hdev, "hw start failed\n"); | 1407 | hid_err(hdev, "hw start failed\n"); |
1388 | goto fail5; | 1408 | goto fail4; |
1389 | } | 1409 | } |
1390 | 1410 | ||
1391 | if (features->quirks & WACOM_QUIRK_MONITOR) | 1411 | if (features->quirks & WACOM_QUIRK_MONITOR) |
@@ -1398,11 +1418,10 @@ static int wacom_probe(struct hid_device *hdev, | |||
1398 | 1418 | ||
1399 | return 0; | 1419 | return 0; |
1400 | 1420 | ||
1401 | fail5: if (hdev->bus == BUS_BLUETOOTH) | 1421 | fail4: if (hdev->bus == BUS_BLUETOOTH) |
1402 | device_remove_file(&hdev->dev, &dev_attr_speed); | 1422 | device_remove_file(&hdev->dev, &dev_attr_speed); |
1403 | wacom_unregister_inputs(wacom); | 1423 | wacom_unregister_inputs(wacom); |
1404 | fail4: wacom_destroy_battery(wacom); | 1424 | fail3: wacom_destroy_battery(wacom); |
1405 | fail3: wacom_destroy_leds(wacom); | ||
1406 | fail2: wacom_remove_shared_data(wacom_wac); | 1425 | fail2: wacom_remove_shared_data(wacom_wac); |
1407 | fail1: kfree(wacom); | 1426 | fail1: kfree(wacom); |
1408 | hid_set_drvdata(hdev, NULL); | 1427 | hid_set_drvdata(hdev, NULL); |
@@ -1420,7 +1439,6 @@ static void wacom_remove(struct hid_device *hdev) | |||
1420 | if (hdev->bus == BUS_BLUETOOTH) | 1439 | if (hdev->bus == BUS_BLUETOOTH) |
1421 | device_remove_file(&hdev->dev, &dev_attr_speed); | 1440 | device_remove_file(&hdev->dev, &dev_attr_speed); |
1422 | wacom_destroy_battery(wacom); | 1441 | wacom_destroy_battery(wacom); |
1423 | wacom_destroy_leds(wacom); | ||
1424 | wacom_remove_shared_data(&wacom->wacom_wac); | 1442 | wacom_remove_shared_data(&wacom->wacom_wac); |
1425 | 1443 | ||
1426 | hid_set_drvdata(hdev, NULL); | 1444 | hid_set_drvdata(hdev, NULL); |