sys::hw service
The sys::hw service is in charge of hardware devices. It coordinates and manages communications with the hardware.
Hardware detection
Hardware detection is handled by the kernel itself, which then exposes a raw device descriptor (RDD) as well as a connection interface identifier (CII) and a session device identifier (SDI).
Device formats
This section describes the multiple formats used by this service to deal with devices.
Device type descriptor
From the RDD and CII is derived the device type descriptor (DTD), which describes the device's type. Its composition and size depends on the connection type, but it varies from empty (0 byte) if the connection type guarantees no information, up to 256 bytes.
The format remains to be determined but should be along the lines of a number-based equivalent of ModAlias, like :
- PCI-Express:
- Vendor (8 bytes)
- Sub-vendor (8 bytes)
- Type (8 bytes)
- Sub-type (8 bytes)
- ...
- ...
Device identifier
It also derives a unique device identifier (UDI) encoded on 265 bytes, which is made of:
- SDI (4 bytes)
- CII (4 bytes)
- Size of the DTD (1 byte)
- DTD (256 bytes, weakest bits filled with zeros)
Driver device descriptor
A driver device descriptor (DDD) is a data structure meant to be used by drivers. It uses the following format:
- Bytes 000-264: Device's UDI
- Bytes 265-512: Future-proof
Driven device type
A driven device type (DDT), usually referred to as the device type, is generated by the driver for each device is drives. This is a normalized value, used by the system to determine which actions can be performed through this device.
It's a 4-byte value, the strongest two bytes describing the category and the weakest two the sub-category.
The following list contains all possible values for DDTs, but is far from being complete yet. It will also grow over time as new device types appear on the market.
0x0001: Storage0x0001: Hard drive0x0002: SSD0x0003: USB flash drive0x0004: SD flash memory card
- ...
Normalization
Normalized methods
When a device is driven, other processes can ask this service to use normalized methods. These are methods that allow to perform a specific action or to receive normalized notifications about specific events of a specific device.
There are several methods, depending on the device's type (DDT). Notifications differ as well.
The following list contains all methods and related notifications for all DDTs, but is far from being complete yet. It will also grow over time as new device types appear on the market and as existing devices evolve to provide new features.
TODO
Normalized interrupts
Some devices use interrupts to notify the system of a particular event. In such case, the interrupt is normalized to a format called the normalized interrupt format, which is then sent to the driver process using the DEVICE_EVENT notification.
The normalized interrupt format depends on the device's type (DDT).
The following list contains all normalized interrupts for all DDTs, but is far from being complete yet. It will also grow over time as new device types appear on the market and as existing devices evolve to provide new features.
TODO
Normalized notifications
The normalized notifications are a type of notifications sent by a driver to processes that subscribed to them using normalized methods. They are derived from the device's interrupts and events pulled from its memory, after a translation by the driver itself.
The normalized notification format depends on the device's type (DDT).
The following list contains all normalized notifications for all DDTs, but is far from being complete yet. It will also grow over time as new device types appear on the market and as existing devices evolve to provide new features.
TODO
Patterns
Several methods of this service use patterns, which allow to match devices depending on several criterias.
A pattern is a data structure whose size varies from 5 to 277 bytes made of the following:
- Pattern (1 byte)
- Bit 0: match all connection types
- Bit 2: match all buses
- Bit 3: match all ports
- Connection type (1 byte)
- Bus number (1 byte)
- Port number (1 byte)
- DTD length (1 byte) -
0to omit DTD - DTD pattern indicator (16 bytes, only if DTD) - indicates which bytes of the DTD must be used as patterns
- DTD (up to 256 bytes)
It's possible to match only devices that use a given connection type, and more specifically on a given bus and/or port.
It's also possible to list only devices that match a specific DTD pattern. For that, the bit corresponding to the byte number in the DTD pattern indicator must be set.
For instance, providing the DTD 0x0100B2 with the DTD pattern indicator set to 0b01000000, the second byte will match all devices.
Drivers
From a higher level point of view, drivers are services that declare themselves as being able to handle certain type of devices through the REGISTER_DRIVER method, using patterns.
When a device is connected, using multiple criterias which are yet to be determined, a driver is selected from the list of drivers able to handle this specific device. This driver process then receives the DEVICE_EVENT notification.
From this point, the driver can create an AMS from the device's memory using the DEVICE_AMS syscall.
It can also get informed of interrupts the device raises through the DEVICE_INTERRUPT notification.
Other processes can then ask the driver to perform specific actions depending on the type of device, using normalized methods which can be sent to the driver using the ASK_DRIVER method. The driver receives these informations through the DRIVER_METHOD_REQUEST notification.
The driver is also in charge of translating the interrupts of a device as well as eventual events polled from its (mapped) memory to normalized notifications which can then be sent to processes that subscribed to them using the related normalized methods.
A note on performances
Although hardware devices' interrupts are notified to the driver through service socket notifications, the latency is still minimal as soon as the driver listens to the RECV_SOCK_MSG signal, which like all signals uses interrupts and so guarantees a very low latency.
Methods
0x01 ENUM_DEVICES
Enumerate connected devices.
It's also possible to only count the number of devices matching the provided criterias by providing a start index and end index of 0.
Required permissions:
devices.enum
Arguments:
- Start index (4 bytes)
- End index (4 bytes)
- Pattern (277 bytes)
Answer:
- Number of found devices globally (4 bytes)
- Number of devices listed in this answer (4 bytes)
- DDD of each device (512 bytes * number of devices)
0x01if some devices were masked due to insufficient permissions,0x00else (1 byte)
Errors:
0x10: Start index is lower than the end index0x11: Invalid connection type0x12: Bus number was provided without a connection type0x13: Port number was provided without a connection type0x14: Both bus number and port number were provided0x15: Invalid DTD0x20: Range is greater than the available answer size0x21: Provided bus was not found0x22: Provided port was not found
0x02 SUBSCRIBE_DEVICES
Subscribe to events related to devices matching a patterns.
All current and future devices matching this pattern will cause a DEVICE_EVENT notification.
Required permissions:
devices.subscribe
Arguments:
0x00to subscribe, any other value to unsubscribe- Pattern (277 bytes)
Answer:
None
Errors:
0x20: Asked to unsubscribe but no subscription is active for this pattern
0x10 REGISTER_DRIVER
Set up a service as a driver for all devices matching a pattern.
If multiple drivers have colliding patterns, the final user will be prompted to choose a driver.
The driver process will receive DEVICE_EVENT notifications for drivable devices. This notification will only be sent for devices for which the system chose this driver as the main one.
Notifications are also retroactive, which means they will be sent for already-connected devices.
The driver will also have the device registered in its drivable devices attribute, allowing it to use the DEVICE_AMS syscall to map the device's memory in its own.
Required permissions:
devices.register_driver
Arguments:
- Pattern of the devices to drive (277 bytes)
Answer:
None
Errors:
0x20: Current process is not a service0x30: Current process is already registered as a driver for this pattern
0x11 UNREGISTER_DRIVER
Unregister a service previously registered as a driver.
Required permissions:
None
Arguments:
- Pattern to unsubscribe from (277 bytes)
Errors:
0x30: Current process is not registered as a driver for this pattern
0x20 NOTIFY_PROCESS
Send a notification to a process that registered itself for normalized methods through a normalized method.
Required permissions:
None
Arguments:
- Notification ID (8 bytes)
- Normalized notification's content
Answer:
Expected answer by the notified process for this method if any
Errors:
0x20: Unknown notification ID
0xA0 ASK_DRIVER
Ask a driver to use a normalized method on a device it drives.
Required permissions:
devices.ask_driver
Arguments:
- Device's SDI (4 bytes)
- Method's code (4 bytes)
- Method's arguments (size depends on the method)
Answer:
Expected answer format for this method
Errors:
0x20: Unknown device SDI provided0x21: Provided method code is invalid for this device0x22: Invalid arguments provided for this method
Notifications
DEVICE_EVENT
Sent for a specific device to processes that either:
- Drive this specific device
- Subscribed to it using the
SUBSCRIBE_DEVICESmethod
Datafield:
- DDD (512 bytes)
- Event code (1 byte):
0x10: device was just connected0x11: a driver was just selected for the device0x12: the device is ready to use0x20: device was disconnected (software)0x21: the device is being disconnected by its driver0x22: the device has been disconnected by the driver0x23: the device was brutally disconnected (hardware)0x30: device was just put to sleep0x31: device was just awoken from sleep
- Indicator (1 byte):
- Bit 0: set if this device is connected for the first time
- Bit 1: set if this device was disconnected brutally (not by the system itself)
- Bit 2: set if this device is connected for the first time on this specific port
DEVICE_INTERRUPT
Sent to a driver after a device it's currently driving raised an interrupt.
Datafield:
- Device's SDI (4 bytes)
- Normalized interrupt
DRIVER_METHOD_REQUEST
Sent to a driver after receiving a valid normalized method request.
The driver is expected to answer using the relevant answer format for the provided normalized method and arguments.
The notification ID is generated by this service to allow the driver to send normalized notifications to a process that registers for it through this method without showing the caller process' PID to the driver process.
Datafield:
- DDT (4 bytes)
- Notification ID (8 bytes)
- Method's code (4 bytes)
- Method's arguments (size depends on the method)
Expected answer:
Expected answer format for this method if any
DEVICE_NORM_NOTIF
Sent to a process that subscribed to normalized notifications of a device.
This notification is transferred by the sys::hw service after the driver sent it its content through the NOTIFY_PROCESS method.
Datafield:
- Device's SDI (4 bytes)
- Normalized notification's content