Skip to content

DeviceException DriverException

Levente Santha edited this page May 15, 2026 · 1 revision

DeviceException and DriverException

Base exception hierarchy for JNode's device and driver framework, with subclasses covering registration, lookup, API access, and binding errors.

Overview

JNode's device framework uses two parallel checked exception hierarchies to separate device-level errors from driver-level errors. Both extend java.lang.Exception and live in org.jnode.driver.

DeviceException covers errors in the device lifecycle: registration in the DeviceManager, lookup by ID, and API access via Device.getAPI(). Its subclasses represent problems with the device registry or device state.

DriverException covers errors in the driver lifecycle: connecting a driver to a device, starting/stopping devices, and claiming hardware resources (IRQ, I/O ports, memory). Its subclasses represent problems with the driver-device binding mechanism.

The exception hierarchy is:

Exception
├── DeviceException                              (device-level errors)
│   ├── ApiNotFoundException                     (API not registered on device)
│   ├── DeviceAlreadyRegisteredException         (device already in DeviceManager)
│   ├── DeviceNotFoundException                  (device ID not found in DeviceManager)
│   └── ChannelAlreadyOwnedException             (character channel already claimed)
│
└── DriverException                              (driver-level errors)
    ├── DeviceAlreadyConnectedException          (driver already bound to a device)
    └── InvalidDriverException                   (driver not valid for a device)

All exceptions except ChannelAlreadyOwnedException follow the standard four-constructor pattern (no-arg, message, cause, message+cause) and were authored by Ewout Prangsma.

Key Components

Class Path Role
DeviceException core/src/driver/org/jnode/driver/DeviceException.java Base exception for device-level errors (registration, lookup, API)
DriverException core/src/driver/org/jnode/driver/DriverException.java Base exception for driver-level errors (connection, resource claiming)
ApiNotFoundException core/src/driver/org/jnode/driver/ApiNotFoundException.java Thrown by Device.getAPI() when requested interface is not registered
DeviceAlreadyRegisteredException core/src/driver/org/jnode/driver/DeviceAlreadyRegisteredException.java Thrown by AbstractDeviceManager.register() for duplicate device IDs
DeviceNotFoundException core/src/driver/org/jnode/driver/DeviceNotFoundException.java Thrown by AbstractDeviceManager.getDevice() when device ID not found
ChannelAlreadyOwnedException core/src/driver/org/jnode/driver/character/ChannelAlreadyOwnedException.java Thrown when a character device channel is already claimed by another device
DeviceAlreadyConnectedException core/src/driver/org/jnode/driver/DeviceAlreadyConnectedException.java Thrown when a driver is already connected to a device
InvalidDriverException core/src/driver/org/jnode/driver/InvalidDriverException.java Thrown by ByteArrayDevice.setDriver() to reject driver assignment

How It Works

DeviceException Usage

DeviceException and its subclasses are thrown during the device registration and lookup lifecycle:

DeviceManager.register(device)
  └── throws DeviceAlreadyRegisteredException  (device ID already in registry)

DeviceManager.getDevice(id)
  └── throws DeviceNotFoundException           (no device with that ID)

Device.getAPI(SomeAPI.class)
  └── throws ApiNotFoundException              (API not registered on device)

SerialPortDriver / PS2Driver
  └── throws ChannelAlreadyOwnedException      (character channel already claimed)

The most-caught subclass is ApiNotFoundException (52 catch sites), because Device.getAPI() is the primary way code accesses device functionality. The typical pattern is:

try {
    SomeAPI api = device.getAPI(SomeAPI.class);
    // use api
} catch (ApiNotFoundException e) {
    // fallback or log
}

DeviceAlreadyRegisteredException (29 catch sites) is commonly caught during startDevice() when registering child devices (e.g., PCI driver registering sub-devices), since duplicate registration is a common race condition.

DriverException Usage

DriverException is the "workhorse" exception with ~181 throw sites across the codebase. It is the standard way to signal failure during driver startDevice() operations:

Driver.connect(device)
  └── throws DriverException("This driver is already connected to a device")

Device.setDriver(driver)
  └── wraps DriverException("Cannot set driver")

Device.start()
  └── throws DriverException("Cannot start without a driver")
     throws DriverException("Cannot start without being registered")

Device.stop()
  └── throws DriverException("Cannot stop without a driver")
     throws DriverException("Cannot stop without being registered")

Common DriverException message patterns across drivers:

Message Pattern Context Frequency
"Cannot find ResourceManager" JNDI lookup for ResourceManager.NAME fails Most common
"Cannot claim {resource} resources" Resource contention (IRQ, I/O ports) ~30 sites
"Cannot find DeviceManager" JNDI lookup failure ~10 sites
"Timeout in {command} command" Hardware command timeouts (e.g., Prism2 WiFi) ~15 sites
"Card failure" / "No buffer" Hardware state errors ~10 sites
"Unknown exception" Catch-all wrapping unexpected throwables ~20 sites

DriverException is heavily concentrated in net drivers (~80+ throw sites across RTL8139, Prism2, Ne2000, EEPRO100, BCM570x, etc.), gui drivers (~20 sites), and fs drivers (~15 sites).

Exception Flow in Device Lifecycle

Boot → DeviceFinder discovers hardware
  → DeviceManager.register(device)
    └── DeviceAlreadyRegisteredException if duplicate

Plugin loads driver
  → Driver.connect(device)
    └── DriverException if already connected
  → Device.setDriver(driver)
    └── DriverException("Cannot set driver") wraps connect failure
  → Device.start()
    └── DriverException if no driver or not registered
    └── DriverException("Cannot claim IRQ") on resource conflict

Runtime: device.getAPI(SomeAPI.class)
  └── ApiNotFoundException if API not registered

Gotchas & Non-Obvious Behavior

  • DeviceAlreadyConnectedException is never directly thrown: Despite having its own class, Driver.connect() throws a plain DriverException("This driver is already connected to a device") rather than this subclass. The class exists as a semantic marker but is not used in practice.
  • InvalidDriverException is never caught: It is thrown only by ByteArrayDevice.setDriver() as a rejection mechanism ("No driver allowed here"), and no code catches it specifically.
  • ChannelAlreadyOwnedException is the odd one out: It lives in a different package (org.jnode.driver.character), has a custom single-arg constructor taking a Device (not the standard four-constructor pattern), and is authored by "qades" rather than Ewout Prangsma. It is only thrown in two places (serial and PS2 drivers).
  • ApiNotFoundException is the most-caught subclass (52 catch sites): This is because Device.getAPI() is the primary way code accesses device functionality. If you are writing device-aware code, you must handle this exception.
  • DeviceException vs DriverException boundary: DeviceException covers the device side (registration, lookup, API access), while DriverException covers the driver side (connection, starting, stopping, resource claiming). This is a clean conceptual boundary that guides which exception to throw.
  • Both are checked exceptions: Both extend java.lang.Exception directly, so all throw sites must declare throws or wrap in a runtime exception.

Related Pages

Clone this wiki locally