|  | .. SPDX-License-Identifier: GPL-2.0 | 
|  |  | 
|  | ========================= | 
|  | Generic Counter Interface | 
|  | ========================= | 
|  |  | 
|  | Introduction | 
|  | ============ | 
|  |  | 
|  | Counter devices are prevalent among a diverse spectrum of industries. | 
|  | The ubiquitous presence of these devices necessitates a common interface | 
|  | and standard of interaction and exposure. This driver API attempts to | 
|  | resolve the issue of duplicate code found among existing counter device | 
|  | drivers by introducing a generic counter interface for consumption. The | 
|  | Generic Counter interface enables drivers to support and expose a common | 
|  | set of components and functionality present in counter devices. | 
|  |  | 
|  | Theory | 
|  | ====== | 
|  |  | 
|  | Counter devices can vary greatly in design, but regardless of whether | 
|  | some devices are quadrature encoder counters or tally counters, all | 
|  | counter devices consist of a core set of components. This core set of | 
|  | components, shared by all counter devices, is what forms the essence of | 
|  | the Generic Counter interface. | 
|  |  | 
|  | There are three core components to a counter: | 
|  |  | 
|  | * Signal: | 
|  | Stream of data to be evaluated by the counter. | 
|  |  | 
|  | * Synapse: | 
|  | Association of a Signal, and evaluation trigger, with a Count. | 
|  |  | 
|  | * Count: | 
|  | Accumulation of the effects of connected Synapses. | 
|  |  | 
|  | SIGNAL | 
|  | ------ | 
|  | A Signal represents a stream of data. This is the input data that is | 
|  | evaluated by the counter to determine the count data; e.g. a quadrature | 
|  | signal output line of a rotary encoder. Not all counter devices provide | 
|  | user access to the Signal data, so exposure is optional for drivers. | 
|  |  | 
|  | When the Signal data is available for user access, the Generic Counter | 
|  | interface provides the following available signal values: | 
|  |  | 
|  | * SIGNAL_LOW: | 
|  | Signal line is in a low state. | 
|  |  | 
|  | * SIGNAL_HIGH: | 
|  | Signal line is in a high state. | 
|  |  | 
|  | A Signal may be associated with one or more Counts. | 
|  |  | 
|  | SYNAPSE | 
|  | ------- | 
|  | A Synapse represents the association of a Signal with a Count. Signal | 
|  | data affects respective Count data, and the Synapse represents this | 
|  | relationship. | 
|  |  | 
|  | The Synapse action mode specifies the Signal data condition that | 
|  | triggers the respective Count's count function evaluation to update the | 
|  | count data. The Generic Counter interface provides the following | 
|  | available action modes: | 
|  |  | 
|  | * None: | 
|  | Signal does not trigger the count function. In Pulse-Direction count | 
|  | function mode, this Signal is evaluated as Direction. | 
|  |  | 
|  | * Rising Edge: | 
|  | Low state transitions to high state. | 
|  |  | 
|  | * Falling Edge: | 
|  | High state transitions to low state. | 
|  |  | 
|  | * Both Edges: | 
|  | Any state transition. | 
|  |  | 
|  | A counter is defined as a set of input signals associated with count | 
|  | data that are generated by the evaluation of the state of the associated | 
|  | input signals as defined by the respective count functions. Within the | 
|  | context of the Generic Counter interface, a counter consists of Counts | 
|  | each associated with a set of Signals, whose respective Synapse | 
|  | instances represent the count function update conditions for the | 
|  | associated Counts. | 
|  |  | 
|  | A Synapse associates one Signal with one Count. | 
|  |  | 
|  | COUNT | 
|  | ----- | 
|  | A Count represents the accumulation of the effects of connected | 
|  | Synapses; i.e. the count data for a set of Signals. The Generic | 
|  | Counter interface represents the count data as a natural number. | 
|  |  | 
|  | A Count has a count function mode which represents the update behavior | 
|  | for the count data. The Generic Counter interface provides the following | 
|  | available count function modes: | 
|  |  | 
|  | * Increase: | 
|  | Accumulated count is incremented. | 
|  |  | 
|  | * Decrease: | 
|  | Accumulated count is decremented. | 
|  |  | 
|  | * Pulse-Direction: | 
|  | Rising edges on signal A updates the respective count. The input level | 
|  | of signal B determines direction. | 
|  |  | 
|  | * Quadrature: | 
|  | A pair of quadrature encoding signals are evaluated to determine | 
|  | position and direction. The following Quadrature modes are available: | 
|  |  | 
|  | - x1 A: | 
|  | If direction is forward, rising edges on quadrature pair signal A | 
|  | updates the respective count; if the direction is backward, falling | 
|  | edges on quadrature pair signal A updates the respective count. | 
|  | Quadrature encoding determines the direction. | 
|  |  | 
|  | - x1 B: | 
|  | If direction is forward, rising edges on quadrature pair signal B | 
|  | updates the respective count; if the direction is backward, falling | 
|  | edges on quadrature pair signal B updates the respective count. | 
|  | Quadrature encoding determines the direction. | 
|  |  | 
|  | - x2 A: | 
|  | Any state transition on quadrature pair signal A updates the | 
|  | respective count. Quadrature encoding determines the direction. | 
|  |  | 
|  | - x2 B: | 
|  | Any state transition on quadrature pair signal B updates the | 
|  | respective count. Quadrature encoding determines the direction. | 
|  |  | 
|  | - x4: | 
|  | Any state transition on either quadrature pair signals updates the | 
|  | respective count. Quadrature encoding determines the direction. | 
|  |  | 
|  | A Count has a set of one or more associated Synapses. | 
|  |  | 
|  | Paradigm | 
|  | ======== | 
|  |  | 
|  | The most basic counter device may be expressed as a single Count | 
|  | associated with a single Signal via a single Synapse. Take for example | 
|  | a counter device which simply accumulates a count of rising edges on a | 
|  | source input line:: | 
|  |  | 
|  | Count                Synapse        Signal | 
|  | -----                -------        ------ | 
|  | +---------------------+ | 
|  | | Data: Count         |    Rising Edge     ________ | 
|  | | Function: Increase  |  <-------------   / Source \ | 
|  | |                     |                  ____________ | 
|  | +---------------------+ | 
|  |  | 
|  | In this example, the Signal is a source input line with a pulsing | 
|  | voltage, while the Count is a persistent count value which is repeatedly | 
|  | incremented. The Signal is associated with the respective Count via a | 
|  | Synapse. The increase function is triggered by the Signal data condition | 
|  | specified by the Synapse -- in this case a rising edge condition on the | 
|  | voltage input line. In summary, the counter device existence and | 
|  | behavior is aptly represented by respective Count, Signal, and Synapse | 
|  | components: a rising edge condition triggers an increase function on an | 
|  | accumulating count datum. | 
|  |  | 
|  | A counter device is not limited to a single Signal; in fact, in theory | 
|  | many Signals may be associated with even a single Count. For example, a | 
|  | quadrature encoder counter device can keep track of position based on | 
|  | the states of two input lines:: | 
|  |  | 
|  | Count                 Synapse     Signal | 
|  | -----                 -------     ------ | 
|  | +-------------------------+ | 
|  | | Data: Position          |    Both Edges     ___ | 
|  | | Function: Quadrature x4 |  <------------   / A \ | 
|  | |                         |                 _______ | 
|  | |                         | | 
|  | |                         |    Both Edges     ___ | 
|  | |                         |  <------------   / B \ | 
|  | |                         |                 _______ | 
|  | +-------------------------+ | 
|  |  | 
|  | In this example, two Signals (quadrature encoder lines A and B) are | 
|  | associated with a single Count: a rising or falling edge on either A or | 
|  | B triggers the "Quadrature x4" function which determines the direction | 
|  | of movement and updates the respective position data. The "Quadrature | 
|  | x4" function is likely implemented in the hardware of the quadrature | 
|  | encoder counter device; the Count, Signals, and Synapses simply | 
|  | represent this hardware behavior and functionality. | 
|  |  | 
|  | Signals associated with the same Count can have differing Synapse action | 
|  | mode conditions. For example, a quadrature encoder counter device | 
|  | operating in a non-quadrature Pulse-Direction mode could have one input | 
|  | line dedicated for movement and a second input line dedicated for | 
|  | direction:: | 
|  |  | 
|  | Count                   Synapse      Signal | 
|  | -----                   -------      ------ | 
|  | +---------------------------+ | 
|  | | Data: Position            |    Rising Edge     ___ | 
|  | | Function: Pulse-Direction |  <-------------   / A \ (Movement) | 
|  | |                           |                  _______ | 
|  | |                           | | 
|  | |                           |       None         ___ | 
|  | |                           |  <-------------   / B \ (Direction) | 
|  | |                           |                  _______ | 
|  | +---------------------------+ | 
|  |  | 
|  | Only Signal A triggers the "Pulse-Direction" update function, but the | 
|  | instantaneous state of Signal B is still required in order to know the | 
|  | direction so that the position data may be properly updated. Ultimately, | 
|  | both Signals are associated with the same Count via two respective | 
|  | Synapses, but only one Synapse has an active action mode condition which | 
|  | triggers the respective count function while the other is left with a | 
|  | "None" condition action mode to indicate its respective Signal's | 
|  | availability for state evaluation despite its non-triggering mode. | 
|  |  | 
|  | Keep in mind that the Signal, Synapse, and Count are abstract | 
|  | representations which do not need to be closely married to their | 
|  | respective physical sources. This allows the user of a counter to | 
|  | divorce themselves from the nuances of physical components (such as | 
|  | whether an input line is differential or single-ended) and instead focus | 
|  | on the core idea of what the data and process represent (e.g. position | 
|  | as interpreted from quadrature encoding data). | 
|  |  | 
|  | Driver API | 
|  | ========== | 
|  |  | 
|  | Driver authors may utilize the Generic Counter interface in their code | 
|  | by including the include/linux/counter.h header file. This header file | 
|  | provides several core data structures, function prototypes, and macros | 
|  | for defining a counter device. | 
|  |  | 
|  | .. kernel-doc:: include/linux/counter.h | 
|  | :internal: | 
|  |  | 
|  | .. kernel-doc:: drivers/counter/counter-core.c | 
|  | :export: | 
|  |  | 
|  | .. kernel-doc:: drivers/counter/counter-chrdev.c | 
|  | :export: | 
|  |  | 
|  | Driver Implementation | 
|  | ===================== | 
|  |  | 
|  | To support a counter device, a driver must first allocate the available | 
|  | Counter Signals via counter_signal structures. These Signals should | 
|  | be stored as an array and set to the signals array member of an | 
|  | allocated counter_device structure before the Counter is registered to | 
|  | the system. | 
|  |  | 
|  | Counter Counts may be allocated via counter_count structures, and | 
|  | respective Counter Signal associations (Synapses) made via | 
|  | counter_synapse structures. Associated counter_synapse structures are | 
|  | stored as an array and set to the synapses array member of the | 
|  | respective counter_count structure. These counter_count structures are | 
|  | set to the counts array member of an allocated counter_device structure | 
|  | before the Counter is registered to the system. | 
|  |  | 
|  | Driver callbacks must be provided to the counter_device structure in | 
|  | order to communicate with the device: to read and write various Signals | 
|  | and Counts, and to set and get the "action mode" and "function mode" for | 
|  | various Synapses and Counts respectively. | 
|  |  | 
|  | A counter_device structure is allocated using counter_alloc() and then | 
|  | registered to the system by passing it to the counter_add() function, and | 
|  | unregistered by passing it to the counter_unregister function. There are | 
|  | device managed variants of these functions: devm_counter_alloc() and | 
|  | devm_counter_add(). | 
|  |  | 
|  | The struct counter_comp structure is used to define counter extensions | 
|  | for Signals, Synapses, and Counts. | 
|  |  | 
|  | The "type" member specifies the type of high-level data (e.g. BOOL, | 
|  | COUNT_DIRECTION, etc.) handled by this extension. The "``*_read``" and | 
|  | "``*_write``" members can then be set by the counter device driver with | 
|  | callbacks to handle that data using native C data types (i.e. u8, u64, | 
|  | etc.). | 
|  |  | 
|  | Convenience macros such as ``COUNTER_COMP_COUNT_U64`` are provided for | 
|  | use by driver authors. In particular, driver authors are expected to use | 
|  | the provided macros for standard Counter subsystem attributes in order | 
|  | to maintain a consistent interface for userspace. For example, a counter | 
|  | device driver may define several standard attributes like so:: | 
|  |  | 
|  | struct counter_comp count_ext[] = { | 
|  | COUNTER_COMP_DIRECTION(count_direction_read), | 
|  | COUNTER_COMP_ENABLE(count_enable_read, count_enable_write), | 
|  | COUNTER_COMP_CEILING(count_ceiling_read, count_ceiling_write), | 
|  | }; | 
|  |  | 
|  | This makes it simple to see, add, and modify the attributes that are | 
|  | supported by this driver ("direction", "enable", and "ceiling") and to | 
|  | maintain this code without getting lost in a web of struct braces. | 
|  |  | 
|  | Callbacks must match the function type expected for the respective | 
|  | component or extension. These function types are defined in the struct | 
|  | counter_comp structure as the "``*_read``" and "``*_write``" union | 
|  | members. | 
|  |  | 
|  | The corresponding callback prototypes for the extensions mentioned in | 
|  | the previous example above would be:: | 
|  |  | 
|  | int count_direction_read(struct counter_device *counter, | 
|  | struct counter_count *count, | 
|  | enum counter_count_direction *direction); | 
|  | int count_enable_read(struct counter_device *counter, | 
|  | struct counter_count *count, u8 *enable); | 
|  | int count_enable_write(struct counter_device *counter, | 
|  | struct counter_count *count, u8 enable); | 
|  | int count_ceiling_read(struct counter_device *counter, | 
|  | struct counter_count *count, u64 *ceiling); | 
|  | int count_ceiling_write(struct counter_device *counter, | 
|  | struct counter_count *count, u64 ceiling); | 
|  |  | 
|  | Determining the type of extension to create is a matter of scope. | 
|  |  | 
|  | * Signal extensions are attributes that expose information/control | 
|  | specific to a Signal. These types of attributes will exist under a | 
|  | Signal's directory in sysfs. | 
|  |  | 
|  | For example, if you have an invert feature for a Signal, you can have | 
|  | a Signal extension called "invert" that toggles that feature: | 
|  | /sys/bus/counter/devices/counterX/signalY/invert | 
|  |  | 
|  | * Count extensions are attributes that expose information/control | 
|  | specific to a Count. These type of attributes will exist under a | 
|  | Count's directory in sysfs. | 
|  |  | 
|  | For example, if you want to pause/unpause a Count from updating, you | 
|  | can have a Count extension called "enable" that toggles such: | 
|  | /sys/bus/counter/devices/counterX/countY/enable | 
|  |  | 
|  | * Device extensions are attributes that expose information/control | 
|  | non-specific to a particular Count or Signal. This is where you would | 
|  | put your global features or other miscellaneous functionality. | 
|  |  | 
|  | For example, if your device has an overtemp sensor, you can report the | 
|  | chip overheated via a device extension called "error_overtemp": | 
|  | /sys/bus/counter/devices/counterX/error_overtemp | 
|  |  | 
|  | Subsystem Architecture | 
|  | ====================== | 
|  |  | 
|  | Counter drivers pass and take data natively (i.e. ``u8``, ``u64``, etc.) | 
|  | and the shared counter module handles the translation between the sysfs | 
|  | interface. This guarantees a standard userspace interface for all | 
|  | counter drivers, and enables a Generic Counter chrdev interface via a | 
|  | generalized device driver ABI. | 
|  |  | 
|  | A high-level view of how a count value is passed down from a counter | 
|  | driver is exemplified by the following. The driver callbacks are first | 
|  | registered to the Counter core component for use by the Counter | 
|  | userspace interface components:: | 
|  |  | 
|  | Driver callbacks registration: | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
|  | +----------------------------+ | 
|  | | Counter device driver      | | 
|  | +----------------------------+ | 
|  | | Processes data from device | | 
|  | +----------------------------+ | 
|  | | | 
|  | ------------------- | 
|  | / driver callbacks / | 
|  | ------------------- | 
|  | | | 
|  | V | 
|  | +----------------------+ | 
|  | | Counter core         | | 
|  | +----------------------+ | 
|  | | Routes device driver | | 
|  | | callbacks to the     | | 
|  | | userspace interfaces | | 
|  | +----------------------+ | 
|  | | | 
|  | ------------------- | 
|  | / driver callbacks / | 
|  | ------------------- | 
|  | | | 
|  | +---------------+---------------+ | 
|  | |                               | | 
|  | V                               V | 
|  | +--------------------+          +---------------------+ | 
|  | | Counter sysfs      |          | Counter chrdev      | | 
|  | +--------------------+          +---------------------+ | 
|  | | Translates to the  |          | Translates to the   | | 
|  | | standard Counter   |          | standard Counter    | | 
|  | | sysfs output       |          | character device    | | 
|  | +--------------------+          +---------------------+ | 
|  |  | 
|  | Thereafter, data can be transferred directly between the Counter device | 
|  | driver and Counter userspace interface:: | 
|  |  | 
|  | Count data request: | 
|  | ~~~~~~~~~~~~~~~~~~~ | 
|  | ---------------------- | 
|  | / Counter device       \ | 
|  | +----------------------+ | 
|  | | Count register: 0x28 | | 
|  | +----------------------+ | 
|  | | | 
|  | ----------------- | 
|  | / raw count data / | 
|  | ----------------- | 
|  | | | 
|  | V | 
|  | +----------------------------+ | 
|  | | Counter device driver      | | 
|  | +----------------------------+ | 
|  | | Processes data from device | | 
|  | |----------------------------| | 
|  | | Type: u64                  | | 
|  | | Value: 42                  | | 
|  | +----------------------------+ | 
|  | | | 
|  | ---------- | 
|  | / u64     / | 
|  | ---------- | 
|  | | | 
|  | +---------------+---------------+ | 
|  | |                               | | 
|  | V                               V | 
|  | +--------------------+          +---------------------+ | 
|  | | Counter sysfs      |          | Counter chrdev      | | 
|  | +--------------------+          +---------------------+ | 
|  | | Translates to the  |          | Translates to the   | | 
|  | | standard Counter   |          | standard Counter    | | 
|  | | sysfs output       |          | character device    | | 
|  | |--------------------|          |---------------------| | 
|  | | Type: const char * |          | Type: u64           | | 
|  | | Value: "42"        |          | Value: 42           | | 
|  | +--------------------+          +---------------------+ | 
|  | |                               | | 
|  | ---------------                 ----------------------- | 
|  | / const char * /                / struct counter_event / | 
|  | ---------------                 ----------------------- | 
|  | |                               | | 
|  | |                               V | 
|  | |                       +-----------+ | 
|  | |                       | read      | | 
|  | |                       +-----------+ | 
|  | |                       \ Count: 42 / | 
|  | |                        ----------- | 
|  | | | 
|  | V | 
|  | +--------------------------------------------------+ | 
|  | | `/sys/bus/counter/devices/counterX/countY/count` | | 
|  | +--------------------------------------------------+ | 
|  | \ Count: "42"                                      / | 
|  | -------------------------------------------------- | 
|  |  | 
|  | There are four primary components involved: | 
|  |  | 
|  | Counter device driver | 
|  | --------------------- | 
|  | Communicates with the hardware device to read/write data; e.g. counter | 
|  | drivers for quadrature encoders, timers, etc. | 
|  |  | 
|  | Counter core | 
|  | ------------ | 
|  | Registers the counter device driver to the system so that the respective | 
|  | callbacks are called during userspace interaction. | 
|  |  | 
|  | Counter sysfs | 
|  | ------------- | 
|  | Translates counter data to the standard Counter sysfs interface format | 
|  | and vice versa. | 
|  |  | 
|  | Please refer to the Documentation/ABI/testing/sysfs-bus-counter file | 
|  | for a detailed breakdown of the available Generic Counter interface | 
|  | sysfs attributes. | 
|  |  | 
|  | Counter chrdev | 
|  | -------------- | 
|  | Translates Counter events to the standard Counter character device; data | 
|  | is transferred via standard character device read calls, while Counter | 
|  | events are configured via ioctl calls. | 
|  |  | 
|  | Sysfs Interface | 
|  | =============== | 
|  |  | 
|  | Several sysfs attributes are generated by the Generic Counter interface, | 
|  | and reside under the ``/sys/bus/counter/devices/counterX`` directory, | 
|  | where ``X`` is to the respective counter device id. Please see | 
|  | Documentation/ABI/testing/sysfs-bus-counter for detailed information | 
|  | on each Generic Counter interface sysfs attribute. | 
|  |  | 
|  | Through these sysfs attributes, programs and scripts may interact with | 
|  | the Generic Counter paradigm Counts, Signals, and Synapses of respective | 
|  | counter devices. | 
|  |  | 
|  | Counter Character Device | 
|  | ======================== | 
|  |  | 
|  | Counter character device nodes are created under the ``/dev`` directory | 
|  | as ``counterX``, where ``X`` is the respective counter device id. | 
|  | Defines for the standard Counter data types are exposed via the | 
|  | userspace ``include/uapi/linux/counter.h`` file. | 
|  |  | 
|  | Counter events | 
|  | -------------- | 
|  | Counter device drivers can support Counter events by utilizing the | 
|  | ``counter_push_event`` function:: | 
|  |  | 
|  | void counter_push_event(struct counter_device *const counter, const u8 event, | 
|  | const u8 channel); | 
|  |  | 
|  | The event id is specified by the ``event`` parameter; the event channel | 
|  | id is specified by the ``channel`` parameter. When this function is | 
|  | called, the Counter data associated with the respective event is | 
|  | gathered, and a ``struct counter_event`` is generated for each datum and | 
|  | pushed to userspace. | 
|  |  | 
|  | Counter events can be configured by users to report various Counter | 
|  | data of interest. This can be conceptualized as a list of Counter | 
|  | component read calls to perform. For example: | 
|  |  | 
|  | +------------------------+------------------------+ | 
|  | | COUNTER_EVENT_OVERFLOW | COUNTER_EVENT_INDEX    | | 
|  | +========================+========================+ | 
|  | | Channel 0              | Channel 0              | | 
|  | +------------------------+------------------------+ | 
|  | | * Count 0              | * Signal 0             | | 
|  | | * Count 1              | * Signal 0 Extension 0 | | 
|  | | * Signal 3             | * Extension 4          | | 
|  | | * Count 4 Extension 2  +------------------------+ | 
|  | | * Signal 5 Extension 0 | Channel 1              | | 
|  | |                        +------------------------+ | 
|  | |                        | * Signal 4             | | 
|  | |                        | * Signal 4 Extension 0 | | 
|  | |                        | * Count 7              | | 
|  | +------------------------+------------------------+ | 
|  |  | 
|  | When ``counter_push_event(counter, COUNTER_EVENT_INDEX, 1)`` is called | 
|  | for example, it will go down the list for the ``COUNTER_EVENT_INDEX`` | 
|  | event channel 1 and execute the read callbacks for Signal 4, Signal 4 | 
|  | Extension 0, and Count 7 -- the data returned for each is pushed to a | 
|  | kfifo as a ``struct counter_event``, which userspace can retrieve via a | 
|  | standard read operation on the respective character device node. | 
|  |  | 
|  | Userspace | 
|  | --------- | 
|  | Userspace applications can configure Counter events via ioctl operations | 
|  | on the Counter character device node. There following ioctl codes are | 
|  | supported and provided by the ``linux/counter.h`` userspace header file: | 
|  |  | 
|  | * :c:macro:`COUNTER_ADD_WATCH_IOCTL` | 
|  |  | 
|  | * :c:macro:`COUNTER_ENABLE_EVENTS_IOCTL` | 
|  |  | 
|  | * :c:macro:`COUNTER_DISABLE_EVENTS_IOCTL` | 
|  |  | 
|  | To configure events to gather Counter data, users first populate a | 
|  | ``struct counter_watch`` with the relevant event id, event channel id, | 
|  | and the information for the desired Counter component from which to | 
|  | read, and then pass it via the ``COUNTER_ADD_WATCH_IOCTL`` ioctl | 
|  | command. | 
|  |  | 
|  | Note that an event can be watched without gathering Counter data by | 
|  | setting the ``component.type`` member equal to | 
|  | ``COUNTER_COMPONENT_NONE``. With this configuration the Counter | 
|  | character device will simply populate the event timestamps for those | 
|  | respective ``struct counter_event`` elements and ignore the component | 
|  | value. | 
|  |  | 
|  | The ``COUNTER_ADD_WATCH_IOCTL`` command will buffer these Counter | 
|  | watches. When ready, the ``COUNTER_ENABLE_EVENTS_IOCTL`` ioctl command | 
|  | may be used to activate these Counter watches. | 
|  |  | 
|  | Userspace applications can then execute a ``read`` operation (optionally | 
|  | calling ``poll`` first) on the Counter character device node to retrieve | 
|  | ``struct counter_event`` elements with the desired data. |