| 1 | |
| 2 |
|
| 3 | .. |ssam_cdev_request| replace:: :c:type:`struct ssam_cdev_request <ssam_cdev_request>`
|
| 4 | .. |ssam_cdev_request_flags| replace:: :c:type:`enum ssam_cdev_request_flags <ssam_cdev_request_flags>`
|
| 5 | .. |ssam_cdev_event| replace:: :c:type:`struct ssam_cdev_event <ssam_cdev_event>`
|
| 6 |
|
| 7 | ==============================
|
| 8 | User-Space EC Interface (cdev)
|
| 9 | ==============================
|
| 10 |
|
| 11 | The ``surface_aggregator_cdev`` module provides a misc-device for the SSAM
|
| 12 | controller to allow for a (more or less) direct connection from user-space to
|
| 13 | the SAM EC. It is intended to be used for development and debugging, and
|
| 14 | therefore should not be used or relied upon in any other way. Note that this
|
| 15 | module is not loaded automatically, but instead must be loaded manually.
|
| 16 |
|
| 17 | The provided interface is accessible through the ``/dev/surface/aggregator``
|
| 18 | device-file. All functionality of this interface is provided via IOCTLs.
|
| 19 | These IOCTLs and their respective input/output parameter structs are defined in
|
| 20 | ``include/uapi/linux/surface_aggregator/cdev.h``.
|
| 21 |
|
| 22 | A small python library and scripts for accessing this interface can be found
|
| 23 | at https://github.com/linux-surface/surface-aggregator-module/tree/master/scripts/ssam.
|
| 24 |
|
| 25 | .. contents::
|
| 26 |
|
| 27 |
|
| 28 | Receiving Events
|
| 29 | ================
|
| 30 |
|
| 31 | Events can be received by reading from the device-file. The are represented by
|
| 32 | the |ssam_cdev_event| datatype.
|
| 33 |
|
| 34 | Before events are available to be read, however, the desired notifiers must be
|
| 35 | registered via the ``SSAM_CDEV_NOTIF_REGISTER`` IOCTL. Notifiers are, in
|
| 36 | essence, callbacks, called when the EC sends an event. They are, in this
|
| 37 | interface, associated with a specific target category and device-file-instance.
|
| 38 | They forward any event of this category to the buffer of the corresponding
|
| 39 | instance, from which it can then be read.
|
| 40 |
|
| 41 | Notifiers themselves do not enable events on the EC. Thus, it may additionally
|
| 42 | be necessary to enable events via the ``SSAM_CDEV_EVENT_ENABLE`` IOCTL. While
|
| 43 | notifiers work per-client (i.e. per-device-file-instance), events are enabled
|
| 44 | globally, for the EC and all of its clients (regardless of userspace or
|
| 45 | non-userspace). The ``SSAM_CDEV_EVENT_ENABLE`` and ``SSAM_CDEV_EVENT_DISABLE``
|
| 46 | IOCTLs take care of reference counting the events, such that an event is
|
| 47 | enabled as long as there is a client that has requested it.
|
| 48 |
|
| 49 | Note that enabled events are not automatically disabled once the client
|
| 50 | instance is closed. Therefore any client process (or group of processes) should
|
| 51 | balance their event enable calls with the corresponding event disable calls. It
|
| 52 | is, however, perfectly valid to enable and disable events on different client
|
| 53 | instances. For example, it is valid to set up notifiers and read events on
|
| 54 | client instance ``A``, enable those events on instance ``B`` (note that these
|
| 55 | will also be received by A since events are enabled/disabled globally), and
|
| 56 | after no more events are desired, disable the previously enabled events via
|
| 57 | instance ``C``.
|
| 58 |
|
| 59 |
|
| 60 | Controller IOCTLs
|
| 61 | =================
|
| 62 |
|
| 63 | The following IOCTLs are provided:
|
| 64 |
|
| 65 | .. flat-table:: Controller IOCTLs
|
| 66 | :widths: 1 1 1 1 4
|
| 67 | :header-rows: 1
|
| 68 |
|
| 69 | * - Type
|
| 70 | - Number
|
| 71 | - Direction
|
| 72 | - Name
|
| 73 | - Description
|
| 74 |
|
| 75 | * - ``0xA5``
|
| 76 | - ``1``
|
| 77 | - ``WR``
|
| 78 | - ``REQUEST``
|
| 79 | - Perform synchronous SAM request.
|
| 80 |
|
| 81 | * - ``0xA5``
|
| 82 | - ``2``
|
| 83 | - ``W``
|
| 84 | - ``NOTIF_REGISTER``
|
| 85 | - Register event notifier.
|
| 86 |
|
| 87 | * - ``0xA5``
|
| 88 | - ``3``
|
| 89 | - ``W``
|
| 90 | - ``NOTIF_UNREGISTER``
|
| 91 | - Unregister event notifier.
|
| 92 |
|
| 93 | * - ``0xA5``
|
| 94 | - ``4``
|
| 95 | - ``W``
|
| 96 | - ``EVENT_ENABLE``
|
| 97 | - Enable event source.
|
| 98 |
|
| 99 | * - ``0xA5``
|
| 100 | - ``5``
|
| 101 | - ``W``
|
| 102 | - ``EVENT_DISABLE``
|
| 103 | - Disable event source.
|
| 104 |
|
| 105 |
|
| 106 | ``SSAM_CDEV_REQUEST``
|
| 107 | ---------------------
|
| 108 |
|
| 109 | Defined as ``_IOWR(0xA5, 1, struct ssam_cdev_request)``.
|
| 110 |
|
| 111 | Executes a synchronous SAM request. The request specification is passed in
|
| 112 | as argument of type |ssam_cdev_request|, which is then written to/modified
|
| 113 | by the IOCTL to return status and result of the request.
|
| 114 |
|
| 115 | Request payload data must be allocated separately and is passed in via the
|
| 116 | ``payload.data`` and ``payload.length`` members. If a response is required,
|
| 117 | the response buffer must be allocated by the caller and passed in via the
|
| 118 | ``response.data`` member. The ``response.length`` member must be set to the
|
| 119 | capacity of this buffer, or if no response is required, zero. Upon
|
| 120 | completion of the request, the call will write the response to the response
|
| 121 | buffer (if its capacity allows it) and overwrite the length field with the
|
| 122 | actual size of the response, in bytes.
|
| 123 |
|
| 124 | Additionally, if the request has a response, this must be indicated via the
|
| 125 | request flags, as is done with in-kernel requests. Request flags can be set
|
| 126 | via the ``flags`` member and the values correspond to the values found in
|
| 127 | |ssam_cdev_request_flags|.
|
| 128 |
|
| 129 | Finally, the status of the request itself is returned in the ``status``
|
| 130 | member (a negative errno value indicating failure). Note that failure
|
| 131 | indication of the IOCTL is separated from failure indication of the request:
|
| 132 | The IOCTL returns a negative status code if anything failed during setup of
|
| 133 | the request (``-EFAULT``) or if the provided argument or any of its fields
|
| 134 | are invalid (``-EINVAL``). In this case, the status value of the request
|
| 135 | argument may be set, providing more detail on what went wrong (e.g.
|
| 136 | ``-ENOMEM`` for out-of-memory), but this value may also be zero. The IOCTL
|
| 137 | will return with a zero status code in case the request has been set up,
|
| 138 | submitted, and completed (i.e. handed back to user-space) successfully from
|
| 139 | inside the IOCTL, but the request ``status`` member may still be negative in
|
| 140 | case the actual execution of the request failed after it has been submitted.
|
| 141 |
|
| 142 | A full definition of the argument struct is provided below.
|
| 143 |
|
| 144 | ``SSAM_CDEV_NOTIF_REGISTER``
|
| 145 | ----------------------------
|
| 146 |
|
| 147 | Defined as ``_IOW(0xA5, 2, struct ssam_cdev_notifier_desc)``.
|
| 148 |
|
| 149 | Register a notifier for the event target category specified in the given
|
| 150 | notifier description with the specified priority. Notifiers registration is
|
| 151 | required to receive events, but does not enable events themselves. After a
|
| 152 | notifier for a specific target category has been registered, all events of that
|
| 153 | category will be forwarded to the userspace client and can then be read from
|
| 154 | the device file instance. Note that events may have to be enabled, e.g. via the
|
| 155 | ``SSAM_CDEV_EVENT_ENABLE`` IOCTL, before the EC will send them.
|
| 156 |
|
| 157 | Only one notifier can be registered per target category and client instance. If
|
| 158 | a notifier has already been registered, this IOCTL will fail with ``-EEXIST``.
|
| 159 |
|
| 160 | Notifiers will automatically be removed when the device file instance is
|
| 161 | closed.
|
| 162 |
|
| 163 | ``SSAM_CDEV_NOTIF_UNREGISTER``
|
| 164 | ------------------------------
|
| 165 |
|
| 166 | Defined as ``_IOW(0xA5, 3, struct ssam_cdev_notifier_desc)``.
|
| 167 |
|
| 168 | Unregisters the notifier associated with the specified target category. The
|
| 169 | priority field will be ignored by this IOCTL. If no notifier has been
|
| 170 | registered for this client instance and the given category, this IOCTL will
|
| 171 | fail with ``-ENOENT``.
|
| 172 |
|
| 173 | ``SSAM_CDEV_EVENT_ENABLE``
|
| 174 | --------------------------
|
| 175 |
|
| 176 | Defined as ``_IOW(0xA5, 4, struct ssam_cdev_event_desc)``.
|
| 177 |
|
| 178 | Enable the event associated with the given event descriptor.
|
| 179 |
|
| 180 | Note that this call will not register a notifier itself, it will only enable
|
| 181 | events on the controller. If you want to receive events by reading from the
|
| 182 | device file, you will need to register the corresponding notifier(s) on that
|
| 183 | instance.
|
| 184 |
|
| 185 | Events are not automatically disabled when the device file is closed. This must
|
| 186 | be done manually, via a call to the ``SSAM_CDEV_EVENT_DISABLE`` IOCTL.
|
| 187 |
|
| 188 | ``SSAM_CDEV_EVENT_DISABLE``
|
| 189 | ---------------------------
|
| 190 |
|
| 191 | Defined as ``_IOW(0xA5, 5, struct ssam_cdev_event_desc)``.
|
| 192 |
|
| 193 | Disable the event associated with the given event descriptor.
|
| 194 |
|
| 195 | Note that this will not unregister any notifiers. Events may still be received
|
| 196 | and forwarded to user-space after this call. The only safe way of stopping
|
| 197 | events from being received is unregistering all previously registered
|
| 198 | notifiers.
|
| 199 |
|
| 200 |
|
| 201 | Structures and Enums
|
| 202 | ====================
|
| 203 |
|
| 204 | .. kernel-doc:: include/uapi/linux/surface_aggregator/cdev.h
|