Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  *  HID driver for Google Hammer device.
0004  *
0005  *  Copyright (c) 2017 Google Inc.
0006  *  Author: Wei-Ning Huang <wnhuang@google.com>
0007  */
0008 
0009 /*
0010  * This program is free software; you can redistribute it and/or modify it
0011  * under the terms of the GNU General Public License as published by the Free
0012  * Software Foundation; either version 2 of the License, or (at your option)
0013  * any later version.
0014  */
0015 
0016 #include <linux/acpi.h>
0017 #include <linux/hid.h>
0018 #include <linux/input/vivaldi-fmap.h>
0019 #include <linux/leds.h>
0020 #include <linux/module.h>
0021 #include <linux/of.h>
0022 #include <linux/platform_data/cros_ec_commands.h>
0023 #include <linux/platform_data/cros_ec_proto.h>
0024 #include <linux/platform_device.h>
0025 #include <linux/pm_wakeup.h>
0026 #include <asm/unaligned.h>
0027 
0028 #include "hid-ids.h"
0029 #include "hid-vivaldi-common.h"
0030 
0031 /*
0032  * C(hrome)B(ase)A(ttached)S(witch) - switch exported by Chrome EC and reporting
0033  * state of the "Whiskers" base - attached or detached. Whiskers USB device also
0034  * reports position of the keyboard - folded or not. Combining base state and
0035  * position allows us to generate proper "Tablet mode" events.
0036  */
0037 struct cbas_ec {
0038     struct device *dev; /* The platform device (EC) */
0039     struct input_dev *input;
0040     bool base_present;
0041     bool base_folded;
0042     struct notifier_block notifier;
0043 };
0044 
0045 static struct cbas_ec cbas_ec;
0046 static DEFINE_SPINLOCK(cbas_ec_lock);
0047 static DEFINE_MUTEX(cbas_ec_reglock);
0048 
0049 static bool cbas_parse_base_state(const void *data)
0050 {
0051     u32 switches = get_unaligned_le32(data);
0052 
0053     return !!(switches & BIT(EC_MKBP_BASE_ATTACHED));
0054 }
0055 
0056 static int cbas_ec_query_base(struct cros_ec_device *ec_dev, bool get_state,
0057                   bool *state)
0058 {
0059     struct ec_params_mkbp_info *params;
0060     struct cros_ec_command *msg;
0061     int ret;
0062 
0063     msg = kzalloc(struct_size(msg, data, max(sizeof(u32), sizeof(*params))),
0064               GFP_KERNEL);
0065     if (!msg)
0066         return -ENOMEM;
0067 
0068     msg->command = EC_CMD_MKBP_INFO;
0069     msg->version = 1;
0070     msg->outsize = sizeof(*params);
0071     msg->insize = sizeof(u32);
0072     params = (struct ec_params_mkbp_info *)msg->data;
0073     params->info_type = get_state ?
0074         EC_MKBP_INFO_CURRENT : EC_MKBP_INFO_SUPPORTED;
0075     params->event_type = EC_MKBP_EVENT_SWITCH;
0076 
0077     ret = cros_ec_cmd_xfer_status(ec_dev, msg);
0078     if (ret >= 0) {
0079         if (ret != sizeof(u32)) {
0080             dev_warn(ec_dev->dev, "wrong result size: %d != %zu\n",
0081                  ret, sizeof(u32));
0082             ret = -EPROTO;
0083         } else {
0084             *state = cbas_parse_base_state(msg->data);
0085             ret = 0;
0086         }
0087     }
0088 
0089     kfree(msg);
0090 
0091     return ret;
0092 }
0093 
0094 static int cbas_ec_notify(struct notifier_block *nb,
0095                   unsigned long queued_during_suspend,
0096                   void *_notify)
0097 {
0098     struct cros_ec_device *ec = _notify;
0099     unsigned long flags;
0100     bool base_present;
0101 
0102     if (ec->event_data.event_type == EC_MKBP_EVENT_SWITCH) {
0103         base_present = cbas_parse_base_state(
0104                     &ec->event_data.data.switches);
0105         dev_dbg(cbas_ec.dev,
0106             "%s: base: %d\n", __func__, base_present);
0107 
0108         if (device_may_wakeup(cbas_ec.dev) ||
0109             !queued_during_suspend) {
0110 
0111             pm_wakeup_event(cbas_ec.dev, 0);
0112 
0113             spin_lock_irqsave(&cbas_ec_lock, flags);
0114 
0115             /*
0116              * While input layer dedupes the events, we do not want
0117              * to disrupt the state reported by the base by
0118              * overriding it with state reported by the LID. Only
0119              * report changes, as we assume that on attach the base
0120              * is not folded.
0121              */
0122             if (base_present != cbas_ec.base_present) {
0123                 input_report_switch(cbas_ec.input,
0124                             SW_TABLET_MODE,
0125                             !base_present);
0126                 input_sync(cbas_ec.input);
0127                 cbas_ec.base_present = base_present;
0128             }
0129 
0130             spin_unlock_irqrestore(&cbas_ec_lock, flags);
0131         }
0132     }
0133 
0134     return NOTIFY_OK;
0135 }
0136 
0137 static __maybe_unused int cbas_ec_resume(struct device *dev)
0138 {
0139     struct cros_ec_device *ec = dev_get_drvdata(dev->parent);
0140     bool base_present;
0141     int error;
0142 
0143     error = cbas_ec_query_base(ec, true, &base_present);
0144     if (error) {
0145         dev_warn(dev, "failed to fetch base state on resume: %d\n",
0146              error);
0147     } else {
0148         spin_lock_irq(&cbas_ec_lock);
0149 
0150         cbas_ec.base_present = base_present;
0151 
0152         /*
0153          * Only report if base is disconnected. If base is connected,
0154          * it will resend its state on resume, and we'll update it
0155          * in hammer_event().
0156          */
0157         if (!cbas_ec.base_present) {
0158             input_report_switch(cbas_ec.input, SW_TABLET_MODE, 1);
0159             input_sync(cbas_ec.input);
0160         }
0161 
0162         spin_unlock_irq(&cbas_ec_lock);
0163     }
0164 
0165     return 0;
0166 }
0167 
0168 static SIMPLE_DEV_PM_OPS(cbas_ec_pm_ops, NULL, cbas_ec_resume);
0169 
0170 static void cbas_ec_set_input(struct input_dev *input)
0171 {
0172     /* Take the lock so hammer_event() does not race with us here */
0173     spin_lock_irq(&cbas_ec_lock);
0174     cbas_ec.input = input;
0175     spin_unlock_irq(&cbas_ec_lock);
0176 }
0177 
0178 static int __cbas_ec_probe(struct platform_device *pdev)
0179 {
0180     struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
0181     struct input_dev *input;
0182     bool base_supported;
0183     int error;
0184 
0185     error = cbas_ec_query_base(ec, false, &base_supported);
0186     if (error)
0187         return error;
0188 
0189     if (!base_supported)
0190         return -ENXIO;
0191 
0192     input = devm_input_allocate_device(&pdev->dev);
0193     if (!input)
0194         return -ENOMEM;
0195 
0196     input->name = "Whiskers Tablet Mode Switch";
0197     input->id.bustype = BUS_HOST;
0198 
0199     input_set_capability(input, EV_SW, SW_TABLET_MODE);
0200 
0201     error = input_register_device(input);
0202     if (error) {
0203         dev_err(&pdev->dev, "cannot register input device: %d\n",
0204             error);
0205         return error;
0206     }
0207 
0208     /* Seed the state */
0209     error = cbas_ec_query_base(ec, true, &cbas_ec.base_present);
0210     if (error) {
0211         dev_err(&pdev->dev, "cannot query base state: %d\n", error);
0212         return error;
0213     }
0214 
0215     if (!cbas_ec.base_present)
0216         cbas_ec.base_folded = false;
0217 
0218     dev_dbg(&pdev->dev, "%s: base: %d, folded: %d\n", __func__,
0219         cbas_ec.base_present, cbas_ec.base_folded);
0220 
0221     input_report_switch(input, SW_TABLET_MODE,
0222                 !cbas_ec.base_present || cbas_ec.base_folded);
0223 
0224     cbas_ec_set_input(input);
0225 
0226     cbas_ec.dev = &pdev->dev;
0227     cbas_ec.notifier.notifier_call = cbas_ec_notify;
0228     error = blocking_notifier_chain_register(&ec->event_notifier,
0229                          &cbas_ec.notifier);
0230     if (error) {
0231         dev_err(&pdev->dev, "cannot register notifier: %d\n", error);
0232         cbas_ec_set_input(NULL);
0233         return error;
0234     }
0235 
0236     device_init_wakeup(&pdev->dev, true);
0237     return 0;
0238 }
0239 
0240 static int cbas_ec_probe(struct platform_device *pdev)
0241 {
0242     int retval;
0243 
0244     mutex_lock(&cbas_ec_reglock);
0245 
0246     if (cbas_ec.input) {
0247         retval = -EBUSY;
0248         goto out;
0249     }
0250 
0251     retval = __cbas_ec_probe(pdev);
0252 
0253 out:
0254     mutex_unlock(&cbas_ec_reglock);
0255     return retval;
0256 }
0257 
0258 static int cbas_ec_remove(struct platform_device *pdev)
0259 {
0260     struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
0261 
0262     mutex_lock(&cbas_ec_reglock);
0263 
0264     blocking_notifier_chain_unregister(&ec->event_notifier,
0265                        &cbas_ec.notifier);
0266     cbas_ec_set_input(NULL);
0267 
0268     mutex_unlock(&cbas_ec_reglock);
0269     return 0;
0270 }
0271 
0272 static const struct acpi_device_id cbas_ec_acpi_ids[] = {
0273     { "GOOG000B", 0 },
0274     { }
0275 };
0276 MODULE_DEVICE_TABLE(acpi, cbas_ec_acpi_ids);
0277 
0278 #ifdef CONFIG_OF
0279 static const struct of_device_id cbas_ec_of_match[] = {
0280     { .compatible = "google,cros-cbas" },
0281     { },
0282 };
0283 MODULE_DEVICE_TABLE(of, cbas_ec_of_match);
0284 #endif
0285 
0286 static struct platform_driver cbas_ec_driver = {
0287     .probe = cbas_ec_probe,
0288     .remove = cbas_ec_remove,
0289     .driver = {
0290         .name = "cbas_ec",
0291         .acpi_match_table = ACPI_PTR(cbas_ec_acpi_ids),
0292         .of_match_table = of_match_ptr(cbas_ec_of_match),
0293         .pm = &cbas_ec_pm_ops,
0294     },
0295 };
0296 
0297 #define MAX_BRIGHTNESS 100
0298 
0299 struct hammer_kbd_leds {
0300     struct led_classdev cdev;
0301     struct hid_device *hdev;
0302     u8 buf[2] ____cacheline_aligned;
0303 };
0304 
0305 static int hammer_kbd_brightness_set_blocking(struct led_classdev *cdev,
0306         enum led_brightness br)
0307 {
0308     struct hammer_kbd_leds *led = container_of(cdev,
0309                            struct hammer_kbd_leds,
0310                            cdev);
0311     int ret;
0312 
0313     led->buf[0] = 0;
0314     led->buf[1] = br;
0315 
0316     /*
0317      * Request USB HID device to be in Full On mode, so that sending
0318      * hardware output report and hardware raw request won't fail.
0319      */
0320     ret = hid_hw_power(led->hdev, PM_HINT_FULLON);
0321     if (ret < 0) {
0322         hid_err(led->hdev, "failed: device not resumed %d\n", ret);
0323         return ret;
0324     }
0325 
0326     ret = hid_hw_output_report(led->hdev, led->buf, sizeof(led->buf));
0327     if (ret == -ENOSYS)
0328         ret = hid_hw_raw_request(led->hdev, 0, led->buf,
0329                      sizeof(led->buf),
0330                      HID_OUTPUT_REPORT,
0331                      HID_REQ_SET_REPORT);
0332     if (ret < 0)
0333         hid_err(led->hdev, "failed to set keyboard backlight: %d\n",
0334             ret);
0335 
0336     /* Request USB HID device back to Normal Mode. */
0337     hid_hw_power(led->hdev, PM_HINT_NORMAL);
0338 
0339     return ret;
0340 }
0341 
0342 static int hammer_register_leds(struct hid_device *hdev)
0343 {
0344     struct hammer_kbd_leds *kbd_backlight;
0345 
0346     kbd_backlight = devm_kzalloc(&hdev->dev, sizeof(*kbd_backlight),
0347                      GFP_KERNEL);
0348     if (!kbd_backlight)
0349         return -ENOMEM;
0350 
0351     kbd_backlight->hdev = hdev;
0352     kbd_backlight->cdev.name = "hammer::kbd_backlight";
0353     kbd_backlight->cdev.max_brightness = MAX_BRIGHTNESS;
0354     kbd_backlight->cdev.brightness_set_blocking =
0355         hammer_kbd_brightness_set_blocking;
0356     kbd_backlight->cdev.flags = LED_HW_PLUGGABLE;
0357 
0358     /* Set backlight to 0% initially. */
0359     hammer_kbd_brightness_set_blocking(&kbd_backlight->cdev, 0);
0360 
0361     return devm_led_classdev_register(&hdev->dev, &kbd_backlight->cdev);
0362 }
0363 
0364 #define HID_UP_GOOGLEVENDOR 0xffd10000
0365 #define HID_VD_KBD_FOLDED   0x00000019
0366 #define HID_USAGE_KBD_FOLDED    (HID_UP_GOOGLEVENDOR | HID_VD_KBD_FOLDED)
0367 
0368 /* HID usage for keyboard backlight (Alphanumeric display brightness) */
0369 #define HID_AD_BRIGHTNESS   0x00140046
0370 
0371 static int hammer_input_mapping(struct hid_device *hdev, struct hid_input *hi,
0372                 struct hid_field *field,
0373                 struct hid_usage *usage,
0374                 unsigned long **bit, int *max)
0375 {
0376     if (usage->hid == HID_USAGE_KBD_FOLDED) {
0377         /*
0378          * We do not want to have this usage mapped as it will get
0379          * mixed in with "base attached" signal and delivered over
0380          * separate input device for tablet switch mode.
0381          */
0382         return -1;
0383     }
0384 
0385     return 0;
0386 }
0387 
0388 static void hammer_folded_event(struct hid_device *hdev, bool folded)
0389 {
0390     unsigned long flags;
0391 
0392     spin_lock_irqsave(&cbas_ec_lock, flags);
0393 
0394     /*
0395      * If we are getting events from Whiskers that means that it
0396      * is attached to the lid.
0397      */
0398     cbas_ec.base_present = true;
0399     cbas_ec.base_folded = folded;
0400     hid_dbg(hdev, "%s: base: %d, folded: %d\n", __func__,
0401         cbas_ec.base_present, cbas_ec.base_folded);
0402 
0403     if (cbas_ec.input) {
0404         input_report_switch(cbas_ec.input, SW_TABLET_MODE, folded);
0405         input_sync(cbas_ec.input);
0406     }
0407 
0408     spin_unlock_irqrestore(&cbas_ec_lock, flags);
0409 }
0410 
0411 static int hammer_event(struct hid_device *hid, struct hid_field *field,
0412             struct hid_usage *usage, __s32 value)
0413 {
0414     if (usage->hid == HID_USAGE_KBD_FOLDED) {
0415         hammer_folded_event(hid, value);
0416         return 1; /* We handled this event */
0417     }
0418 
0419     return 0;
0420 }
0421 
0422 static bool hammer_has_usage(struct hid_device *hdev, unsigned int report_type,
0423             unsigned application, unsigned usage)
0424 {
0425     struct hid_report_enum *re = &hdev->report_enum[report_type];
0426     struct hid_report *report;
0427     int i, j;
0428 
0429     list_for_each_entry(report, &re->report_list, list) {
0430         if (report->application != application)
0431             continue;
0432 
0433         for (i = 0; i < report->maxfield; i++) {
0434             struct hid_field *field = report->field[i];
0435 
0436             for (j = 0; j < field->maxusage; j++)
0437                 if (field->usage[j].hid == usage)
0438                     return true;
0439         }
0440     }
0441 
0442     return false;
0443 }
0444 
0445 static bool hammer_has_folded_event(struct hid_device *hdev)
0446 {
0447     return hammer_has_usage(hdev, HID_INPUT_REPORT,
0448                 HID_GD_KEYBOARD, HID_USAGE_KBD_FOLDED);
0449 }
0450 
0451 static bool hammer_has_backlight_control(struct hid_device *hdev)
0452 {
0453     return hammer_has_usage(hdev, HID_OUTPUT_REPORT,
0454                 HID_GD_KEYBOARD, HID_AD_BRIGHTNESS);
0455 }
0456 
0457 static void hammer_get_folded_state(struct hid_device *hdev)
0458 {
0459     struct hid_report *report;
0460     char *buf;
0461     int len, rlen;
0462     int a;
0463 
0464     report = hdev->report_enum[HID_INPUT_REPORT].report_id_hash[0x0];
0465 
0466     if (!report || report->maxfield < 1)
0467         return;
0468 
0469     len = hid_report_len(report) + 1;
0470 
0471     buf = kmalloc(len, GFP_KERNEL);
0472     if (!buf)
0473         return;
0474 
0475     rlen = hid_hw_raw_request(hdev, report->id, buf, len, report->type, HID_REQ_GET_REPORT);
0476 
0477     if (rlen != len) {
0478         hid_warn(hdev, "Unable to read base folded state: %d (expected %d)\n", rlen, len);
0479         goto out;
0480     }
0481 
0482     for (a = 0; a < report->maxfield; a++) {
0483         struct hid_field *field = report->field[a];
0484 
0485         if (field->usage->hid == HID_USAGE_KBD_FOLDED) {
0486             u32 value = hid_field_extract(hdev, buf+1,
0487                     field->report_offset, field->report_size);
0488 
0489             hammer_folded_event(hdev, value);
0490             break;
0491         }
0492     }
0493 
0494 out:
0495     kfree(buf);
0496 }
0497 
0498 static void hammer_stop(void *hdev)
0499 {
0500     hid_hw_stop(hdev);
0501 }
0502 
0503 static int hammer_probe(struct hid_device *hdev,
0504             const struct hid_device_id *id)
0505 {
0506     struct vivaldi_data *vdata;
0507     int error;
0508 
0509     vdata = devm_kzalloc(&hdev->dev, sizeof(*vdata), GFP_KERNEL);
0510     if (!vdata)
0511         return -ENOMEM;
0512 
0513     hid_set_drvdata(hdev, vdata);
0514 
0515     error = hid_parse(hdev);
0516     if (error)
0517         return error;
0518 
0519     error = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
0520     if (error)
0521         return error;
0522 
0523     error = devm_add_action(&hdev->dev, hammer_stop, hdev);
0524     if (error)
0525         return error;
0526 
0527     /*
0528      * We always want to poll for, and handle tablet mode events from
0529      * devices that have folded usage, even when nobody has opened the input
0530      * device. This also prevents the hid core from dropping early tablet
0531      * mode events from the device.
0532      */
0533     if (hammer_has_folded_event(hdev)) {
0534         hdev->quirks |= HID_QUIRK_ALWAYS_POLL;
0535         error = hid_hw_open(hdev);
0536         if (error)
0537             return error;
0538 
0539         hammer_get_folded_state(hdev);
0540     }
0541 
0542     if (hammer_has_backlight_control(hdev)) {
0543         error = hammer_register_leds(hdev);
0544         if (error)
0545             hid_warn(hdev,
0546                 "Failed to register keyboard backlight: %d\n",
0547                 error);
0548     }
0549 
0550     return 0;
0551 }
0552 
0553 static void hammer_remove(struct hid_device *hdev)
0554 {
0555     unsigned long flags;
0556 
0557     if (hammer_has_folded_event(hdev)) {
0558         hid_hw_close(hdev);
0559 
0560         /*
0561          * If we are disconnecting then most likely Whiskers is
0562          * being removed. Even if it is not removed, without proper
0563          * keyboard we should not stay in clamshell mode.
0564          *
0565          * The reason for doing it here and not waiting for signal
0566          * from EC, is that on some devices there are high leakage
0567          * on Whiskers pins and we do not detect disconnect reliably,
0568          * resulting in devices being stuck in clamshell mode.
0569          */
0570         spin_lock_irqsave(&cbas_ec_lock, flags);
0571         if (cbas_ec.input && cbas_ec.base_present) {
0572             input_report_switch(cbas_ec.input, SW_TABLET_MODE, 1);
0573             input_sync(cbas_ec.input);
0574         }
0575         cbas_ec.base_present = false;
0576         spin_unlock_irqrestore(&cbas_ec_lock, flags);
0577     }
0578 
0579     /* Unregistering LEDs and stopping the hardware is done via devm */
0580 }
0581 
0582 static const struct hid_device_id hammer_devices[] = {
0583     { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
0584              USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_DON) },
0585     { HID_DEVICE(BUS_USB, HID_GROUP_VIVALDI,
0586              USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_EEL) },
0587     { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
0588              USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) },
0589     { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
0590              USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MAGNEMITE) },
0591     { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
0592              USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MASTERBALL) },
0593     { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
0594              USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MOONBALL) },
0595     { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
0596              USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STAFF) },
0597     { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
0598              USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_WAND) },
0599     { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
0600              USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_WHISKERS) },
0601     { }
0602 };
0603 MODULE_DEVICE_TABLE(hid, hammer_devices);
0604 
0605 static struct hid_driver hammer_driver = {
0606     .name = "hammer",
0607     .id_table = hammer_devices,
0608     .probe = hammer_probe,
0609     .remove = hammer_remove,
0610     .feature_mapping = vivaldi_feature_mapping,
0611     .input_configured = vivaldi_input_configured,
0612     .input_mapping = hammer_input_mapping,
0613     .event = hammer_event,
0614 };
0615 
0616 static int __init hammer_init(void)
0617 {
0618     int error;
0619 
0620     error = platform_driver_register(&cbas_ec_driver);
0621     if (error)
0622         return error;
0623 
0624     error = hid_register_driver(&hammer_driver);
0625     if (error) {
0626         platform_driver_unregister(&cbas_ec_driver);
0627         return error;
0628     }
0629 
0630     return 0;
0631 }
0632 module_init(hammer_init);
0633 
0634 static void __exit hammer_exit(void)
0635 {
0636     hid_unregister_driver(&hammer_driver);
0637     platform_driver_unregister(&cbas_ec_driver);
0638 }
0639 module_exit(hammer_exit);
0640 
0641 MODULE_LICENSE("GPL");