cdev.rst 7.9 KB

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