Skip to content
Levente Santha edited this page May 14, 2026 · 2 revisions

DeviceAPI Pattern

Interface-based API pattern in JNode that separates device access contracts from their implementations.

Overview

The DeviceAPI pattern is a core architectural pattern in JNode's driver framework. It provides a clean separation between what a device can do (the API interface) and how it does it (the implementation). This pattern enables flexible device access, runtime API discovery, and multiple API implementations per device.

At its core, every device API must extend the marker interface DeviceAPI. Devices maintain a map of registered API implementations, allowing clients to query and retrieve specific capabilities at runtime.

Key Components

Class/InterfaceLocationPurpose
DeviceAPIcore/src/driver/org/jnode/driver/DeviceAPI.javaBase marker interface for all device APIs
DeviceInfoAPIcore/src/driver/org/jnode/driver/DeviceInfoAPI.javaExtends DeviceAPI to provide device information display
Devicecore/src/driver/org/jnode/driver/Device.javaHolds the API registry (HashMap<Class, DeviceAPI>)
ApiNotFoundExceptioncore/src/driver/org/jnode/driver/ApiNotFoundException.javaException thrown when requested API is not found

How It Works

API Registration and Discovery

The Device class maintains a HashMap of registered API implementations:

// From Device.java lines 62-63privatefinalHashMap<Class<? extendsDeviceAPI>, DeviceAPI> apis =
newHashMap<Class<? extendsDeviceAPI>, DeviceAPI>();

Drivers register their API implementations when they connect to a device:

// Device.registerAPI (lines 211-229)publicfinal <TextendsDeviceAPI> voidregisterAPI(Class<T> apiInterface, TapiImplementation) {
if (!apiInterface.isInstance(apiImplementation)) {
thrownewIllegalArgumentException("API implementation does not implement API interface");
}
if (!apiInterface.isInterface()) {
thrownewIllegalArgumentException("API interface must be an interface");
}
apis.put(apiInterface, apiImplementation);
// Also register parent interfacesfinalClass[] interfaces = apiInterface.getInterfaces();
if (interfaces != null) {
for (Classintf : interfaces) {
if (DeviceAPI.class.isAssignableFrom(intf)) {
if (!apis.containsKey(intf)) {
apis.put((Class<? extendsDeviceAPI>) intf, apiImplementation);
}
}
}
}
}

Clients can query whether a device implements a specific API:

// Device.implementsAPI (lines 246-254)publicfinalbooleanimplementsAPI(Class<? extendsDeviceAPI> apiInterface) {
//lookup is classname based to handle multi isolate uscasesfor (Classclazz : apis.keySet()) {
if (clazz.getName().equals(apiInterface.getName())) {
returntrue;
}
}
returnfalse;
}

And retrieve the API implementation:

// Device.getAPI (lines 272-286)publicfinal <TextendsDeviceAPI> TgetAPI(Class<T> apiInterface) throwsApiNotFoundException {
//lookup is classname based to handle multi isolate uscasesClassapiInterface2 = null;
for (Classclazz : apis.keySet()) {
if (clazz.getName().equals(apiInterface.getName())) {
apiInterface2 = clazz;
break;
}
}
finalTimpl = apiInterface.cast(apis.get(apiInterface2));
if (impl == null) {
thrownewApiNotFoundException(apiInterface.getName());
}
returnimpl;
}

Common Device API Implementations

JNode defines many specialized device APIs:

API InterfacePackagePurpose
BlockDeviceAPIfs/src/driver/org/jnode/driver/block/Block device read/write operations
FSBlockDeviceAPIfs/src/driver/org/jnode/driver/block/Filesystem-aware block device
PartitionableBlockDeviceAPIfs/src/driver/org/jnode/driver/block/Partition management
NetDeviceAPInet/src/net/org/jnode/net/Network device operations
CharacterDeviceAPIcore/src/driver/Character-oriented devices
DeviceInfoAPIcore/src/driver/org/jnode/driver/Device information display

Example: IDE Disk Driver

The IDE disk driver registers multiple APIs:

// fs/src/driver/org/jnode/driver/block/ide/disk/IDEDiskDriver.java (line 62)implementsIDEDeviceAPI<IBMPartitionTableEntry>, IDEConstants

Gotchas

  1. Classname-based lookup: The API lookup uses classname comparison rather than direct instanceof to handle multi-isolate use cases where the same interface may be loaded in different isolate classloaders.

  2. Parent interface auto-registration: When registering an API, parent DeviceAPI interfaces are automatically registered to the same implementation.

  3. Immutable lookup results: Device.implementedAPIs() returns an immutable key set view of the API map.

  4. No API versioning: There is no built-in mechanism for API version negotiation between client and device.

Related Pages

Clone this wiki locally