8.3. Cast of Characters

DA consists of a single device manager, a number of device services, driver locator services, and driver services. Briefly, DA performs the following duties:

  • Device detection. With the aid of native drivers, DA can detect whether a device is connected and can register a device service to represent its functionality.

  • Device refinement. The device manager automatically refines a device service by consulting drivers and registering new device services. In the meantime, the device manager also asks driver locators to find and download new drivers on the fly to participate in this process.

  • Reconfiguration. When no driver can be found in the device refinement process to represent a device in one way, the device manager may try alternative device services to represent the device in a different way.

Let's first look at each of the main entities in DA and what role they play at a high level, then we'll get our hands dirty examining them in action.

8.3.1. Device Service

A device service exposes the functionality provided by a physical device through its service interface. It must extend the org.osgi.service.device.Device interface. For example, ParallelService, whose service interface represents operations on a parallel port, may look like this:

/**
 * ParallelService accesses data using the parallel port.
 */
public interface ParallelService
   extends org.osgi.service.device.Device
{
   /**
    * Gets the output stream to write to the specified parallel port.
    * Closing the stream closes the port.
    * @param port the specification for the parallel port.
    */
   public OutputStream getOutputStream(String port);
   /** Gets the input stream to read from the parallel port. */
   public InputStream getInputStream(String port);
}

The org.osgi.service.device.Device interface defines only one method:

public void noDriverFound();

This method is used in the reconfiguration process for a device, which is described later in this chapter. It does not represent device operations, and implementations not concerned with the reconfiguration scenario should provide an empty method body.

In DA, registration and unregistration of the device service corresponds to the attachment and detachment of the physical device. For example, when you plug an external ZIP disk drive into the parallel port, ParallelService is registered with the framework and can be obtained and invoked by any client bundle that wishes to access the port. Later, when you unplug the ZIP drive, ParallelService is then unregistered in accordance with the changed reality in the physical world.[1]

[1] ParallelService's unregistration does not mean the parallel port is gone. It means that no device is connected to the port, so there's no need to provide a service designed to communicate through the parallel interface.

By monitoring ParallelService unregistration events, the client bundles can find out that the parallel port is vacated and can take suitable action using techniques described in Chapter 5.

From the client bundle's perspective, it is often desirable to access the device at different levels. For example, most applications care about retrieving and storing files when they use a ZIP drive, rather than transferring bits directly through the parallel port using ParallelService. They probably would prefer ZipDiskService at a higher level of abstraction, like this:

public interface ZipDiskService extends
   org.osgi.service.device.Device {

   /** Gets input stream to read from a file. */
   public InputStream readFile(String fileName);

   /**
    * Gets input stream to read from the file locked with a password.
    */
   public InputStream readFile(String fileName, String password);

   /** Locks the file with a password. */
   public void LockFile(String fileName, String password);
   ...
}

In this sense, we say ParallelService is refined by ZipDiskService. If both are registered, client bundles now can access the same device at different levels of abstraction as needed. A ZIP diagnostic utility may call ParallelService to send or get raw bits from the parallel port; an image downloading service, on the other hand, would call ZipDiskService to save files to the ZIP drive without knowing the parallel channel at the lower layer.

When a device service is registered, it must be registered with at least one service property under the name DEVICE_CATEGORY. For instance, the parallel service could be registered with the property DEVICE_CATEGORY=parallel, whereas ZipDiskService could be registered with DEVICE_CATEGORY=removable_disk. In addition, the following properties may also be included:

  • DEVICE_CLASS

  • DEVICE_MODEL

  • DEVICE_MAKE

  • DEVICE_SERIAL

  • DEVICE_REVISION

These service properties help define the nature of the device, and serve as the basis for the device refinement process.

The OSGi consortium intends to work with appropriate organizations to standardize many device service interface APIs. For example, there may be a USB device service interface, a modem device service interface, a switch device service interface, and so on, in the future. At the time of this writing, neither a standard device service API nor a standard device category exists. We look at a few device service interface in later sections, but they are by no means standard.

Driver services are responsible for evaluating an existing device service and registering other device services to refine it.

8.3.2. Driver Services

In DA parlance, the term driver means not just the low-level device drivers in the operating system. The low-level drivers, such as the one that you would download from Iomega's Web site and enables access to your parallel ZIP drive, are entities outside the OSGi framework and are referred to as the base drivers in the specification. Base drivers are responsible for detecting devices. For example, a base driver can poll a parallel port periodically to see whether a device is connected, and if so, register ParallelService.

Within DA, there are other entities also referred to as drivers. The job of these drivers is to register the appropriate device services in an attempt to refine the existing device service with new ones that offer richer semantics or different levels of abstraction. For example, semantically, ZipDiskService is at a higher level than ParallelService. Because drivers within DA make refinement of device services happen, they are called the refinement drivers in the specification.

A refinement driver usually comes with its own bundle.[2] The driver bundle registers an org.osgi.service.device.Driver service when it is started and usually carries a number of device services in the bundle as candidates for refining certain kinds of device services registered in the framework. Figure 8.2 shows the structure of a driver bundle used to refine ParallelService to ZipDiskService. Let's call it the parallel-zip driver.

[2] We use driver and driver service without defining their difference. The former is equated to a driver bundle, which registers the latter. If the driver is selected by the device manager, it is also responsible for registering the refined device service.

Figure 8.2. A driver bundle. It registers the Driver service when it is first started and carries ZipDiskService as a candidate for refining ParallelService when asked.


Driver bundles can be installed and activated beforehand, or they may be downloaded, installed, and activated on the fly by driver locators (which are explained in the next section).

Each refining driver is uniquely identified by its driver ID. If two drivers differ in any one of the following aspects, their driver IDs must be different as well:

  • Vendor. Driver IDs of IEEE 1394 drivers from Apple and Sony must differ.

  • Type. IDs of modem drivers must be different from those of serial drivers.

  • Revisions. Drivers from the same vendor for the same type of device must have different driver IDs if they have different revision numbers.

The driver ID is required to be one of the service properties when a Driver service is registered with the framework.

The Driver service is an “expert” on the capabilities of the device services contained in the driver bundle and what kind of device services registered in the framework can be refined by them. It stands ready to advise the device manager in the device refinement process. The device manager asks: Given the device service just registered, how well can the device services you know of further refine it? All existing Driver services are queried with the following method defined in the Driver interface:

public int match(ServiceReference sr) throws Exception;

The service reference sr belongs to the device service to be refined, and a return value from this call indicates the confidence level of the driver to refine it. For example, when asked to match ParallelService, the parallel-zip driver yields a big integer value (Use me!), because it knows that ZipDiskService refines ParallelService perfectly. However, it returns zero if EthernetService is refined, because it knows that ZipDiskService cannot be accessed through Ethernet at all.

Based on the Driver services' replies, the device manager selects the highest bidder and instructs it to register the new device services. This is achieved by the other method defined in the Driver service interface:

public String attach(ServiceReference sr) throws Exception;

This method should register the new device services and return null. In so doing, it attaches the driver to the existing device service. In our example, the parallel-zip driver is chosen to register ZipDiskService and is attached to ParallelService.

This API also serves a secondary function: referring other drivers. If the current driver chosen by the device manager knows of another driver that can better attach to the device service, it returns a non-null referral driver ID, informing the device manager to use the other driver rather than register any device services itself.

8.3.3. Driver Locator

Refinement drivers may be present already when the device manager makes its round to query each. However, if a driver locator service is registered, the device manager asks the driver locator service to find and download driver bundles on the fly, and the new drivers still get a chance to participate in the device refinement process.

The driver locator service encapsulates the knowledge of the whereabouts of refinement drivers for a particular device service. Multiple driver locators can be present in the framework, and each may implement a different search strategy or target repository.

The org.osgi.service.device.DriverLocator interface defines the following method for finding drivers:

public String[] findDrivers(Dictionary prop);

The dictionary prop contains the service properties for the device service whose refining drivers are sought. The method returns a set of driver IDs to the device manager.

The other method defined in the DriverLocator interface is

public InputStream loadDriver(String driverID) throws IOException;

With the driver ID obtained from the findDrivers call, the device manager downloads the driver bundle from the input stream returned by this method and installs and starts it in the framework.

8.3.4. Device Manager

The device manager is the conductor orchestrating the actions of device services, drivers, and driver locators. It is an invisible player because it does not register any service of its own. It drives the refinement process in the following sequence:

1.
The device manager monitors device service registrations.

2.
When it is notified that a device service has been registered, it asks all available driver locators to download appropriate drivers that can refine the device service.

3.
The device manager then queries all existing drivers regarding how well they can refine the device.

4.
Of the replies the device manager selects the best driver and instructs that driver to register its device services as a refinement.

You may have noticed that in step 4, registration of refined device services causes step 2 to be repeated. The process continues until step 3, when none of the refinement drivers returns a positive bid. Figure 8.3 shows one iteration in the refinement process.

Figure 8.3. Refining device service. S1 is a device service, DM is the device manager, DL1 and DL2 are driver locator services, and D1 and D2 are driver services. (a) A device service S1 is registered in the framework, triggering DM to ask the two existing driver locators whether they know any driver that can refine S1. DL2 replies positively. (b) DM asks DL2 to download the driver, which DM installs and activates in the framework, resulting in the registration of a new driver service, D3. (c) DM queries each of the drivers regarding how well it can refine S1. Driver D2 yields the highest bid. (d) DM selects D2, which registers a refined service S2 for S1. This sequence repeats itself for S2.


The design of the DA attempts to reuse as many mechanisms from the OSGi framework as possible. Essentially, it is about mapping the physical devices, which are dynamic and versatile, to services in the OSGi framework, which are equally dynamic and flexible.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.167.183