| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * drivers/input/tablet/wacom_sys.c |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | */ |
|---|
| 6 | 7 | |
|---|
| 7 | 8 | /* |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 10 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 11 | | - * (at your option) any later version. |
|---|
| 12 | 9 | */ |
|---|
| 13 | 10 | |
|---|
| 14 | 11 | #include "wacom_wac.h" |
|---|
| .. | .. |
|---|
| 163 | 160 | { |
|---|
| 164 | 161 | struct wacom *wacom = hid_get_drvdata(hdev); |
|---|
| 165 | 162 | |
|---|
| 163 | + if (wacom->wacom_wac.features.type == BOOTLOADER) |
|---|
| 164 | + return 0; |
|---|
| 165 | + |
|---|
| 166 | 166 | if (size > WACOM_PKGLEN_MAX) |
|---|
| 167 | 167 | return 1; |
|---|
| 168 | 168 | |
|---|
| .. | .. |
|---|
| 250 | 250 | field->usage[i-1].hid == HID_DG_INVERT && |
|---|
| 251 | 251 | field->usage[i+1].hid == HID_DG_INRANGE) { |
|---|
| 252 | 252 | usage->hid = HID_DG_BARRELSWITCH2; |
|---|
| 253 | + } |
|---|
| 254 | + } |
|---|
| 255 | + |
|---|
| 256 | + /* |
|---|
| 257 | + * Wacom's AES devices use different vendor-defined usages to |
|---|
| 258 | + * report serial number information compared to their branded |
|---|
| 259 | + * hardware. The usages are also sometimes ill-defined and do |
|---|
| 260 | + * not have the correct logical min/max values set. Lets patch |
|---|
| 261 | + * the descriptor to use the branded usage convention and fix |
|---|
| 262 | + * the errors. |
|---|
| 263 | + */ |
|---|
| 264 | + if (usage->hid == WACOM_HID_WT_SERIALNUMBER && |
|---|
| 265 | + field->report_size == 16 && |
|---|
| 266 | + field->index + 2 < field->report->maxfield) { |
|---|
| 267 | + struct hid_field *a = field->report->field[field->index + 1]; |
|---|
| 268 | + struct hid_field *b = field->report->field[field->index + 2]; |
|---|
| 269 | + |
|---|
| 270 | + if (a->maxusage > 0 && |
|---|
| 271 | + a->usage[0].hid == HID_DG_TOOLSERIALNUMBER && |
|---|
| 272 | + a->report_size == 32 && |
|---|
| 273 | + b->maxusage > 0 && |
|---|
| 274 | + b->usage[0].hid == 0xFF000000 && |
|---|
| 275 | + b->report_size == 8) { |
|---|
| 276 | + features->quirks |= WACOM_QUIRK_AESPEN; |
|---|
| 277 | + usage->hid = WACOM_HID_WD_TOOLTYPE; |
|---|
| 278 | + field->logical_minimum = S16_MIN; |
|---|
| 279 | + field->logical_maximum = S16_MAX; |
|---|
| 280 | + a->logical_minimum = S32_MIN; |
|---|
| 281 | + a->logical_maximum = S32_MAX; |
|---|
| 282 | + b->usage[0].hid = WACOM_HID_WD_SERIALHI; |
|---|
| 283 | + b->logical_minimum = 0; |
|---|
| 284 | + b->logical_maximum = U8_MAX; |
|---|
| 253 | 285 | } |
|---|
| 254 | 286 | } |
|---|
| 255 | 287 | |
|---|
| .. | .. |
|---|
| 2095 | 2127 | |
|---|
| 2096 | 2128 | error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac); |
|---|
| 2097 | 2129 | if (error) { |
|---|
| 2098 | | - /* no pad in use on this interface */ |
|---|
| 2130 | + /* no pad events using this interface */ |
|---|
| 2099 | 2131 | input_free_device(pad_input_dev); |
|---|
| 2100 | 2132 | wacom_wac->pad_input = NULL; |
|---|
| 2101 | 2133 | pad_input_dev = NULL; |
|---|
| .. | .. |
|---|
| 2387 | 2419 | goto fail_quirks; |
|---|
| 2388 | 2420 | } |
|---|
| 2389 | 2421 | |
|---|
| 2390 | | - if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) |
|---|
| 2422 | + if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) { |
|---|
| 2391 | 2423 | error = hid_hw_open(hdev); |
|---|
| 2424 | + if (error) { |
|---|
| 2425 | + hid_err(hdev, "hw open failed\n"); |
|---|
| 2426 | + goto fail_quirks; |
|---|
| 2427 | + } |
|---|
| 2428 | + } |
|---|
| 2392 | 2429 | |
|---|
| 2393 | 2430 | wacom_set_shared_values(wacom_wac); |
|---|
| 2394 | 2431 | devres_close_group(&hdev->dev, wacom); |
|---|
| .. | .. |
|---|
| 2492 | 2529 | return; |
|---|
| 2493 | 2530 | } |
|---|
| 2494 | 2531 | |
|---|
| 2532 | +static void wacom_remote_destroy_battery(struct wacom *wacom, int index) |
|---|
| 2533 | +{ |
|---|
| 2534 | + struct wacom_remote *remote = wacom->remote; |
|---|
| 2535 | + |
|---|
| 2536 | + if (remote->remotes[index].battery.battery) { |
|---|
| 2537 | + devres_release_group(&wacom->hdev->dev, |
|---|
| 2538 | + &remote->remotes[index].battery.bat_desc); |
|---|
| 2539 | + remote->remotes[index].battery.battery = NULL; |
|---|
| 2540 | + remote->remotes[index].active_time = 0; |
|---|
| 2541 | + } |
|---|
| 2542 | +} |
|---|
| 2543 | + |
|---|
| 2495 | 2544 | static void wacom_remote_destroy_one(struct wacom *wacom, unsigned int index) |
|---|
| 2496 | 2545 | { |
|---|
| 2497 | 2546 | struct wacom_remote *remote = wacom->remote; |
|---|
| .. | .. |
|---|
| 2506 | 2555 | remote->remotes[i].registered = false; |
|---|
| 2507 | 2556 | spin_unlock_irqrestore(&remote->remote_lock, flags); |
|---|
| 2508 | 2557 | |
|---|
| 2509 | | - if (remote->remotes[i].battery.battery) |
|---|
| 2510 | | - devres_release_group(&wacom->hdev->dev, |
|---|
| 2511 | | - &remote->remotes[i].battery.bat_desc); |
|---|
| 2558 | + wacom_remote_destroy_battery(wacom, i); |
|---|
| 2512 | 2559 | |
|---|
| 2513 | 2560 | if (remote->remotes[i].group.name) |
|---|
| 2514 | 2561 | devres_release_group(&wacom->hdev->dev, |
|---|
| .. | .. |
|---|
| 2516 | 2563 | |
|---|
| 2517 | 2564 | remote->remotes[i].serial = 0; |
|---|
| 2518 | 2565 | remote->remotes[i].group.name = NULL; |
|---|
| 2519 | | - remote->remotes[i].battery.battery = NULL; |
|---|
| 2520 | 2566 | wacom->led.groups[i].select = WACOM_STATUS_UNKNOWN; |
|---|
| 2521 | 2567 | } |
|---|
| 2522 | 2568 | } |
|---|
| .. | .. |
|---|
| 2601 | 2647 | if (remote->remotes[index].battery.battery) |
|---|
| 2602 | 2648 | return 0; |
|---|
| 2603 | 2649 | |
|---|
| 2650 | + if (!remote->remotes[index].active_time) |
|---|
| 2651 | + return 0; |
|---|
| 2652 | + |
|---|
| 2604 | 2653 | if (wacom->led.groups[index].select == WACOM_STATUS_UNKNOWN) |
|---|
| 2605 | 2654 | return 0; |
|---|
| 2606 | 2655 | |
|---|
| .. | .. |
|---|
| 2616 | 2665 | { |
|---|
| 2617 | 2666 | struct wacom *wacom = container_of(work, struct wacom, remote_work); |
|---|
| 2618 | 2667 | struct wacom_remote *remote = wacom->remote; |
|---|
| 2668 | + ktime_t kt = ktime_get(); |
|---|
| 2619 | 2669 | struct wacom_remote_data data; |
|---|
| 2620 | 2670 | unsigned long flags; |
|---|
| 2621 | 2671 | unsigned int count; |
|---|
| .. | .. |
|---|
| 2641 | 2691 | for (i = 0; i < WACOM_MAX_REMOTES; i++) { |
|---|
| 2642 | 2692 | serial = data.remote[i].serial; |
|---|
| 2643 | 2693 | if (data.remote[i].connected) { |
|---|
| 2694 | + |
|---|
| 2695 | + if (kt - remote->remotes[i].active_time > WACOM_REMOTE_BATTERY_TIMEOUT |
|---|
| 2696 | + && remote->remotes[i].active_time != 0) |
|---|
| 2697 | + wacom_remote_destroy_battery(wacom, i); |
|---|
| 2644 | 2698 | |
|---|
| 2645 | 2699 | if (remote->remotes[i].serial == serial) { |
|---|
| 2646 | 2700 | wacom_remote_attach_battery(wacom, i); |
|---|
| .. | .. |
|---|
| 2725 | 2779 | wacom_wac->features = *((struct wacom_features *)id->driver_data); |
|---|
| 2726 | 2780 | features = &wacom_wac->features; |
|---|
| 2727 | 2781 | |
|---|
| 2728 | | - if (features->check_for_hid_type && features->hid_type != hdev->type) { |
|---|
| 2729 | | - error = -ENODEV; |
|---|
| 2730 | | - goto fail; |
|---|
| 2731 | | - } |
|---|
| 2782 | + if (features->check_for_hid_type && features->hid_type != hdev->type) |
|---|
| 2783 | + return -ENODEV; |
|---|
| 2732 | 2784 | |
|---|
| 2733 | 2785 | error = wacom_devm_kfifo_alloc(wacom); |
|---|
| 2734 | 2786 | if (error) |
|---|
| 2735 | | - goto fail; |
|---|
| 2787 | + return error; |
|---|
| 2736 | 2788 | |
|---|
| 2737 | 2789 | wacom_wac->hid_data.inputmode = -1; |
|---|
| 2738 | 2790 | wacom_wac->mode_report = -1; |
|---|
| .. | .. |
|---|
| 2751 | 2803 | INIT_WORK(&wacom->battery_work, wacom_battery_work); |
|---|
| 2752 | 2804 | INIT_WORK(&wacom->remote_work, wacom_remote_work); |
|---|
| 2753 | 2805 | INIT_WORK(&wacom->mode_change_work, wacom_mode_change_work); |
|---|
| 2806 | + timer_setup(&wacom->idleprox_timer, &wacom_idleprox_timeout, TIMER_DEFERRABLE); |
|---|
| 2754 | 2807 | |
|---|
| 2755 | 2808 | /* ask for the report descriptor to be loaded by HID */ |
|---|
| 2756 | 2809 | error = hid_parse(hdev); |
|---|
| 2757 | 2810 | if (error) { |
|---|
| 2758 | 2811 | hid_err(hdev, "parse failed\n"); |
|---|
| 2759 | | - goto fail; |
|---|
| 2812 | + return error; |
|---|
| 2813 | + } |
|---|
| 2814 | + |
|---|
| 2815 | + if (features->type == BOOTLOADER) { |
|---|
| 2816 | + hid_warn(hdev, "Using device in hidraw-only mode"); |
|---|
| 2817 | + return hid_hw_start(hdev, HID_CONNECT_HIDRAW); |
|---|
| 2760 | 2818 | } |
|---|
| 2761 | 2819 | |
|---|
| 2762 | 2820 | error = wacom_parse_and_register(wacom, false); |
|---|
| 2763 | 2821 | if (error) |
|---|
| 2764 | | - goto fail; |
|---|
| 2822 | + return error; |
|---|
| 2765 | 2823 | |
|---|
| 2766 | 2824 | if (hdev->bus == BUS_BLUETOOTH) { |
|---|
| 2767 | 2825 | error = device_create_file(&hdev->dev, &dev_attr_speed); |
|---|
| .. | .. |
|---|
| 2772 | 2830 | } |
|---|
| 2773 | 2831 | |
|---|
| 2774 | 2832 | return 0; |
|---|
| 2775 | | - |
|---|
| 2776 | | -fail: |
|---|
| 2777 | | - hid_set_drvdata(hdev, NULL); |
|---|
| 2778 | | - return error; |
|---|
| 2779 | 2833 | } |
|---|
| 2780 | 2834 | |
|---|
| 2781 | 2835 | static void wacom_remove(struct hid_device *hdev) |
|---|
| .. | .. |
|---|
| 2794 | 2848 | cancel_work_sync(&wacom->battery_work); |
|---|
| 2795 | 2849 | cancel_work_sync(&wacom->remote_work); |
|---|
| 2796 | 2850 | cancel_work_sync(&wacom->mode_change_work); |
|---|
| 2851 | + del_timer_sync(&wacom->idleprox_timer); |
|---|
| 2797 | 2852 | if (hdev->bus == BUS_BLUETOOTH) |
|---|
| 2798 | 2853 | device_remove_file(&hdev->dev, &dev_attr_speed); |
|---|
| 2799 | 2854 | |
|---|
| .. | .. |
|---|
| 2802 | 2857 | |
|---|
| 2803 | 2858 | if (wacom->wacom_wac.features.type != REMOTE) |
|---|
| 2804 | 2859 | wacom_release_resources(wacom); |
|---|
| 2805 | | - |
|---|
| 2806 | | - hid_set_drvdata(hdev, NULL); |
|---|
| 2807 | 2860 | } |
|---|
| 2808 | 2861 | |
|---|
| 2809 | 2862 | #ifdef CONFIG_PM |
|---|