A.2. Chapter 8—Device Access

A.2.1. Serial Service and Driver Locator

A.2.1.1. com/acme/service/device/serial/SerialService.java
package com.acme.service.device.serial;
import javax.comm.SerialPortEventListener;
import org.osgi.service.device.Device;

/**
 * The serial device service represents an available serial port
 * on the host. If multiple ports are available, we claim
 * ownership for them and register an instance of this service
 * for each of the ports.
 *
 * It also allows multiple event listeners to be added for
 * SerialPortEvents, which are delivered to the listeners
 * synchronously.
 *
 * Do not disable the CTS event notification, because DA relies on
 * that to detect if a device is connected to or disconnected from the
 * serial port.
 */
public interface SerialService extends Device {

   /**
    * The confidence values used by the driver to match this service.
    */
   public static final int MATCH_OK = 1;

   /**
    * Gets the SerialPort object for the port.
    */
   public javax.comm.SerialPort getPort();

   /**
    * Adds an event listener for SerialPortEvents.
    */
   public void addEventListener(SerialPortEventListener l);

   /**
    * Removes the event listener for SerialPortEvents.
    */
   public void removeEventListener(SerialPortEventListener l);
}

A.2.1.2. com/acme/impl/device/serial/SerialServiceImpl.java
package com.acme.impl.device.serial;
import java.util.*;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import com.acme.service.device.serial.SerialService;

class SerialServiceImpl implements SerialService {
   private SerialPort port;
   private Vector listeners;

   public SerialPort getPort() {
      return this.port;
   }
   public void addEventListener(SerialPortEventListener l) {
      listeners.addElement(l);
   }

   public void removeEventListener(SerialPortEventListener l) {
      listeners.removeElement(l);
   }

   public void noDriverFound() {
   }

   void fireEvent(SerialPortEvent e) {
      synchronized (listeners) {
         for (int i=0; i<listeners.size(); i++) {
            SerialPortEventListener l = (SerialPortEventListener)
                  listeners.elementAt(i);
            l.serialEvent(e);
         }
      }
   }

   SerialServiceImpl(SerialPort port) {
      this.port = port;
      this.listeners = new Vector(4);
   }
}

A.2.1.3. com/acme/impl/device/serial/SerialListener.java
package com.acme.impl.device.serial;
import java.util.Properties;
import javax.comm.*;
import org.osgi.framework.*;

class SerialListener implements SerialPortEventListener {
   private BundleContext context;
   private ServiceRegistration serialReg = null;
   private SerialServiceImpl serialService = null;
   private String[] deviceClazzes = {
      "com.acme.service.device.serial.SerialService",
      "org.osgi.service.device.Device" };
   SerialListener(BundleContext ctxt) {
      this.context = ctxt;
   }

   public void serialEvent(SerialPortEvent e) {
      SerialPort port = (SerialPort) e.getSource();
      int t = e.getEventType();
      if (t == SerialPortEvent.CTS) {
         // listen to CTS pin of the serial interface
         boolean plugged = e.getNewValue();
         if (plugged) {
            // register a serial device service when a
            // device is connected to the serial port
            Properties props = new Properties();
            props.put("DEVICE_CATEGORY", "serial");
            props.put("DEVICE_MAKE", "Acme");
            props.put("Port", port.getName());
            serialService = new SerialServiceImpl(port);
            serialReg = context.registerService(deviceClazzes,
               serialService, props);
         } else {
            // unregister the serial device service when
            // the device is disconnected from the serial
            // port
            if (serialReg != null) {
               serialReg.unregister();
               serialReg = null;
               serialService = null;
            }
         }
      } else {
         if (serialService != null)
            serialService.fireEvent(e);
      }
   }
}

A.2.1.4. com/acme/impl/locator/DriverLocatorImpl.java
package com.acme.impl.locator;
import java.util.*;
import java.net.URL;
import java.io.InputStream;
import java.io.IOException;
import org.osgi.service.device.*;

/**
 * This driver locator tries to find a refining driver for the
 * serial device category in its own bundle as a resource.
 */
public class DriverLocatorImpl implements DriverLocator {
   // Map a device category to IDs of refining drivers
   private Hashtable categoryMap;
   // Map a driver ID to a URL to the driver bundle
   private Hashtable driverMap;
   static final String DRIVER_ID_PREFIX = "com.acme.device.drivers";

   public String[] findDrivers(Dictionary props) {
      String category = (String) props.get("DEVICE_CATEGORY");
      String make = (String) props.get("DEVICE_MAKE");
      if (!"Acme".equalsIgnoreCase(make))
         return null;
      String[] ids = (String []) categoryMap.get(category);
      return ids;
   }

   public InputStream loadDriver(String id) throws IOException {
      URL u = (URL) driverMap.get(id);
      if (u != null) {
         return u.openStream();
      }
      return null;
   }

   public DriverLocatorImpl() {
      categoryMap = new Hashtable(3);
      categoryMap.put("serial",
         new String[] { DRIVER_ID_PREFIX + ".serial.modem.0"});
      driverMap = new Hashtable(3);
      driverMap.put(DRIVER_ID_PREFIX + ".serial.modem.0",
            this.getClass().getResource("/drivers/driver.jar"));
   }
}

A.2.1.5. com/acme/impl/device/serial/Activator.java
package com.acme.impl.device.serial;
import java.util.*;
import javax.comm.*;
import org.osgi.framework.*;
import com.acme.impl.locator.DriverLocatorImpl;

/**
 * The bundle activator registers a driver locator service,
 * finds all available serial ports, and defines a listener
 * for each port, detecting if a device is connected to
 * the serial port.
 */
public class Activator implements BundleActivator {
   private Vector ports = new Vector(4);

   public void start(BundleContext ctxt) throws Exception {
      // register a driver locator
      Properties props = new Properties();
      props.put("description",
        "Locating refining drivers for " +
        "the serial device category.");
      ctxt.registerService(
         "org.osgi.service.device.DriverLocator",
         new DriverLocatorImpl(), props);
      for (Enumeration enum =
         CommPortIdentifier.getPortIdentifiers();
         enum.hasMoreElements(); )
      {
         CommPortIdentifier portId =
            (CommPortIdentifier) enum.nextElement();
         if (portId.getPortType() ==
            CommPortIdentifier.PORT_SERIAL) {
            try {
               SerialPort port = (SerialPort)
                  portId.open("SerialService", 2000);
               port.notifyOnCTS(true);
               SerialListener serialListener =
                  new SerialListener(ctxt);
               port.addEventListener(serialListener);
               ports.addElement(port);
               if (port.isCTS()) {
                  SerialPortEvent event = new SerialPortEvent(
                     port, SerialPortEvent.CTS, false, true);
                  serialListener.serialEvent(event);
               }
            } catch (PortInUseException e) {
               // the serial port has been occupied; skip it
            } catch (TooManyListenersException e) {
               // can't happen
            }
         }
      }
   }

   public void stop(BundleContext ctxt) throws Exception {
      for (int i=0; i<ports.size(); i++) {
         SerialPort port = (SerialPort) ports.elementAt(i);
         port.removeEventListener();
         port.close();
      }
   }
}

A.2.1.6. Manifest
Bundle-Activator: com.acme.impl.device.serial.Activator
Export-Package: com.acme.service.device.serial
Import-Package: org.osgi.service.device

A.2.2. Driver Service and Modem Service

A.2.2.1. com/acme/impl/driver/DriverImpl.java
package com.acme.impl.driver;
import java.util.Properties;
import java.io.*;
import javax.comm.*;
import org.osgi.framework.*;
import org.osgi.service.device.*;
import com.acme.service.device.serial.SerialService;
import com.acme.impl.device.modem.ModemServiceImpl;

class DriverImpl implements Driver {
   private BundleContext context;
   private ServiceRegistration reg;
   private ServiceReference serialRef;

   public int match(ServiceReference sr) throws Exception {
      String category =
         (String) sr.getProperty("DEVICE_CATEGORY");
      if ("serial".equals(category)) {
         if (modemAccessed(sr))
            return SerialService.MATCH_OK;
      }
      return Device.MATCH_NONE;
   }

   public String attach(ServiceReference sr) throws Exception {
      String[] deviceClazzes = new String[] {
         "org.osgi.service.device.Device",
         "com.acme.service.device.modem.ModemService" };
      Properties props = new Properties();
      props.put("DEVICE_CATEGORY", "modem");
      props.put("DEVICE_MAKE", "Acme");
      props.put("Port", sr.getProperty("Port"));
      serialRef=sr;
      SerialService serialService = (SerialService)
            context.getService(sr);
      reg = context.registerService(deviceClazzes,
               new ModemServiceImpl(serialService),
               props);
      return null;
   }

   DriverImpl(BundleContext ctxt) {
      this.context = ctxt;
      try {
         String filter = "(objectClass=" +
      "com.acme.service.device.serial.SerialService)";
         context.addServiceListener(new ServiceListener() {
            public void serviceChanged(ServiceEvent e) {
               if (e.getType() == ServiceEvent.UNREGISTERING) {
                     if (e.getServiceReference().equals(serialRef)&&
                         if (reg != null {
                         reg.unregister();
                         reg = null;
                         serialRef = null;
                  }
               }
            }
         }, filter);
      } catch (InvalidSyntaxException e) {
         // can't happen
      }
   }

   private boolean modemAccessed(ServiceReference sr) {
      boolean isModem = false;
      SerialService ss = (SerialService) context.getService(sr);
      SerialPort port = ss.getPort();
      try {
         OutputStream out = port.getOutputStream();
         InputStream in = port.getInputStream();
         out.write("ATE0
".getBytes());
         out.flush();
         // ReceiveTimeout is set so that we won't block forever
         // in case it's not a modem
         port.enableReceiveTimeout(3000);
         byte[] buf = new byte[20];
         int byteRead;
         while (true) {
            byteRead = in.read(buf);
            if (byteRead == 0)
               break;
            String s = new String(buf, 0, byteRead);
            if (s.indexOf("
OK
") >= 0) {
               isModem = true;
               break;
            } else if (s.indexOf("
ERROR
") >=0)
               break;
         }
      } catch (Exception e) {
      } finally {
         context.ungetService(sr);
      }
      return isModem;
   }
}

A.2.2.2. com/acme/impl/driver/Activator.java
package com.acme.impl.driver;
import java.util.Properties;
import org.osgi.framework.*;

public class Activator implements BundleActivator {
   private ServiceRegistration reg;

   public void start(BundleContext ctxt) {
      Properties props = new Properties();
      props.put("DRIVER_ID",
         "com.acme.device.drivers.serial.modem.0");
      props.put("description",
         "The driver that refines a serial device to a modem device.");
      reg = ctxt.registerService("org.osgi.service.device.Driver",
         new DriverImpl(ctxt), props);
   }

   public void stop(BundleContext ctxt) {
      if (reg != null)
         reg.unregister();
   }
}

A.2.2.3. com/acme/service/device/modem/ModemService.java
package com.acme.service.device.modem;
import java.io.*;
import org.osgi.service.device.Device;

/**
 * ModemService allows access to a modem.
 */
public interface ModemService extends Device {
   /**
    * The data connection to a connected modem.
    */
   interface DataConnection {
      public OutputStream getOutputStream() throws IOException;
      public InputStream getInputStream() throws IOException;
      public void returnToCommandMode();
   }

   /** Disables the modem's speaker */
   public static final int SPEAKER_DISABLED = 0;
   /** Sets the volume of the modem's speaker to the default level */
   public static final int SPEAKER_DEFAULT = 1;

   /**
    * Dials up a modem with the given phone number.
    */
   public DataConnection dialup(String phoneNumber)
      throws IOException;

   /**
    * Hangs up the modem.
    */
   public void hangup() throws IOException;

   /**
    * Gets information about the modem.
    */
   public String getInfo() throws IOException;

   /**
    * Configures the volume of the modem's speaker.
    * @param mode the volume level of the speaker. Must be either
    * SPEAKER_DISABLED or SPEAKER_DEFAULT.
    */
   public void configureSpeaker(int mode) throws IOException;

   /**
    * Gets the value of the given S register.
    */
   public byte getSRegister(int r) throws IOException;
   /**
    * Sets the value for the given S register.
    */
   public void setSRegister(int r, byte value) throws IOException;
}

A.2.2.4. com/acme/impl/device/modem/ModemServiceImpl.java
package com.acme.impl.device.modem;
import java.io.*;
import javax.comm.*;
import com.acme.service.device.modem.ModemService;
import com.acme.service.device.serial.SerialService;

public class ModemServiceImpl implements ModemService {
   private SerialPort port;

   public void noDriverFound() {
   }

   public ModemService.DataConnection dialup(String phoneNumber)
      throws IOException
   {
      String rc = sendCommand("ATDT"+phoneNumber+"
");
      if (rc.indexOf("CONNECT") != -1) {
         return this.new DataConnectionImpl();
      }
      return null;
   }

   public void hangup() throws IOException {
      sendCommand("ATH
");
   }

   public String getInfo() throws IOException {
      String rc = sendCommand("ATI4
");
      int pos = rc.indexOf("
", 2);
      if (pos != -1)
         rc = rc.substring(2, pos);
      return rc;
   }
   public void configureSpeaker(int mode) throws IOException {
      sendCommand("ATM" + mode + "
");
   }

   public byte getSRegister(int n) throws IOException {
      String rc = sendCommand("ATS" + n + "?
");
      int pos = rc.indexOf("
", 2);
      if (pos != -1)
         rc = rc.substring(2, pos);
      return Byte.parseByte(rc);
   }

   public void setSRegister(int n, byte value) throws IOException {
      String r = sendCommand("ATS" + n + "=" + value);
   }

   public ModemServiceImpl(SerialService ss)
      throws UnsupportedCommOperationException
   {
      this.port = ss.getPort();
      port.enableReceiveTimeout(5000);
   }

   private String sendCommand(String cmd) throws IOException {
      InputStream in = port.getInputStream();
      int byteRead;
      int off = 0;
      byte[] buf = new byte[1024];
      StringBuffer sb = new StringBuffer();
      while (true) {
         byteRead = in.read(buf);
         if (byteRead == 0)
            break;
         String s = new String(buf, 0, byteRead);
         sb.append(s);
         if (s.indexOf("
OK
") >= 0)
            break;
         else if (s.indexOf("
ERROR
") >=0)
            throw new IOException(sb.toString());
      }
         return sb.toString();
   }

   class DataConnectionImpl
      implements ModemService.DataConnection
   {
      public OutputStream getOutputStream() throws IOException {
         return port.getOutputStream();
      }

      public InputStream getInputStream() throws IOException {
         return port.getInputStream();
      }

      public void returnToCommandMode() {
         try {
            getOutputStream().write("+++".getBytes());
         } catch (IOException e) {
         }
      }
   }
}

A.2.2.5. Manifest
Bundle-Activator: com.acme.impl.driver.Activator
Export-Package: com.acme.service.device.modem
Import-Package: org.osgi.service.device,
 com.acme.service.device.serial

A.2.3. Web Interface to the Serial Ports

A.2.3.1. com/acme/gui/serial/SerialServlet.java
package com.acme.gui.serial;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.comm.*;
import org.osgi.framework.*;
import com.acme.service.device.serial.*;
class SerialServlet extends HttpServlet {
   private BundleContext context;
   private static int[] bauds = { 2400, 4800, 9600, 19200,
      28800, 38400, 57600, 115200 };
   private static int[] dataBits = {
      SerialPort.DATABITS_5, SerialPort.DATABITS_6,
      SerialPort.DATABITS_7, SerialPort.DATABITS_8 };
   private static String[] dataBitsLabel = { "5", "6", "7", "8" };
   private static int[] parity = { SerialPort.PARITY_NONE,
      SerialPort.PARITY_ODD, SerialPort.PARITY_EVEN,
      SerialPort.PARITY_MARK, SerialPort.PARITY_SPACE };
   private static String[] parityLabel = {
      "None", "Odd", "Even", "Mark", "Space" };
   private static int[] stopBits = { SerialPort.STOPBITS_1,
      SerialPort.STOPBITS_2, SerialPort.STOPBITS_1_5 };
   private static String[] stopBitsLabel = { "1", "2", "1.5" };

   SerialServlet(BundleContext ctxt) {
      this.context = ctxt;
   }

   public void doGet(HttpServletRequest req,
      HttpServletResponse resp)
      throws ServletException, IOException
   {
      ServletOutputStream out = resp.getOutputStream();
      resp.setContentType("text/html");
      displayHeader(out);
      try {
         ServiceReference[] refs = context.getServiceReferences(
            "com.acme.service.device.serial.SerialService",
            null);
         if (refs == null) {
            out.println("<i>No device is found to be attached "+
                "to any of the serial ports.</i>");
         } else {
            // display serial port settings for each port found
            for (int i=0; i<refs.length; i++)
               displayControl(out, refs[i]);
         }
      } catch (InvalidSyntaxException e) {
      }
      displayFooter(out);
      out.close();
   }

   public void doPost(HttpServletRequest req,
      HttpServletResponse resp)
      throws ServletException, IOException
   {
      String message = null;
      String portName = req.getParameter("port");
      try {
         ServiceReference[] refs = context.getServiceReferences(
            "com.acme.service.device.serial.SerialService",
            "(Port=" + portName + ")");
         if (refs != null) {
            SerialService ss =
               (SerialService) context.getService(refs[0]);
            SerialPort port = ss.getPort();
            // receive new settings posted from the browser
            int baud = Integer.parseInt(
               req.getParameter("baud_select"));
            int databits = Integer.parseInt(
               req.getParameter("databits_select"));
            int stopbits = Integer.parseInt(
               req.getParameter("stopbits_select"));
            int parity = Integer.parseInt(
               req.getParameter("parity_select"));
            // set new parameters to the given serial port
             port.setSerialPortParams(baud, databits,
               stopbits, parity);
         } else {
            message = "<i>Could not set serial port parameters: "+
               "no device is attached to " + portName +
               " any longer.</i>";
         }
      } catch (InvalidSyntaxException e) {
      } catch (UnsupportedCommOperationException e) {
          message = "<i>Failed to set serial port parameters: "+
          e.toString() + "</i>";
       }
      if (message != null) {
         ServletOutputStream out = resp.getOutputStream();
         resp.setContentType("text/html");
         displayHeader(out);
         out.println(message);
         displayFooter(out);
         out.close();
      } else {
         resp.sendRedirect("/serialports");
      }
   }

   // display parameters for a given serial port
   private void displayControl(ServletOutputStream out,
      ServiceReference ref)
      throws ServletException, IOException
   {
      SerialService ss = (SerialService) context.getService(ref);
      SerialPort port = ss.getPort();
      String name = port.getName();
      out.println("<form action="/serialports" method=post>
");
      out.println("<table border=0>
" +
         "<tr><td colspan=5><b>Port: " +
         "<font color=green>" + name + "</font>" +
         "</b></td></tr>
" +
         "<tr>
" +
         "<td>" +
         displaySelect("baud_select",
              bauds, null, port.getBaudRate()) +
         "</td>
" +
         "<td>" +
         displaySelect("databits_select",
              dataBits, dataBitsLabel,
              port.getDataBits()) +
         "</td>
" +
         "<td>" +
         displaySelect("stopbits_select",
              stopBits, stopBitsLabel,
              port.getStopBits()) +
         "</td>
" +
         "<td>" +
         displaySelect("parity_select",
              parity, parityLabel, port.getParity()) +
         "</td>
" +
         "<td>
" +
         "<input type=submit value=Set>
" +
         "</td>
" +
         "</tr>
" +
         "</table>
" +
         "<input type=hidden name=port value="" + name + "">
" +
         "</form>");
      context.ungetService(ref);
   }

   private String displaySelect(String widgetId,
             int[] candidates,
             String[] labels,
             int value)
   {
      StringBuffer sb = new StringBuffer();
      sb.append("<select name="" + widgetId + "">
");
      for (int i=0; i<candidates.length; i++) {
         sb.append("<option value="" + candidates[i] + """ +
           (candidates[i] == value ? " selected" : "") +">" +
           (labels != null ? labels[i] :
            Integer.toString(candidates[i])) + "
");
      }
      sb.append("</select>
");
      return sb.toString();
   }

   private void displayHeader(ServletOutputStream out)
      throws ServletException, IOException
   {
      out.println("<HTML>
" +
         "<HEAD>
" +
         "<TITLE>Serial Port Configuration</TITLE>
" +
         "</HEAD>
" +
         "<BODY BGCOLOR=#cccccc>");
   }
   private void displayFooter(ServletOutputStream out)
      throws ServletException, IOException
   {
      out.println("</BODY>
" +
         "</HTML>");
   }
}

A.2.3.2. com/acme/gui/serial/Activator.java
package com.acme.gui.serial;
import java.net.*;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
import org.osgi.framework.*;
import org.osgi.service.http.*;

public class Activator implements BundleActivator {
   private HttpService http;
   private final String SERVLET_ALIAS = "/serialports";

   public void start(BundleContext context)
      throws ServletException, NamespaceException
   {
      ServiceReference ref = context.getServiceReference(
            "org.osgi.service.http.HttpService");
      http = (HttpService) context.getService(ref);
      SerialServlet servlet = new SerialServlet(context);
      http.registerServlet(SERVLET_ALIAS, servlet, null, null);
   }

   public void stop(BundleContext context) {
      if (http != null) {
         http.unregister(SERVLET_ALIAS);
      }
   }
}

A.2.3.3. com/acme/gui/serial/Manifest
Bundle-Activator: com.acme.gui.serial.Activator
Import-Package: org.osgi.service.http,
 com.acme.service.device.serial,
 javax.servlet, javax.servlet.http

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

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