-
Notifications
You must be signed in to change notification settings - Fork 0
DeviceManager
Central registry for devices, drivers, and their bindings.
The DeviceManager (core/src/driver/org/jnode/driver/DeviceManager.java) is the central registry of JNode's device framework. It manages the complete lifecycle of hardware devices — from discovery through registration, driver binding, and startup — while providing a query API for applications to locate and interact with devices.
The DeviceManager interface defines the contract, and AbstractDeviceManager provides the core implementation with the device map (Map<String, Device>), system bus tree, listener dispatch, and device lifecycle logic. DefaultDeviceManager extends this with plugin-based loading of DeviceFinder and DeviceToDriverMapper extensions from the org.jnode.driver.finders and org.jnode.driver.mappers extension points.
At boot, DefaultDeviceManager binds itself to the InitialNaming service registry under DeviceManager.NAME so that any code can look it up:
DeviceManager dm = InitialNaming.lookup(DeviceManager.NAME);
Collection<Device> allDevices = dm.getDevices();| Class / File | Role |
|---|---|
core/src/driver/org/jnode/driver/DeviceManager.java |
Public interface: registration, startup, shutdown, device lookup, listener management |
core/src/driver/org/jnode/driver/AbstractDeviceManager.java |
Core implementation: device map, bus tree, lifecycle methods, event dispatch |
core/src/driver/org/jnode/driver/DefaultDeviceManager.java |
Plugin integration: loads finders and mappers from extension points |
core/src/driver/org/jnode/driver/DeviceManagerListener.java |
DeviceManagerListener — Listener interface for deviceRegistered / deviceUnregister events |
core/src/driver/org/jnode/driver/DeviceToDriverMapper.java |
Interface for matching a device to a suitable driver |
core/src/driver/org/jnode/driver/DeviceFinder.java |
Interface for discovering devices on a bus |
DeviceManager.register(Device) performs three steps atomically (within doRegister()):
-
Check uniqueness — throws
DeviceAlreadyRegisteredExceptionif the device ID is already in the map. -
Find a driver — calls
findDriver(device)which iterates registeredDeviceToDriverMappers (sorted by match level) until one returns a non-nullDriver. If a driver is found,device.setDriver(driver)is called. -
Add to the map —
devices.put(device.getId(), device).
After registration, start(device) is called unless the command line contains no<deviceId>:
// AbstractDeviceManager.register()
shouldStart = doRegister(device);
if (cmdLine.indexOf("no" + device.getId()) >= 0) {
shouldStart = false;
}
fireRegisteredEvent(device);
if (shouldStart) {
start(device);
}findDriver iterates mappers in priority order:
// AbstractDeviceManager.findDriver()
protected final Driver findDriver(Device device) {
synchronized (mappers) {
for (DeviceToDriverMapper mapper : mappers) {
final Driver drv = mapper.findDriver(device);
if (drv != null) {
return drv;
}
}
}
return null;
}The MapperComparator sorts mappers ascending by getMatchLevel():
-
MATCH_DEVICE_PREDEFINED = -1— custom/predefined mapping logic -
MATCH_DEVICE_REVISION = 0— exact device + revision (best match) -
MATCH_DEVICE = 1— exact device ID -
MATCH_DEVCLASS = 2— device class only
findDeviceDrivers() is called whenever a new mapper extension is added, re-evaluating all devices that currently have no driver.
DefaultDeviceManager implements ExtensionPointListener and listens to two extension points. When an extension is added, it reloads all extensions and re-runs device driver discovery:
// DefaultDeviceManager.extensionAdded()
public final void extensionAdded(ExtensionPoint point, Extension extension) {
loadExtensions(); // refreshFinders() + refreshMappers()
findDeviceDrivers();
}Finders and mappers are configured via XML in plugin descriptors:
<extension point="org.jnode.driver.finders">
<finder class="org.jnode.driver.bus.pci.PCIFinder"/>
</extension>
<extension point="org.jnode.driver.mappers">
<mapper class="org.jnode.driver.bus.pci.PCIDriverMapper"/>
</extension>Two listener interfaces:
-
DeviceManagerListener— DeviceManagerListener —deviceRegistered(Device)anddeviceUnregister(Device)for all manager events -
DeviceListener— DeviceListener —deviceStarted(Device)anddeviceStop(Device)for device lifecycle events
Listeners that take longer than 100ms to respond trigger an error log:
// AbstractDeviceManager.fireRegisteredEvent()
StopWatch sw = new StopWatch();
for (DeviceManagerListener l : list) {
sw.start();
l.deviceRegistered(device);
if (sw.isElapsedLongerThen(100)) {
BootLogInstance.get().error("DeviceManagerListener took " + sw + " in deviceRegistered");
}
}The DeviceManager.getDevicesByAPI(Class<? extends DeviceAPI>) method enables service discovery by API type:
public final Collection<Device> getDevicesByAPI(Class<? extends DeviceAPI> apiClass) {
final ArrayList<Device> result = new ArrayList<Device>();
for (Device dev : devices.values()) {
if (dev.implementsAPI(apiClass)) {
result.add(dev);
}
}
return result;
}Devices register their APIs via device.registerAPI(DeviceAPI.class, implementation). Common hierarchies: BlockDeviceAPI → FSBlockDeviceAPI, CharacterDeviceAPI → SerialPortAPI, NetDeviceAPI, FrameBufferAPI.
The system bus (AbstractDeviceManager.getSystemBus()) is the root of the hardware topology. Created as a package-private SystemBus inner class:
this.systemBus = new SystemBus();Bus drivers attach child buses (PCI, USB, ISA) to it, and DeviceFinder implementations probe these buses for hardware.
-
doRegisteris synchronized butstartis not — registration is atomic but device startup happens outside the synchronized block, meaning a device can be in the map but not yet started if another thread races. -
Mapper ordering is by match level, not specificity — a
MATCH_DEVCLASSmapper with level 2 runs after aMATCH_DEVICE_REVISIONmapper with level 0. Broad-match mappers must have higher level values. -
Delayed driver binding — if no mapper finds a driver, the device stays registered but unstarted.
findDeviceDrivers()is called whenever a new mapper extension is added, allowing late-binding to reconnect these devices. -
100ms listener warning threshold — both
DeviceManagerListenerandDeviceListenercallbacks are checked for timing. Slow listeners can affect the timing of other device registrations. -
Command-line device blocking —
no<deviceId>injnode.cmdlineonly blocks startup, not registration. The device still appears ingetDevices(). -
Immutable lookup collection —
getDevices()andgetDevicesByAPI()returnCollections.unmodifiableCollection. Iteration over the live map is safe against concurrent modification but the map values themselves can change.
- Driver-Framework — Broader driver subsystem: bus drivers, resource management, API hierarchies.
- Plugin-System — How DeviceFinder and DeviceToDriverMapper are registered via extension points.
- Resource-Management — Hardware resource allocation (IRQ, I/O ports, DMA, memory) used by device drivers.
- Interrupt-Handling — How hardware IRQs are routed to device driver handlers.
- Device-Manager — Alias for the same page (existing hyphenated name).