205 lines
7.9 KiB
ReStructuredText
205 lines
7.9 KiB
ReStructuredText
.. SPDX-License-Identifier: GPL-2.0+
|
|
|
|
.. |ssam_cdev_request| replace:: :c:type:`struct ssam_cdev_request <ssam_cdev_request>`
|
|
.. |ssam_cdev_request_flags| replace:: :c:type:`enum ssam_cdev_request_flags <ssam_cdev_request_flags>`
|
|
.. |ssam_cdev_event| replace:: :c:type:`struct ssam_cdev_event <ssam_cdev_event>`
|
|
|
|
==============================
|
|
User-Space EC Interface (cdev)
|
|
==============================
|
|
|
|
The ``surface_aggregator_cdev`` module provides a misc-device for the SSAM
|
|
controller to allow for a (more or less) direct connection from user-space to
|
|
the SAM EC. It is intended to be used for development and debugging, and
|
|
therefore should not be used or relied upon in any other way. Note that this
|
|
module is not loaded automatically, but instead must be loaded manually.
|
|
|
|
The provided interface is accessible through the ``/dev/surface/aggregator``
|
|
device-file. All functionality of this interface is provided via IOCTLs.
|
|
These IOCTLs and their respective input/output parameter structs are defined in
|
|
``include/uapi/linux/surface_aggregator/cdev.h``.
|
|
|
|
A small python library and scripts for accessing this interface can be found
|
|
at https://github.com/linux-surface/surface-aggregator-module/tree/master/scripts/ssam.
|
|
|
|
.. contents::
|
|
|
|
|
|
Receiving Events
|
|
================
|
|
|
|
Events can be received by reading from the device-file. The are represented by
|
|
the |ssam_cdev_event| datatype.
|
|
|
|
Before events are available to be read, however, the desired notifiers must be
|
|
registered via the ``SSAM_CDEV_NOTIF_REGISTER`` IOCTL. Notifiers are, in
|
|
essence, callbacks, called when the EC sends an event. They are, in this
|
|
interface, associated with a specific target category and device-file-instance.
|
|
They forward any event of this category to the buffer of the corresponding
|
|
instance, from which it can then be read.
|
|
|
|
Notifiers themselves do not enable events on the EC. Thus, it may additionally
|
|
be necessary to enable events via the ``SSAM_CDEV_EVENT_ENABLE`` IOCTL. While
|
|
notifiers work per-client (i.e. per-device-file-instance), events are enabled
|
|
globally, for the EC and all of its clients (regardless of userspace or
|
|
non-userspace). The ``SSAM_CDEV_EVENT_ENABLE`` and ``SSAM_CDEV_EVENT_DISABLE``
|
|
IOCTLs take care of reference counting the events, such that an event is
|
|
enabled as long as there is a client that has requested it.
|
|
|
|
Note that enabled events are not automatically disabled once the client
|
|
instance is closed. Therefore any client process (or group of processes) should
|
|
balance their event enable calls with the corresponding event disable calls. It
|
|
is, however, perfectly valid to enable and disable events on different client
|
|
instances. For example, it is valid to set up notifiers and read events on
|
|
client instance ``A``, enable those events on instance ``B`` (note that these
|
|
will also be received by A since events are enabled/disabled globally), and
|
|
after no more events are desired, disable the previously enabled events via
|
|
instance ``C``.
|
|
|
|
|
|
Controller IOCTLs
|
|
=================
|
|
|
|
The following IOCTLs are provided:
|
|
|
|
.. flat-table:: Controller IOCTLs
|
|
:widths: 1 1 1 1 4
|
|
:header-rows: 1
|
|
|
|
* - Type
|
|
- Number
|
|
- Direction
|
|
- Name
|
|
- Description
|
|
|
|
* - ``0xA5``
|
|
- ``1``
|
|
- ``WR``
|
|
- ``REQUEST``
|
|
- Perform synchronous SAM request.
|
|
|
|
* - ``0xA5``
|
|
- ``2``
|
|
- ``W``
|
|
- ``NOTIF_REGISTER``
|
|
- Register event notifier.
|
|
|
|
* - ``0xA5``
|
|
- ``3``
|
|
- ``W``
|
|
- ``NOTIF_UNREGISTER``
|
|
- Unregister event notifier.
|
|
|
|
* - ``0xA5``
|
|
- ``4``
|
|
- ``W``
|
|
- ``EVENT_ENABLE``
|
|
- Enable event source.
|
|
|
|
* - ``0xA5``
|
|
- ``5``
|
|
- ``W``
|
|
- ``EVENT_DISABLE``
|
|
- Disable event source.
|
|
|
|
|
|
``SSAM_CDEV_REQUEST``
|
|
---------------------
|
|
|
|
Defined as ``_IOWR(0xA5, 1, struct ssam_cdev_request)``.
|
|
|
|
Executes a synchronous SAM request. The request specification is passed in
|
|
as argument of type |ssam_cdev_request|, which is then written to/modified
|
|
by the IOCTL to return status and result of the request.
|
|
|
|
Request payload data must be allocated separately and is passed in via the
|
|
``payload.data`` and ``payload.length`` members. If a response is required,
|
|
the response buffer must be allocated by the caller and passed in via the
|
|
``response.data`` member. The ``response.length`` member must be set to the
|
|
capacity of this buffer, or if no response is required, zero. Upon
|
|
completion of the request, the call will write the response to the response
|
|
buffer (if its capacity allows it) and overwrite the length field with the
|
|
actual size of the response, in bytes.
|
|
|
|
Additionally, if the request has a response, this must be indicated via the
|
|
request flags, as is done with in-kernel requests. Request flags can be set
|
|
via the ``flags`` member and the values correspond to the values found in
|
|
|ssam_cdev_request_flags|.
|
|
|
|
Finally, the status of the request itself is returned in the ``status``
|
|
member (a negative errno value indicating failure). Note that failure
|
|
indication of the IOCTL is separated from failure indication of the request:
|
|
The IOCTL returns a negative status code if anything failed during setup of
|
|
the request (``-EFAULT``) or if the provided argument or any of its fields
|
|
are invalid (``-EINVAL``). In this case, the status value of the request
|
|
argument may be set, providing more detail on what went wrong (e.g.
|
|
``-ENOMEM`` for out-of-memory), but this value may also be zero. The IOCTL
|
|
will return with a zero status code in case the request has been set up,
|
|
submitted, and completed (i.e. handed back to user-space) successfully from
|
|
inside the IOCTL, but the request ``status`` member may still be negative in
|
|
case the actual execution of the request failed after it has been submitted.
|
|
|
|
A full definition of the argument struct is provided below.
|
|
|
|
``SSAM_CDEV_NOTIF_REGISTER``
|
|
----------------------------
|
|
|
|
Defined as ``_IOW(0xA5, 2, struct ssam_cdev_notifier_desc)``.
|
|
|
|
Register a notifier for the event target category specified in the given
|
|
notifier description with the specified priority. Notifiers registration is
|
|
required to receive events, but does not enable events themselves. After a
|
|
notifier for a specific target category has been registered, all events of that
|
|
category will be forwarded to the userspace client and can then be read from
|
|
the device file instance. Note that events may have to be enabled, e.g. via the
|
|
``SSAM_CDEV_EVENT_ENABLE`` IOCTL, before the EC will send them.
|
|
|
|
Only one notifier can be registered per target category and client instance. If
|
|
a notifier has already been registered, this IOCTL will fail with ``-EEXIST``.
|
|
|
|
Notifiers will automatically be removed when the device file instance is
|
|
closed.
|
|
|
|
``SSAM_CDEV_NOTIF_UNREGISTER``
|
|
------------------------------
|
|
|
|
Defined as ``_IOW(0xA5, 3, struct ssam_cdev_notifier_desc)``.
|
|
|
|
Unregisters the notifier associated with the specified target category. The
|
|
priority field will be ignored by this IOCTL. If no notifier has been
|
|
registered for this client instance and the given category, this IOCTL will
|
|
fail with ``-ENOENT``.
|
|
|
|
``SSAM_CDEV_EVENT_ENABLE``
|
|
--------------------------
|
|
|
|
Defined as ``_IOW(0xA5, 4, struct ssam_cdev_event_desc)``.
|
|
|
|
Enable the event associated with the given event descriptor.
|
|
|
|
Note that this call will not register a notifier itself, it will only enable
|
|
events on the controller. If you want to receive events by reading from the
|
|
device file, you will need to register the corresponding notifier(s) on that
|
|
instance.
|
|
|
|
Events are not automatically disabled when the device file is closed. This must
|
|
be done manually, via a call to the ``SSAM_CDEV_EVENT_DISABLE`` IOCTL.
|
|
|
|
``SSAM_CDEV_EVENT_DISABLE``
|
|
---------------------------
|
|
|
|
Defined as ``_IOW(0xA5, 5, struct ssam_cdev_event_desc)``.
|
|
|
|
Disable the event associated with the given event descriptor.
|
|
|
|
Note that this will not unregister any notifiers. Events may still be received
|
|
and forwarded to user-space after this call. The only safe way of stopping
|
|
events from being received is unregistering all previously registered
|
|
notifiers.
|
|
|
|
|
|
Structures and Enums
|
|
====================
|
|
|
|
.. kernel-doc:: include/uapi/linux/surface_aggregator/cdev.h
|