Input: cros-ec-keyb - allow skipping keyboard registration
authorStephen Boyd <swboyd@chromium.org>
Mon, 16 May 2022 20:29:58 +0000 (13:29 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 17 May 2022 18:59:26 +0000 (11:59 -0700)
If the device is a detachable (and therefore lacks full keyboard), we may
still want to load this driver because the device might have some other
buttons or switches (e.g. volume and power buttons or a tablet mode
switch). In such case we do not want to register the "main" keyboard device
to allow userspace detect when the detachable keyboard is disconnected and
adjust the system behavior for the tablet mode.

Originally it was suggested to simply skip keyboard registration if row and
columns properties didn't exist, but that approach did not convey the
intent strongly enough and also had a slight problem for migrating existing
DTBs without updating the kernel first, so it was decided to introduce new
google,cros-ec-keyb-switches to explicitly mark devices that only have
axillary buttons and switches.

Reviewed-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Link: https://lore.kernel.org/r/20220516183452.942008-3-swboyd@chromium.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/keyboard/cros_ec_keyb.c

index fc02c54..06a90fe 100644 (file)
@@ -439,10 +439,13 @@ static __maybe_unused int cros_ec_keyb_resume(struct device *dev)
  * but the ckdev->bs_idev will remain NULL when this function exits.
  *
  * @ckdev: The keyboard device
+ * @expect_buttons_switches: Indicates that EC must report button and/or
+ *   switch events
  *
  * Returns 0 if no error or -error upon error.
  */
-static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev)
+static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev,
+                                   bool expect_buttons_switches)
 {
        struct cros_ec_device *ec_dev = ckdev->ec;
        struct device *dev = ckdev->dev;
@@ -469,7 +472,7 @@ static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev)
        switches = get_unaligned_le32(&event_data.switches);
 
        if (!buttons && !switches)
-               return 0;
+               return expect_buttons_switches ? -EINVAL : 0;
 
        /*
         * We call the non-matrix buttons/switches 'input1', if present.
@@ -520,7 +523,7 @@ static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev)
 }
 
 /**
- * cros_ec_keyb_register_bs - Register matrix keys
+ * cros_ec_keyb_register_matrix - Register matrix keys
  *
  * Handles all the bits of the keyboard driver related to matrix keys.
  *
@@ -659,12 +662,12 @@ static const struct attribute_group cros_ec_keyb_attr_group = {
        .attrs = cros_ec_keyb_attrs,
 };
 
-
 static int cros_ec_keyb_probe(struct platform_device *pdev)
 {
        struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
        struct device *dev = &pdev->dev;
        struct cros_ec_keyb *ckdev;
+       bool buttons_switches_only = device_get_match_data(dev);
        int err;
 
        if (!dev->of_node)
@@ -678,13 +681,16 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
        ckdev->dev = dev;
        dev_set_drvdata(dev, ckdev);
 
-       err = cros_ec_keyb_register_matrix(ckdev);
-       if (err) {
-               dev_err(dev, "cannot register matrix inputs: %d\n", err);
-               return err;
+       if (!buttons_switches_only) {
+               err = cros_ec_keyb_register_matrix(ckdev);
+               if (err) {
+                       dev_err(dev, "cannot register matrix inputs: %d\n",
+                               err);
+                       return err;
+               }
        }
 
-       err = cros_ec_keyb_register_bs(ckdev);
+       err = cros_ec_keyb_register_bs(ckdev, buttons_switches_only);
        if (err) {
                dev_err(dev, "cannot register non-matrix inputs: %d\n", err);
                return err;
@@ -692,7 +698,7 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
 
        err = devm_device_add_group(dev, &cros_ec_keyb_attr_group);
        if (err) {
-               dev_err(dev, "failed to create attributes. err=%d\n", err);
+               dev_err(dev, "failed to create attributes%d\n", err);
                return err;
        }
 
@@ -721,7 +727,8 @@ static int cros_ec_keyb_remove(struct platform_device *pdev)
 #ifdef CONFIG_OF
 static const struct of_device_id cros_ec_keyb_of_match[] = {
        { .compatible = "google,cros-ec-keyb" },
-       {},
+       { .compatible = "google,cros-ec-keyb-switches", .data = (void *)true },
+       {}
 };
 MODULE_DEVICE_TABLE(of, cros_ec_keyb_of_match);
 #endif