-
Notifications
You must be signed in to change notification settings - Fork 0
DeviceAPI
Interface-based API pattern in JNode that separates device access contracts from their implementations.
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.
| Class/Interface | Location | Purpose |
|---|---|---|
DeviceAPI |
core/src/driver/org/jnode/driver/DeviceAPI.java |
Base marker interface for all device APIs |
DeviceInfoAPI |
core/src/driver/org/jnode/driver/DeviceInfoAPI.java |
Extends DeviceAPI to provide device information display |
Device |
core/src/driver/org/jnode/driver/Device.java |
Holds the API registry (HashMap<Class, DeviceAPI>) |
ApiNotFoundException |
core/src/driver/org/jnode/driver/ApiNotFoundException.java |
Exception thrown when requested API is not found |
The Device class maintains a HashMap of registered API implementations:
// From Device.java lines 62-63
private final HashMap<Class<? extends DeviceAPI>, DeviceAPI> apis =
new HashMap<Class<? extends DeviceAPI>, DeviceAPI>();Drivers register their API implementations when they connect to a device:
// Device.registerAPI (lines 211-229)
public final <T extends DeviceAPI> void registerAPI(Class<T> apiInterface, T apiImplementation) {
if (!apiInterface.isInstance(apiImplementation)) {
throw new IllegalArgumentException("API implementation does not implement API interface");
}
if (!apiInterface.isInterface()) {
throw new IllegalArgumentException("API interface must be an interface");
}
apis.put(apiInterface, apiImplementation);
// Also register parent interfaces
final Class[] interfaces = apiInterface.getInterfaces();
if (interfaces != null) {
for (Class intf : interfaces) {
if (DeviceAPI.class.isAssignableFrom(intf)) {
if (!apis.containsKey(intf)) {
apis.put((Class<? extends DeviceAPI>) intf, apiImplementation);
}
}
}
}
}Clients can query whether a device implements a specific API:
// Device.implementsAPI (lines 246-254)
public final boolean implementsAPI(Class<? extends DeviceAPI> apiInterface) {
//lookup is classname based to handle multi isolate uscases
for (Class clazz : apis.keySet()) {
if (clazz.getName().equals(apiInterface.getName())) {
return true;
}
}
return false;
}And retrieve the API implementation:
// Device.getAPI (lines 272-286)
public final <T extends DeviceAPI> T getAPI(Class<T> apiInterface) throws ApiNotFoundException {
//lookup is classname based to handle multi isolate uscases
Class apiInterface2 = null;
for (Class clazz : apis.keySet()) {
if (clazz.getName().equals(apiInterface.getName())) {
apiInterface2 = clazz;
break;
}
}
final T impl = apiInterface.cast(apis.get(apiInterface2));
if (impl == null) {
throw new ApiNotFoundException(apiInterface.getName());
}
return impl;
}JNode defines many specialized device APIs:
| API Interface | Package | Purpose |
|---|---|---|
BlockDeviceAPI |
fs/src/driver/org/jnode/driver/block/ |
Block device read/write operations |
FSBlockDeviceAPI |
fs/src/driver/org/jnode/driver/block/ |
Filesystem-aware block device |
PartitionableBlockDeviceAPI |
fs/src/driver/org/jnode/driver/block/ |
Partition management |
NetDeviceAPI |
net/src/net/org/jnode/net/ |
Network device operations |
CharacterDeviceAPI |
core/src/driver/ |
Character-oriented devices |
DeviceInfoAPI |
core/src/driver/org/jnode/driver/ |
Device information display |
The IDE disk driver registers multiple APIs:
// fs/src/driver/org/jnode/driver/block/ide/disk/IDEDiskDriver.java (line 62)
implements IDEDeviceAPI<IBMPartitionTableEntry>, IDEConstants-
Classname-based lookup: The API lookup uses classname comparison rather than direct
instanceofto handle multi-isolate use cases where the same interface may be loaded in different isolate classloaders. -
Parent interface auto-registration: When registering an API, parent DeviceAPI interfaces are automatically registered to the same implementation.
-
Immutable lookup results:
Device.implementedAPIs()returns an immutable key set view of the API map. -
No API versioning: There is no built-in mechanism for API version negotiation between client and device.
- DeviceManager — Central registry that coordinates devices and drivers
- Driver-Framework — Parent subsystem containing the DeviceAPI pattern
- Device-Manager — Related documentation (note: DeviceAPI is mentioned here)
- Block-Device-Layer — Block device APIs that extend DeviceAPI
- Network-Stack — Network device APIs (NetDeviceAPI)
- Bus-Drivers — Bus drivers that enumerate devices with specific APIs