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: Storage
    • 0x0001: Hard drive
    • 0x0002: SSD
    • 0x0003: USB flash drive
    • 0x0004: 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) - 0 to 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)
  • 0x01 if some devices were masked due to insufficient permissions, 0x00 else (1 byte)

Errors:

  • 0x10: Start index is lower than the end index
  • 0x11: Invalid connection type
  • 0x12: Bus number was provided without a connection type
  • 0x13: Port number was provided without a connection type
  • 0x14: Both bus number and port number were provided
  • 0x15: Invalid DTD
  • 0x20: Range is greater than the available answer size
  • 0x21: Provided bus was not found
  • 0x22: 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:

  • 0x00 to 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 service
  • 0x30: 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:

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 provided
  • 0x21: Provided method code is invalid for this device
  • 0x22: Invalid arguments provided for this method

Notifications

DEVICE_EVENT

Sent for a specific device to processes that either:

Datafield:

  • DDD (512 bytes)
  • Event code (1 byte):
    • 0x10: device was just connected
    • 0x11: a driver was just selected for the device
    • 0x12: the device is ready to use
    • 0x20: device was disconnected (software)
    • 0x21: the device is being disconnected by its driver
    • 0x22: the device has been disconnected by the driver
    • 0x23: the device was brutally disconnected (hardware)
    • 0x30: device was just put to sleep
    • 0x31: 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:

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: