Lunatik

hidModule

Writes a HID driver in Lua: it matches devices by id_table, and can fix a device’s report descriptor and rewrite its raw reports.

The driver’s runtime is softirq: the script runs with lunatik run -c softirq <script>, other contexts raise runtime context mismatch, and the callbacks, which run under that runtime’s lock, must not sleep. The driver stays registered until its stop or the end of the runtime.

See examples/gesture and examples/xiaomi.

Usage

-- run with `lunatik run -c softirq <script>`
local hid = require("hid")

local function raw_event(driver, hdev, report, raw)
  print(hdev.name, report.id, #raw)
end

hid.register({
  name = "luahid_trace",
  id_table = {{bus = 0x05, vendor = 0x2717, product = 0x5014}},
  raw_event = raw_event,
})

Class hid_driver

hid_driver:stop () Unregisters the driver.

hid

register (opts) Registers a new HID driver.

Class hid_driver in detail

Represents a registered HID driver.
hid_driver:stop ()
Unregisters the driver. The devices it drives are released from it, and no callback of it runs again. Calling it again does nothing, and a to-be-closed variable holding the driver stops it the same way.

Returns

    nil

Raises

“not allowed once the runtime is armed” past the script body: hid_unregister_driver sleeps, and an armed runtime runs under its spinlock

Usage

driver:stop()

hid in detail

register (opts)
Registers a new HID driver. The opts table is the driver: each callback it carries receives it as its first argument, and one it does not carry does nothing.

Parameters

  • opts table driver options: name (string), id_table (array of device ID tables, each with optional integer fields bus and group, from 0 to 0xffff, vendor and product, from 0 to 0xffffffff, and driver_data, from 0), and the optional callbacks:

    • probe(driver, hdev, id): a device matched; hdev is the device’s table, made here and handed to every later callback of the device, and id is the matching entry, with bus, group, vendor, product and driver_data. Returning a negative errno, -errno.ENODEV say, with linux.errno, fails the probe with it; an error, or a return that is neither nothing, zero nor an errno a user program is given, the kernel’s own from ERESTARTSYS on, logged as invalid errno, fails it with ECANCELED.
    • report_fixup(driver, hdev, rdesc): rdesc is a data over the report descriptor, edited in place, of fixed size and valid only during the call.
    • raw_event(driver, hdev, report, raw): raw is a data over the report, edited in place and valid only during the call. Returning nothing or zero passes the report on and a negative errno drops it; an error, or any other return, drops it with ECANCELED.
    • remove(driver, hdev): the device left the driver, or the HID core failed its probe after probe returned, so each probe that returned gets one remove; a device the driver still holds when its runtime stops gets none.

    hdev carries bus, group, vendor, product, version and name, and keeps what the callbacks store in it; report carries id, type, size, application and maxfield. What report_fixup and remove return is ignored, and a callback’s error goes to the kernel log.

Returns

    hid_driver the driver, which hid.register keeps for its runtime: dropping it stops nothing, and the driver stays registered until stop or the end of the runtime

Raises

“not allowed once the runtime is armed” past the script body; from a percpu runtime; if required fields are missing, or id_table is invalid or too long; the kernel’s errno if it refuses the driver, EBUSY for a name another driver holds on the bus; bad field '<field>' (number expected, got <type>) if an entry’s bus, group, vendor, product or driver_data is present and not a number, and bad field '<field>' (out of bounds) if it is past its range; bad field '<field>' (function expected, got <type>) if probe, report_fixup, raw_event or remove is present and not a function; runtime context mismatch unless the runtime is softirq; not allowed while the runtime closes from a finalizer that runs at its close