Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Kernel 5.10 #80

Open
wants to merge 179 commits into
base: master
Choose a base branch
from

Conversation

Zizigola
Copy link

Support for Kernel 5.10

We aren't doing any runtime power management (and don't need to), and
even if we were it's unlikely our current suspend/resume callbacks
would be appropriate.

Furthermore, since our suspend/resume callbacks are not for runtime
power management, they don't need to (and should not) be inside
CONFIG_PM ifdef's.
These are gcc specific, but gcc by default already generates the
alignment and packing we want.
While desktop environments will also do this, this restores the
backlight level during early boot when, for example, the disk password
is being queried for.

Note that while Apple stores various settings in the EFI vars, they do
not store the keyboard backlight level there (and hence don't restore it
till the desktop comes up). I.e. there is no existing EFI var to use to
save this value, so this creates/uses a new one.
Only the fn key can be swapped, because the key is handled specially in
the driver - for all other key remappings use the console and desktop
key mapping mechanisms.

This closes #59.
An info command is now sent to the touchpad during initialization, the
result of which contains a model id (or so we think). The model id is
then used instead of the dmi info to look up the touchpad dimensions
(that information does not appear to be present in the info command
results, unfortunately). This makes the lookup more robust for future
laptops that use the same touchpads.

Additionally, the input device's vendor and product id fields are now
filled in, using Synaptics' USB vendor id for the vendor id and the
above model id for the product id. The choice of vendor id is based on
the fact that that is what is used in the kernel rmi4 driver too (see
drivers/input/rmi4/rmi_driver.h).

This addresses #64.
Most operations are reads (i.e. keyboard and touchpad events);
furthermore the read-write-change delay is only necessary when actually
switching between read and write operations. So putting the delay after
each read is in most cases unnecessary. Hence this moves the delay to
the start of the writes instead (note that because each write is
followed by a read, it follows that each write is preceded by a read,
and so the delay at the start of the write is always necessary).
Otherwise we might try to handle an interrupt on a non-enabled SPI
device.
If system wakeup via keyboard/touchpad is enabled, then the GPE is
(re)enabled by the core just before going to sleep, and consequently
when a key is pressed to wake up the system the key-release generates
another GPE which our handler then receives (before the core can
re-disable the GPE). Since the SPI device is not ready, this results
in an ugly error message in dmesg.

So we now remember when we're suspended and just ignore all GPE's while
in that state.
It will stay on while the system is suspended otherwise.

Note that we don't need to explicitly turn it back on again on resume,
as the higher layers will do that for us.
Keyboards in particular are usually expected to wake a device from sleep
by default, but since this keyboard is attached to SPI (as opposed to,
say USB) this isn't the case here. So explicitly enable it for wake.
The multitouch core already sets these capabilities, together with a
bunch of others. Furthermore, since it also generates those events but
we don't, it's best to leave the setting of those capabilities to the
mt core in the first place.
We weren't clearing the read/write-in-progress flags if reading an spi
packet failed, which could leave those set indefinitely, making it
impossible to remove the module.
efivar_entry_set_safe() returns standard status codes, not efi ones.
Thanks to Lukas Wunner for catching that.
It turns on the touchbar, and switches it between the special and
function keys when the FN key is pressed or released. In addition it
translates the raw function keys to special keys whenever in special
key mode.

Lastly, it turns the touchbar off if no input (from keyboard, touchpad,
or touchbar) is received for 60 seconds (configurable via module param).
The hid driver core assigns devices to the hid-generic driver unless an
override is present in its hid_ignore_list. Unfortunately it does not
appear to be possible to override this behaviour dynamically. This
therefore introduces a terrible hack where we watch for iBridge device
and then forcefully unregister the current hid driver, allowing us to be
assigned as the driver when we (re)register ourselves as a hid driver.

To be removed when there is a better alternative...
Workqueue callbacks are not run in an interrupt context, so don't need
to use the irqsave/irqrestore variants of the lock functions.

Also removed an unused constant and created a missing one.

And lastly ensured code indents use tabs.
Need to make sure we don't try to process input events before the touchbar
device has been set up properly.
The module parameter is now called default_idle_timeout and can only be
set at module load time. The idle_timeout settable via sysfs and will now
properly take effect immediately.

As part of this also added two new modes: an idle_timeout of 0 disables
the touchbar until the timeout is changed again; a value of -1 disables
the timeout, i.e. causes the touchbar to never turn off.
For modes are supported, mirroring those of the regular hid-apple driver:
0 - only function keys
1 - fn key press switches from special to function keys
2 - fn key press switches from function to special keys
3 - only special keys

The fn mode is a device attribute, and the default (1) can be changed on
module insert via the default_fn_mode parameter.
If the key release happened while the usb control request was in
progress, then appletb_do_tb_mode_switch() would see the current state
as the old state (since pnd_tb_mode had been reset but cut_tb_mode
hadn't been updated yet) and hence not schedule a change for the key
release.
Regular resume's definitely do not need a reset, and in fact can cause
issues as it gets triggered when enabling the touchbar after having been
turned off due to idling.
From the review by Peter Meerwald-Stadler.
The values are either set later or ignored.

From the review by Peter Meerwald-Stadler.
From the review by Peter Meerwald-Stadler.
Renamed to needs_io_start, as suggested in the review by Jonathan
Cameron.

Fixed potential concurrency issue: since this driver is attached to
multiple hid-devices, probe and other callbacks may be called
concurrently (with different hid-devices). Therefore we now remember
which hid-device is being probed and hence needs io-start (there can be
only one at any given time, due to a mutex around that respective code),
and we ensure proper memory barriers are applied when writing and
reading this hid-device value.

Lastly, set the flag during remove too, as an io-start would be needed
there too if any sub-driver's remove function needed to receive packets.
Outright removing the hid_device ensures that it isn't accidently used
again, e.g. when a module is subsequently loaded and registers its
hid_driver.
From the review by Jonathan Cameron.
From the review by Jonathan Cameron.
From the review by Peter Meerwald-Stadler.
From the reviews by Peter Meerwald-Stadler and Jonathan Cameron.
From the review by Peter Meerwald-Stadler.
We're already guaranteed to not be called with this device anymore after
this call, so no need to check for duplicate cleanups.

From the review by Jonathan Cameron.
From the review by Jonathan Cameron.
From the review by Jonathan Cameron.
From the review by Jonathan Cameron.
From the review by Jonathan Cameron.
Instead of malloc'ing them separately.

From the review by Jonathan Cameron.
The existing solution was an ugly hack: a static appleib_dev variable
was used to pass the ib_dev pointer from the acpi-probe callback to the
hid-driver probe callback. Instead we now pass this pointer via the
driver_data field of the hid_device_id. This necessitates making a copy
of the hid_driver and hid_device_id structures, though, to hold the
modified data.

From the review by Jonathan Cameron.
Apparently this is the preferred approach.

From the review by Jonathan Cameron.
idle_timeout 0 now just turns the display off, rather than completely
disabling the touch bar; -2 can be used to disable it now. Not only does
this provide useful functionality for user space, but it's also more
consistent, as only  the display is turned off when the timeout expires.

Signed-off-by: Ronald Tschalär <[email protected]>
Also put in a more explicit date for the refactoring, since it's not so
recent anymore.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants