Hi, On 10/20/20 2:15 AM, Mark Pearson wrote: > Use input device event support for notifying userspace of lap mode sensor > state changes. > > Signed-off-by: Mark Pearson <markpearson@xxxxxxxxxx> > --- > drivers/platform/x86/thinkpad_acpi.c | 75 ++++++++++++++++++++++------ > 1 file changed, 59 insertions(+), 16 deletions(-) > > diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c > index 5ddf2775fb06..c20b9902270b 100644 > --- a/drivers/platform/x86/thinkpad_acpi.c > +++ b/drivers/platform/x86/thinkpad_acpi.c > @@ -4013,7 +4013,7 @@ static bool hotkey_notify_usrevent(const u32 hkey, > } > > static void thermal_dump_all_sensors(void); > -static void proxsensor_refresh(void); > +static void proxsensor_refresh(bool palm, bool lap); > > static bool hotkey_notify_6xxx(const u32 hkey, > bool *send_acpi_ev, > @@ -4081,7 +4081,7 @@ static bool hotkey_notify_6xxx(const u32 hkey, > case TP_HKEY_EV_PALM_DETECTED: > case TP_HKEY_EV_PALM_UNDETECTED: > /* palm detected - pass on to event handler */ > - proxsensor_refresh(); > + proxsensor_refresh(true /* palm */, false /* lap */); > return true; > > default: > @@ -9929,6 +9929,23 @@ static struct ibm_struct dytc_driver_data = { > struct input_dev *tpacpi_sw_dev; > bool has_palmsensor; > bool palmsensor_state; > +bool has_lapsensor; > +bool lapsensor_state; Again, drop the global _state caching, it is not necessary. > + > +static int lapsensor_get(bool *present, bool *state) > +{ > + acpi_handle dytc_handle; > + int output; > + > + *present = false; > + if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "DYTC", &dytc_handle))) > + return -ENODEV; > + if (!acpi_evalf(dytc_handle, &output, NULL, "dd", DYTC_CMD_GET)) > + return -EIO; > + *present = true; /*If we get his far, we have lapmode support*/ > + *state = output & BIT(DYTC_GET_LAPMODE_BIT) ? true : false; > + return 0; > +} > > static int palmsensor_get(bool *present, bool *state) > { > @@ -9945,36 +9962,56 @@ static int palmsensor_get(bool *present, bool *state) > return 0; > } > > -static void proxsensor_refresh(void) > +static void proxsensor_refresh(bool palm, bool lap) There is zero shared code between the palm ==true and the lap ==true paths, please just make this 2 separate functions. And then I guess rename the original proxsensor_refresh to palmsensor_refresh (note please do this in the 2/3 patch) and add a new lapsensor_refresh > { > bool new_state; > int err; > > - if (has_palmsensor) { > + if (palm && has_palmsensor) { > err = palmsensor_get(&has_palmsensor, &new_state); > - if (err) > - return; And then you can also keep the if (err) return; construct, which is a bit cleaner (more common used) solution vs the !err way of handling errors. > - if (new_state != palmsensor_state) { > + if (!err && (new_state != palmsensor_state)) { > input_report_switch(tpacpi_sw_dev, SW_PALMREST_PROXIMITY, new_state); > input_sync(tpacpi_sw_dev); > palmsensor_state = new_state; > } > } > + > + if (lap && has_lapsensor) { > + err = lapsensor_get(&has_lapsensor, &new_state); > + if (!err && (new_state != lapsensor_state)) { > + input_report_switch(tpacpi_sw_dev, SW_LAP_PROXIMITY, new_state); > + input_sync(tpacpi_sw_dev); > + lapsensor_state = new_state; Same as with the other patch there is no need for the new_state != lapsensor_state check, the input core does this for you turning reporting the same state twice into a no-op. > + } > + } > } > > static int tpacpi_proxsensor_init(struct ibm_init_struct *iibm) > { > - int palm_err; > + int palm_err, lap_err, err; > > + /* Make sure globals are set to a sensible initial value */ > + has_palmsensor = false; > + has_lapsensor = false; > palm_err = palmsensor_get(&has_palmsensor, &palmsensor_state); > + lap_err = lapsensor_get(&has_lapsensor, &lapsensor_state); > + > /* If support isn't available (ENODEV) then don't return an error */ > - if (palm_err == -ENODEV) > + if ((palm_err == -ENODEV) && (lap_err == -ENODEV)) > return 0; return 1, see comment on previous patch. ## begin block ### > - /* For all other errors we can flag the failure */ > + /* If both sensors error out - return an error */ > + if (palm_err && lap_err) > + return palm_err ? palm_err : lap_err; > + /* > + * If just one sensor not available, we still want the input device, > + * so just flag it and carry on > + */ > if (palm_err) > - return palm_err; > + pr_info("Palm sensor returned error %d", palm_err); > + if (lap_err) > + pr_info("Lap sensor returned error %d", lap_err); ### end block ### thinkpad_acpi will typically error out completely on non -ENODEV errors and the palmsensor code from patch 2/3 also does that. Note that returning an error from a module/sub-driver's init() is fatal (causes the module to not load), so before this change the palmsensor_get call failing with a non -ENODEV error was fatal. This may seem a bit harsh, but it is how error handling in thinkpad_acpi has worked so far, so lets be consistent here. Also if now only 1 of the 2 sensors is available you will log the -ENODEV error. So this whole block should be replaced with something like this: if (palm_err && palm_err != ENODEV) return palm_err; if (lap_err && lap_err != ENODEV) return lap_err; > > - if (has_palmsensor) { > + if (has_palmsensor || has_lapsensor) { > tpacpi_sw_dev = input_allocate_device(); > if (!tpacpi_sw_dev) > return -ENOMEM; > @@ -9990,10 +10027,14 @@ static int tpacpi_proxsensor_init(struct ibm_init_struct *iibm) > input_set_capability(tpacpi_sw_dev, EV_SW, SW_PALMREST_PROXIMITY); > input_report_switch(tpacpi_sw_dev, SW_PALMREST_PROXIMITY, palmsensor_state); > } > - palm_err = input_register_device(tpacpi_sw_dev); > - if (palm_err) { > + if (has_lapsensor) { > + input_set_capability(tpacpi_sw_dev, EV_SW, SW_LAP_PROXIMITY); > + input_report_switch(tpacpi_sw_dev, SW_LAP_PROXIMITY, lapsensor_state); > + } > + err = input_register_device(tpacpi_sw_dev); > + if (err) { > input_free_device(tpacpi_sw_dev); > - return palm_err; > + return err; > } > } > return 0; > @@ -10057,8 +10098,10 @@ static void tpacpi_driver_event(const unsigned int hkey_event) > mutex_unlock(&kbdlight_mutex); > } > > - if (hkey_event == TP_HKEY_EV_THM_CSM_COMPLETED) > + if (hkey_event == TP_HKEY_EV_THM_CSM_COMPLETED) { > dytc_lapmode_refresh(); > + proxsensor_refresh(false /* palm */, true /* lap */); > + } > > } > > Otherwise this looks good to me, Regards, Hans