Skip to content

HardwareManager

Jan Lapp edited this page Nov 26, 2019 · 1 revision

HardwareManager

Usage of the HardwareManager service

The HardwareManager service is commonly used by low level drivers that need information about the existence of specific interface hardware, which can be specified for instance in terms of a port identifier, such as /dev/ttyUSB0 or COM14. However, in a productive system, the port may not be fixed, therefore a more flexible mechanism is needed to identify hardware of a specific type. The HardwareManager provides such a mechanism, currently for Linux systems only.

How does it work

 

The hardware access interface provides information on hardware interfaces available as well as hardware devices connected to these interfaces. Devices are connected to the OGEMA gateway mainly via USB. But there are other devices which could be connected via digital IO or native UARTs.

A connected device is unambiguously identified in the system by an identifier string, whose format varies between the different connection types. The first part of an identifier string is the type of the connection (e.g. usb, serial, io).

  • USB: This is a usb identifier string which is OGEMA specific and consists of the vendor and product id (VID and PID) of the device, the (optional) serial number of the device, the configuration and interface and the physical path to the device (root hub – port on hub – port on hub – device). The information required to setup such an identifier string is provided by the underlying operating system. In a linux based system the device file system udev provides such an interface which can be used to obtain the information about the topology of the connected USB devices. In order to support OGEMA, an operating system needs to provide such an interface. Furthermore, the operating system has to support hot plugging mechanisms,  like the one implemented for linux, which is described in [4]. As an example, an FTDI serial adapter connected to port 1 of an intermediate hub, connected to root hub 1: “usb:1.1:1.0:0x0403:0x06001:FTU74ZQE” “connection type: physical bus location: vendor id: product id: serial number”
  • Serial: a serial identifier string simply list the number/name of the port: “serial:1” “connection type: port number”
  • Digital IO: a digitalIO identifier string has the format: “digitalIO:in:portID:pinID”

This identifier string is used when identifying hardware and requesting hardware access.

The HardwareManager is responsible to manage a list of currently available hardware. Additional Information is available in HardwareDescriptors that can be accessed via the HardwareManager and contain additional information according to the connection type of the device. The most important information would be the port name (Windows) or device file (Linux) of the device.

All devices that are accessible via a serial port, are controlled by OGEMA drivers via serial communication Java-API (RXTX, javax.com, jssc). The hardware manager makes all connected USB devices and their topology available to the framework at startup of the system. When an OGEMA low level driver is installed, the administrator can associate the driver with a device by selecting a device description string from the list of device location identifiers provided by the hardware manager. These associations are stored persistently and compared after each reboot with the existing hardware configuration and updated if necessary.

If a device is removed or added, the table of devices is updated so that it reflects the current state of the hardware configuration.

Getting current hardware configuration

The following code shows how to actively query the current hardware configuration for a device with VID 0403 and PID 6001:

Collection<HardwareDescriptor> descriptors = hwMngr.getHardwareDescriptors(".+:0403:6001:");
            // ".+:0403:6001:" is a regular expression that should match a hardware idetifier as explained above.
            for (HardwareDescriptor descr : descriptors) {
                portName = ((UsbHardwareDescriptor) descr).getPortName();
                if (portName != null) {
                    Connection con = new Connection(portName, this);
                    if (con.localDevice != null)
                        addConnection(con);
                }
            }

The driver need to register a HardwareListener implementation by calling the method org.ogema.core.hardwaremanager.HardwareManager.addListener(HardwareListener). An example implementation of the listener methods can look like this:

    @Override
    public void hardwareAdded(HardwareDescriptor descriptor) {
        logger.debug("hardware added: " + descriptor.getIdentifier());
        String portName = null;
        if (descriptor.getHardwareType() == HardwareType.USB) {
            portName = ((UsbHardwareDescriptor) descriptor).getPortName();
        }
        else if (descriptor.getHardwareType() == HardwareType.SERIAL) {
            portName = ((SerialHardwareDescriptor) descriptor).getPortName();
        }
        else {
            logger.debug("error, descriptor has unsupported hardware type: " + descriptor.getHardwareType().toString());
        }
        if (null == portName) {
            logger.error("Add device with port name null.");
            return;
        }
        Connection con = new Connection(portName, this);
        addConnection(con);
    }

    @Override
    public void hardwareRemoved(HardwareDescriptor descriptor) {
        logger.debug("hardware removed: " + descriptor.getIdentifier().toString());
        String portName = null;
        if (descriptor.getHardwareType() == HardwareType.USB) {
            portName = ((UsbHardwareDescriptor) descriptor).getPortName();
        }
        else if (descriptor.getHardwareType() == HardwareType.SERIAL) {
            portName = ((SerialHardwareDescriptor) descriptor).getPortName();
        }
        Connection con = connectionsMap.get(portName);
        if (con != null)
            con.close();
        connectionsMap.remove(portName);
    }

 

Note: Currently only linux based platforms are supported by the HardwareManager. On unsupported platforms drivers should be organized to get the necessary hardware information via alternative methods, e.g. java command line properties.

Start configuration for the HardwareManager

Note that the implementation bundle for the native access must be started before the hardware manager itself. The following is a valid start configuration for the OGEMA launcher rundir:

   <bundle dir="bin/ogema" groupId="org.ogema.ref-impl" artifactId="hardware-manager-rpi" version="&ogema-version;" startLevel="3"/>    
    <bundle dir="bin/ogema" groupId="org.ogema.ref-impl" artifactId="hardware-manager" version="&ogema-version;" startLevel="4"/>

The requirement to introduce explicit start levels may be avoided in future releases.

The hardware manager itself must be started even if there is no NativeAccess available, since some drivers have a mandatory dependency to it. It will use a dummy NativeAccess then. Starting the native component on a computer with incompatible OS/architecture will cause a failure.

Note that the driver need a ServicePermission to get the service reference of the HardwareManager (it can be obtained alternatively from the ApplicationManager). The  driver can than retrieve the current hardware configuration immediately or register a org.ogema.core.hardwaremanager.HardwareListener to get notifications about changes in the hardware configuration. The common way is though to retrieve the configuration at the initialization phase and if needed (e.g. the needed hardware not detected at this time but it could be connected later) to register the HardwareListener too.

 

Clone this wiki locally