changeset 275:2f7da76bdc69 tip

./comment
author onazarkina
date Fri, 09 Sep 2016 13:20:20 +0300
parents f7b7bfe5485e 935bcaf28721
children
files Makefile src/se/classes/com/oracle/dio/gpio/impl/GPIOEventHandler.java src/se/classes/com/oracle/dio/gpio/impl/GPIOPinEventHandler.java src/se/classes/com/oracle/dio/gpio/impl/GPIOPortEventHandler.java src/se/classes/com/oracle/dio/impl/EventQueue.java src/se/classes/com/oracle/dio/registry/RegistryList.java src/se/classes/com/oracle/dio/uart/impl/UARTEventHandler.java src/se/classes/com/oracle/dio/utils/Logging.java src/se/classes/jdk/dio/mmio/AccessOutOfBoundsException.java src/se/classes/jdk/dio/mmio/MMIODevice.java src/se/classes/jdk/dio/mmio/MMIODeviceConfig.java src/se/classes/jdk/dio/mmio/MMIOEvent.java src/se/classes/jdk/dio/mmio/MMIOEventListener.java src/se/classes/jdk/dio/mmio/MMIOPermission.java src/se/classes/jdk/dio/mmio/RawBlock.java src/se/classes/jdk/dio/mmio/RawMemory.java src/se/classes/jdk/dio/mmio/RawRegister.java src/se/classes/jdk/dio/mmio/package-info.java src/se/native/com/oracle/dio/dio_event_queue.cpp src/se/native/com/oracle/dio/uart/impl/jni_uart.cpp src/share/classes/com/oracle/dio/impl/AbstractPeripheral.java src/share/classes/com/oracle/dio/spibus/impl/SPICompositeMessageImpl.java src/share/classes/com/oracle/dio/uart/impl/UARTImpl.java src/share/classes/com/oracle/dio/utils/ActionFactory.java src/share/classes/com/oracle/dio/utils/Utils.java src/share/classes/jdk/dio/Device.java src/share/classes/jdk/dio/DeviceManager.java src/share/classes/jdk/dio/adc/ADCChannel.java src/share/classes/jdk/dio/dac/DACChannel.java src/share/classes/jdk/dio/generic/GenericBufferIODevice.java src/share/classes/jdk/dio/power/PowerManaged.java src/share/classes/jdk/dio/pwm/PWMChannel.java src/share/classes/jdk/dio/spibus/SPIDevice.java src/share/linux/native/com/oracle/dio/i2c/i2c.c src/share/linux/native/com/oracle/dio/uart/serial.c src/share/linux/native/com/oracle/dio/uart/uart.c src/share/native/com/oracle/dio/javacall_uart.h
diffstat 173 files changed, 8660 insertions(+), 6346 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgtags	Fri Sep 09 13:20:20 2016 +0300
@@ -0,0 +1,1 @@
+8afb91f7282cf47cac272928caf4bd3fee91bc7b me-8.2
--- a/Makefile	Mon Aug 29 14:45:05 2016 +0300
+++ b/Makefile	Fri Sep 09 13:20:20 2016 +0300
@@ -1,3 +1,4 @@
+
 #########################################################################
 # Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -74,7 +75,7 @@
 
 # define variables needed for dir setup
 TARGET_CPU_LEGACY_LIB ?= arm
-DIO_VERSION := 1.0.1
+DIO_VERSION := 1.1
 BUILD_NUMBER ?= dev
 
 ifneq ($(BUILD_NUMBER),dev)
--- a/config/dio.properties-raspberrypi	Mon Aug 29 14:45:05 2016 +0300
+++ b/config/dio.properties-raspberrypi	Fri Sep 09 13:20:20 2016 +0300
@@ -24,27 +24,21 @@
 #
 #########################################################################
 
-2  = deviceType: gpio.GPIOPin, pinNumber:2, name:GPIO2, mode:1, predefined:true
-3  = deviceType: gpio.GPIOPin, pinNumber:3, name:GPIO3, mode:1, predefined:true
-4  = deviceType: gpio.GPIOPin, pinNumber:4, name:GPIO4, predefined:true
-17 = deviceType: gpio.GPIOPin, pinNumber:17, name:GPIO17, predefined:true
-27 = deviceType: gpio.GPIOPin, pinNumber:27, name:GPIO27, predefined:true
-22 = deviceType: gpio.GPIOPin, pinNumber:22, name:GPIO22, predefined:true
-10 = deviceType: gpio.GPIOPin, pinNumber:10, name:GPIO10, predefined:true
-9  = deviceType: gpio.GPIOPin, pinNumber:9, name:GPIO9, predefined:true
-11 = deviceType: gpio.GPIOPin, pinNumber:11, name:GPIO11, predefined:true
-14 = deviceType: gpio.GPIOPin, pinNumber:14, name:GPIO14, mode:4, direction:1, predefined:true
-15 = deviceType: gpio.GPIOPin, pinNumber:15, name:GPIO15, mode:4, direction:1, predefined:true
-18 = deviceType: gpio.GPIOPin, pinNumber:18, name:GPIO18, mode:4, direction:1, predefined:true
-23 = deviceType: gpio.GPIOPin, pinNumber:23, name:GPIO23, mode:4, direction:1, predefined:true
-24 = deviceType: gpio.GPIOPin, pinNumber:24, name:GPIO24, mode:4, direction:1, predefined:true
-25 = deviceType: gpio.GPIOPin, pinNumber:25, name:GPIO25, mode:4, direction:1, predefined:true
-8  = deviceType: gpio.GPIOPin, pinNumber:8, name:GPIO8, mode:4, direction:1, predefined:true
-7  = deviceType: gpio.GPIOPin, pinNumber:7, name:GPIO7, mode:4, direction:1, predefined:true
+# RPi rev2 P1 header pins
+1 = deviceType: gpio.GPIOPin, pinNumber:4, name:GPIO4, predefined:true
+2 = deviceType: gpio.GPIOPin, pinNumber:7, name:GPIO7, mode:4, direction:1, predefined:true
+3 = deviceType: gpio.GPIOPin, pinNumber:17, name:GPIO17, predefined:true
+4 = deviceType: gpio.GPIOPin, pinNumber:18, name:GPIO18, mode:4, direction:1, predefined:true
+5 = deviceType: gpio.GPIOPin, pinNumber:22, name:GPIO22, predefined:true
+6 = deviceType: gpio.GPIOPin, pinNumber:23, name:GPIO23, mode:4, direction:1, predefined:true
+7 = deviceType: gpio.GPIOPin, pinNumber:24, name:GPIO24, mode:4, direction:1, predefined:true
+8 = deviceType: gpio.GPIOPin, pinNumber:25, name:GPIO25, mode:4, direction:1, predefined:true
+9 = deviceType: gpio.GPIOPin, pinNumber:27, name:GPIO27, predefined:true
 
-12 = deviceType: spibus.SPIDevice, name:SPI_Slave, deviceNumber:0, address:0, csActive:1, wordLength:8, clockFrequency:500000, clockMode:1, bitOrdering:1, predefined:true
+300 = deviceType: spibus.SPIDevice, name:SPI0.0, controllerNumber:0, address:0, csActive:1, wordLength:8, clockFrequency:500000, clockMode:1, bitOrdering:1, predefined:true
 
-40 = deviceType: uart.UART, deviceName:ttyAMA0, name:UART, baudRate:19200, dataBits:8, parity:0, stopBits:1, flowControl:0, predefined:true
-gpio.GPIOPin = initValue:0, deviceNumber:0, direction:0, mode:1, trigger:3, predefined:true
+100 = deviceType: uart.UART, controllerName:ttyAMA0, name:ttyAMA0, baudRate:19200, dataBits:8, parity:0, stopBits:1, flowControl:0, predefined:true
+
+gpio.GPIOPin = initValue:0, controllerNumber:0, direction:0, mode:1, trigger:0, predefined:true
 uart.UART = baudRate:19200, parity:0, dataBits:8, stopBits:1, flowControl:0, predefined:true
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/gpio.rules-raspberrypi	Fri Sep 09 13:20:20 2016 +0300
@@ -0,0 +1,36 @@
+#########################################################################
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#########################################################################
+
+# udev script to access GPIO devices without root privileges.
+# copy it to "/etc/udev/rules.d/gpio.rules" file.
+# "gpio" user group must be present at the host
+# note! tested on RaspberryPi only. 
+
+SUBSYSTEM=="gpio", KERNEL=="gpiochip[0-9]*", ACTION=="add", DEVPATH=="/devices/virtual/gpio/gpiochip[0-9]*",\
+ PROGRAM="/bin/sh -c 'cd /sys%p/subsystem; chown :gpio export unexport; chmod g+w export unexport'"
+ 
+SUBSYSTEM=="gpio", KERNEL=="gpio[0-9]*", ACTION=="add", DEVPATH=="/devices/virtual/gpio/gpio[0-9]*",\
+ PROGRAM="/bin/sh -c 'cd /sys%p; chown :gpio direction value edge; chmod g+w direction value edge'"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/java.policy.ext.rpi	Fri Sep 09 13:20:20 2016 +0300
@@ -0,0 +1,49 @@
+#########################################################################
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+#########################################################################
+
+// this an example of java policy file with security permissions required for DIO library.
+
+// policy for DIO framework
+grant codeBase "file:./dio.jar" {
+        permission "java.util.PropertyPermission" "jdk.dio.registry", "read";
+        permission "java.io.FilePermission" "./dio.properties-raspberrypi", "read,write";
+        permission "java.lang.RuntimePermission" "loadLibrary.dio";
+// used by classloader when libdio.so is loaded
+        permission "java.util.PropertyPermission" "user.dir", "read";
+// these are necessary for open_by_id case (note! there should be no DeviceMgmtPermission)
+        permission jdk.dio.adc.ADCPermission "*:*";
+        permission jdk.dio.atcmd.ATPermission "*:*";
+        permission jdk.dio.counter.CounterPermission "*:*";
+        permission jdk.dio.dac.DACPermission "*:*";
+        permission jdk.dio.generic.GenericPermission "*:*";
+        permission jdk.dio.gpio.GPIOPinPermission "*:*", "open,setdirection";
+        permission jdk.dio.gpio.GPIOPortPermission "*:*";
+        permission jdk.dio.i2cbus.I2CPermission "*:*";
+        permission jdk.dio.pwm.PWMPermission "*:*";
+        permission jdk.dio.spibus.SPIPermission "*:*";
+        permission jdk.dio.uart.UARTPermission "*:*";
+        permission jdk.dio.watchdog.WatchdogTimerPermission "*:*";
+};
--- a/samples/spi/src/dio/spi/MCP3008Config.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/samples/spi/src/dio/spi/MCP3008Config.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,7 +30,11 @@
  */
 package dio.spi;
 
+import java.io.IOException;
+import java.io.OutputStream;
+
 import jdk.dio.*;
+import jdk.dio.DeviceConfig;
 import jdk.dio.spibus.*;
 
 /*
@@ -49,4 +53,9 @@
     public int getDeviceNumber() {
         return this.deviceNumber;
     }
+
+    @Override
+    public int serialize(OutputStream out) throws IOException {
+        return 0;
+    }
 }
--- a/samples/spi/src/dio/spi/MCP3008Impl.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/samples/spi/src/dio/spi/MCP3008Impl.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,10 +32,20 @@
 package dio.spi;
 
 import java.io.*;
+import java.io.IOException;
 import java.nio.*;
+import java.nio.ByteBuffer;
+
 import jdk.dio.*;
+import jdk.dio.DeviceConfig;
+import jdk.dio.DeviceManager;
+import jdk.dio.DeviceNotFoundException;
+import jdk.dio.UnavailableDeviceException;
+import jdk.dio.UnsupportedDeviceTypeException;
 import jdk.dio.spi.*;
+import jdk.dio.spi.AbstractDevice;
 import jdk.dio.spibus.*;
+import jdk.dio.spibus.SPIDevice;
 
 /*
  * MCP3008Impl
@@ -88,4 +98,9 @@
         }
     }
 
+    @Override
+    public java.nio.ByteOrder getByteOrder() {
+        return java.nio.ByteOrder.nativeOrder();
+    }
+
 }
--- a/samples/spi/src/dio/spi/MCP3008Provider.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/samples/spi/src/dio/spi/MCP3008Provider.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,8 +31,14 @@
 package dio.spi;
 
 import java.io.*;
+import java.io.IOException;
+
 import jdk.dio.*;
+import jdk.dio.DeviceConfig;
+import jdk.dio.DeviceException;
 import jdk.dio.spi.*;
+import jdk.dio.spi.AbstractDevice;
+import jdk.dio.spi.DeviceProvider;
 
 /*
  * MCP3008Provider
@@ -69,4 +75,9 @@
         }
         return false;
     }
+
+    @Override
+    public DeviceConfig<? super MCP3008> deserialize(java.io.InputStream in) {
+        return null;
+    }
 }
--- a/src/se/classes/com/oracle/dio/gpio/impl/GPIOEventHandler.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.oracle.dio.gpio.impl;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-import jdk.dio.Device;
-import com.oracle.dio.impl.AbstractPeripheral;
-import com.oracle.dio.impl.Event;
-import com.oracle.dio.impl.EventHandler;
-import com.oracle.dio.impl.EventQueue;
-
-abstract class GPIOEventHandler<T extends AbstractPeripheral> implements EventHandler {
-
-    private final Hashtable<T, Object> listeners = new Hashtable<>();
-    private static final int QUEUE_BUFFER_SIZE = 4096;
-    protected final EventQueue queue = EventQueue.createEventQueue(QUEUE_BUFFER_SIZE);
-
-    protected <U extends GPIOEvent> GPIOEventHandler(Class<U> eventClass) {
-        queue.registerForEvent(eventClass, this);
-    }
-
-    synchronized void setEventListener(T peripheral, Object listener) {
-        listeners.put(peripheral, listener);
-    }
-
-    synchronized void removeEventListener(T peripheral) {
-        listeners.remove(peripheral);
-    }
-
-    public synchronized boolean handleEvent(Event event) {
-        GPIOEvent e = (GPIOEvent)event;
-        Enumeration<T> peripherals = listeners.keys();
-        while (peripherals.hasMoreElements()) {
-            T p = peripherals.nextElement();
-            if (p.getHandle().getNativeHandle() == e.getNativeHandle()) {
-                Object listener = listeners.get(p);
-                handleGPIOEvent(listener, p, e);
-            }
-        }
-        return true;
-    }
-
-    protected abstract void handleGPIOEvent(Object listener, T peripheral, GPIOEvent event);
-
-    protected static abstract class GPIOEvent extends Event {
-        int getNativeHandle() {
-            byte[] payload = getPayload();
-            int handle = ((0x00ff & payload[0]) << 24) |
-                         ((0x00ff & payload[1]) << 16) |
-                         ((0x00ff & payload[2]) << 8)  |
-                         ((0x00ff & payload[3]));
-            return handle;
-        }
-    }
-}
--- a/src/se/classes/com/oracle/dio/gpio/impl/GPIOPinEventHandler.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.oracle.dio.gpio.impl;
-
-import jdk.dio.gpio.PinEvent;
-import jdk.dio.gpio.PinListener;
-import java.nio.Buffer;
-
-final class GPIOPinEventHandler extends GPIOEventHandler<GPIOPinImpl> {
-
-    private static final GPIOPinEventHandler instance = new GPIOPinEventHandler();
-
-    private GPIOPinEventHandler() {
-        super(InternalEvent.class);
-    }
-
-    static GPIOPinEventHandler getInstance() {
-        return instance;
-    }
-
-    static {
-        setNativeEntries(instance.queue.getNativeBuffer(), InternalEvent.class);
-    }
-
-    protected void handleGPIOEvent(Object listener, GPIOPinImpl pin, GPIOEvent event) {
-        boolean value = ((InternalEvent)event).getValue();
-        PinListener pinListener = (PinListener)listener;
-        pinListener.valueChanged(new PinEvent(pin, value));
-    }
-
-    public static class InternalEvent extends GPIOEvent {
-        boolean getValue() {
-            byte[] payload = getPayload();
-            int value = ((int)(0x00ff & payload[4]) << 24) |
-                        ((int)(0x00ff & payload[5]) << 16) |
-                        ((int)(0x00ff & payload[6]) << 8)  |
-                        ((int)(0x00ff & payload[7]));
-            return (value != 0);
-        }
-    }
-
-    private static native void setNativeEntries(Buffer buffer, Class<InternalEvent> eventClass);
-}
--- a/src/se/classes/com/oracle/dio/gpio/impl/GPIOPortEventHandler.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.oracle.dio.gpio.impl;
-
-import jdk.dio.gpio.PortEvent;
-import jdk.dio.gpio.PortListener;
-import java.nio.Buffer;
-
-final class GPIOPortEventHandler extends GPIOEventHandler<GPIOPortImpl> {
-
-    private static final GPIOPortEventHandler instance = new GPIOPortEventHandler();
-
-    private GPIOPortEventHandler() {
-        super(InternalEvent.class);
-    }
-
-    static GPIOPortEventHandler getInstance() {
-        return instance;
-    }
-
-    static {
-        setNativeEntries(instance.queue.getNativeBuffer(), InternalEvent.class);
-    }
-
-    protected void handleGPIOEvent(Object listener, GPIOPortImpl port, GPIOEvent event) {
-        int value = ((InternalEvent)event).getValue();
-        PortListener portListener = (PortListener)listener;
-        portListener.valueChanged(new PortEvent(port, value));
-    }
-
-    class InternalEvent extends GPIOEvent {
-        int getValue() {
-            byte[] payload = getPayload();
-            int value = ((int)(0x00ff & payload[4]) << 24) |
-                        ((int)(0x00ff & payload[5]) << 16) |
-                        ((int)(0x00ff & payload[6]) << 8)  |
-                        ((int)(0x00ff & payload[7]));
-            return value;
-        }
-    }
-
-    private static native void setNativeEntries(Buffer buffer, Class<InternalEvent> eventClass);
-}
--- a/src/se/classes/com/oracle/dio/impl/Event.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/classes/com/oracle/dio/impl/Event.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,26 +24,22 @@
  */
 
 package com.oracle.dio.impl;
+import jdk.dio.Device;
 
 /**
  * Base class for all events.
  */
 public class Event {
     private byte[] payload;
-
+    private Class<? extends Device> eventType;
     /**
      * Creates event object with payload.
      * @param payload event payload
+     * @param clazz  device class that describes event type
      */
-    public Event(byte[] payload) {
+    public Event(Class<? extends Device> clazz, byte[] payload) {
         this.payload = payload;
-    }
-
-    /**
-     * Creates event object with empty payload.
-     */
-    public Event() {
-        payload = null;
+        eventType = clazz;
     }
 
     /**
@@ -55,8 +51,9 @@
         return payload;
     }
 
-    void setPayload(byte[] payload) {
-        this.payload = payload;
+    /** Returns type of this event. */
+    public Class<? extends Device> getType() {
+        return eventType;
     }
 
     @Override
--- a/src/se/classes/com/oracle/dio/impl/EventQueue.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/classes/com/oracle/dio/impl/EventQueue.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,8 @@
 import java.util.ArrayList;
 import java.util.LinkedList;
 
+import jdk.dio.Device;
+
 /**
  * Event queue implementation.
  */
@@ -43,6 +45,10 @@
     private Thread                  nativeEventThread;
     private Thread                  eventDispatchThread;
 
+    public Thread getEventDispatchThread(){
+        return eventDispatchThread;
+    }
+
     private static class QueueInstanceHolder {
         private static EventQueue sharedEventQueue = new EventQueue(SHARED_QUEUE_BUFFER_SIZE);
     }
@@ -51,15 +57,7 @@
         buffer = ByteBuffer.allocateDirect(bufferSize);
         buffer.position(0).limit(0);
         startQueue();
-    }
-
-    /**
-     * This method creates new event queue.
-     * @param bufferSize size of the native buffer in bytes
-     * @return event queue
-     */
-    public static EventQueue createEventQueue(int bufferSize) {
-        return new EventQueue(bufferSize);
+        setNativeEntries(buffer);
     }
 
     /**
@@ -78,22 +76,15 @@
                 try {
                     while (true) {
                         while (buffer.hasRemaining()) {
-                            Class<? extends Event> eventClass = getEventClass(buffer, buffer.position());
+                            Class<? extends Device> eventType = getEventType(buffer);
                             byte[] payload = null;
-                            byte hibyte = buffer.get();
-                            byte lobyte = buffer.get();
-                            short len = (short)((0xff00 & (hibyte << 8)) | (lobyte & 0xff));
+                            short len = buffer.getShort();
                             if (len > 0) {
                                 payload = new byte[len];
                                 buffer.get(payload);
                             }
-                            try {
-                                Event e = eventClass.newInstance();
-                                e.setPayload(payload);
-                                postEvent(e);
-                            } catch (InstantiationException | IllegalAccessException ex) {
-                                // do nothing, just skip
-                            }
+                            Event e = new Event(eventType, payload);
+                            postEvent(e);
                         }
                         buffer.position(0).limit(0);
                         buffer.wait();
@@ -108,24 +99,23 @@
     private class EventDispatchThread implements Runnable {
         @Override
         public void run() {
+            Event evt = null;
             while (true) {
                 synchronized (queue) {
                     try {
                         if (queue.isEmpty()) {
                             queue.wait();
                         }
-
-                        while (!queue.isEmpty()) {
-                            Event evt = queue.poll();
-                            if (evt != null) {
-                                dispatch(evt);
-                            }
-                        }
+                        evt = queue.poll();
                     } catch (InterruptedException ex) {
                         // do something
                     }
+                }//synchronized queue
+
+                if (evt != null) {
+                    dispatch(evt);
                 }
-            }
+            }//while true
         }
     }
 
@@ -152,7 +142,7 @@
      * @param evtClass class object of event class
      * @param handler listener
      */
-    public <T extends Event> void registerForEvent(Class<T> evtClass, EventHandler handler) {
+    public <T extends Device> void registerForEvent(Class<T> evtClass, EventHandler handler) {
         if (evtClass == null || handler == null) {
             throw new IllegalArgumentException();
         }
@@ -166,14 +156,9 @@
     private void dispatch(final Event evt) {
         synchronized (listeners) {
             for (int i = 0; i < listeners.size(); i += 2) {
-                if (listeners.get(i).equals(evt.getClass())) {
-                    final EventHandler h = (EventHandler)listeners.get(i+1);
-                    new Thread() {
-                        @Override
-                        public void run() {
-                            h.handleEvent(evt);
-                        }
-                    }.start();
+                if (listeners.get(i).equals(evt.getType())) {
+                    EventHandler h = (EventHandler)listeners.get(i+1);
+                    h.handleEvent(evt);
                 }
             }
         }
@@ -188,15 +173,19 @@
         eventDispatchThread.start();
     }
 
-    /**
-     * Returns native buffer. This is intended solely for components with native
-     * event generating. Java components must not call any methods of the
-     * returned buffer object.
-     * @return native buffer
-     */
-    public Buffer getNativeBuffer() {
-        return buffer;
+    private Class<? extends Device> getEventType(ByteBuffer buffer) {
+        char c;
+        StringBuilder sb = new StringBuilder();
+        while (0 != (c = (char)buffer.get())) {
+            sb.append(c);
+        }
+        try {
+            return (Class<? extends Device>)Class.forName(sb.toString());
+        } catch (ClassNotFoundException cnfe) {
+        }
+
+        return Device.class;
     }
 
-    private static native Class<? extends Event> getEventClass(ByteBuffer buffer, int position);
+    private static native void setNativeEntries(ByteBuffer buffer);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/se/classes/com/oracle/dio/impl/EventQueueManager.java	Fri Sep 09 13:20:20 2016 +0300
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package com.oracle.dio.impl;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import com.oracle.dio.impl.AbstractPeripheral;
+
+import jdk.dio.Device;
+import jdk.dio.DeviceEvent;
+
+public final class EventQueueManager implements EventHandler {
+
+    private final Vector<Integer> registeredTypes = new Vector<>();
+    private final Hashtable<Integer, AbstractPeripheral> listenerRegistry = new Hashtable();
+
+    private static final EventQueueManager instance = new EventQueueManager();
+
+    private final EventQueue queue = EventQueue.getSharedEventQueue();
+
+    public static EventQueueManager getInstance() {
+        return instance;
+    }
+
+    private EventQueueManager() {
+    }
+
+    private int getHash(int deviceType, int eventType, int nativeHandle) {
+        return deviceType * (deviceType + deviceType * eventType) + nativeHandle;
+    }
+
+    public void setEventListener(Class<? extends Device> clazz, int eventSubType, AbstractPeripheral listener) {
+        final int eventType = clazz.hashCode();
+        final int nativeHandle = listener.getHandle().getNativeHandle();
+        if (!registeredTypes.contains(eventType)) {
+            // prevent overriding that leads to message losses
+            queue.registerForEvent(clazz, this);
+            registeredTypes.add(eventType);
+        }
+
+        listenerRegistry.put(getHash(eventType, eventSubType, nativeHandle), listener);
+    }
+
+    public void removeEventListener(Class<? extends Device> clazz, int eventSubType, AbstractPeripheral listener) {
+        final int eventType = clazz.hashCode();
+        final int nativeHandle = listener.getHandle().getNativeHandle();
+        listenerRegistry.remove(getHash(eventType, eventSubType, nativeHandle));
+    }
+
+    public void postEvent(AbstractPeripheral receiver, int subEventType, DeviceEvent event) {
+        final Tuple tuple = new Tuple(receiver.getDescriptor().getInterface(), subEventType, receiver, event);
+        queue.postEvent(tuple);
+    }
+
+
+    /**
+     * This method is called by EventQueue.dispatch(). Each call is made on a
+     * separate thread.
+     * @param event a previously queued event to handle
+     */
+    public boolean handleEvent(Event event) {
+        if (event instanceof Tuple) {
+            Tuple tuple = (Tuple)event;
+            tuple.receiver.processDeviceEvent(tuple.eventType, tuple.event);
+        } else {
+            IntBuffer payload = ByteBuffer.wrap(event.getPayload()).asIntBuffer();
+            // all data are stored in big endian format
+            int handle = payload.get();
+            int subEvent  = payload.get();
+            int data   = payload.get();
+            AbstractPeripheral handler = listenerRegistry.get(getHash(event.getType().hashCode(), subEvent, handle));
+            if (handler != null) {
+                handler.processNativeEvent(subEvent, data);
+            }
+        }
+        return true;
+    }
+
+    public boolean isDispatchThread() {
+        return queue.getEventDispatchThread().equals(Thread.currentThread());
+    }
+
+    /* simple holder for custom data */
+    private final class Tuple extends Event {
+        private final DeviceEvent event;
+        private final int eventType;
+        private final AbstractPeripheral receiver;
+        private Tuple(Class<? extends Device> type, int eventType, AbstractPeripheral receiver, DeviceEvent event) {
+            super(type, null);
+            this.eventType = eventType;
+            this.receiver = receiver;
+            this.event = event;
+        }
+    }
+}
--- a/src/se/classes/com/oracle/dio/impl/FakeHandle.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/classes/com/oracle/dio/impl/FakeHandle.java	Fri Sep 09 13:20:20 2016 +0300
@@ -24,6 +24,8 @@
  */
 package com.oracle.dio.impl;
 
+import com.oracle.dio.utils.Constants;
+
 /**
  * Pure Java device handle.
  */
@@ -33,6 +35,11 @@
     private FakeHandle() {
     }
 
+    @Override
+    public void close() {
+        device_reference = Constants.INVALID_HANDLE;
+    }
+
     public static synchronized FakeHandle getFakeHandle() {
         FakeHandle h = new FakeHandle();
         h.device_reference = counter++;
--- a/src/se/classes/com/oracle/dio/impl/Platform.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/classes/com/oracle/dio/impl/Platform.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,17 @@
  */
 package com.oracle.dio.impl;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.Objects;
+
+import com.oracle.dio.utils.ExceptionMessage;
+import com.oracle.dio.utils.Logging;
 
 public final class Platform {
     /** Don't let anyone instantiate this class */
@@ -43,4 +52,105 @@
                 }
             });
     }
+
+    /**
+     * Compare two objects by recursive inspection of their fields.
+     *
+     * @param obj1 first object to compare
+     * @param obj2 second object to compare
+     *
+     * @return true if objects classes are the same and all objects
+     *         members are equals.
+     *
+     * @note unimplemented
+     */
+    public static boolean equals(Object obj1, Object obj2) {
+        if (null == obj1 || null == obj2) {
+            return false;
+        }
+
+        try {
+            return serialize(obj1).equals(serialize(obj2));
+        } catch (IOException e) {
+            return obj1 == obj2;
+        }
+    }
+
+    /**
+     * Creates a copy of object.
+     *
+     * @param obj object to be cloned.
+     * @return a clone of object.
+     */
+    public static Object clone(Object obj)  {
+        try {
+            return deserialize(serialize(obj));
+        } catch (IOException e) {
+            Logging.reportWarning(ExceptionMessage.format(ExceptionMessage.CLONE_ERROR));
+            return obj;
+        }
+    }
+
+    /**
+     * Convert the given byte array into object form.
+     *
+     * @note The object must be annotated with @SerializeMe tag
+     * @note So far ByteArrayInputStream is only useful
+     *       InputStream implementation
+     *
+     * @param in the serialized form of the objects to restore
+     *
+     * @return the root object
+     */
+    public static Object deserialize(InputStream in) throws IOException {
+        Objects.requireNonNull(in, "Invalid InputStream");
+        throw new IOException("Platform.deserialize() is not implemented");
+    }
+
+
+
+    /**
+     *  Converts the given object and everything is refers to
+     *       into serialized form.
+     * @note The object must be annotated with @SerializeMe tag
+     * @param obj root the root object to start serialization from
+     * @param os output stream to store serialized data
+     *
+     * @return a size of serialized data
+     */
+    public static int serialize(Object obj, OutputStream os) throws IOException {
+        Objects.requireNonNull(os, "Invalid OutputStream");
+        throw new IOException("Platform.serialize() is not implemented");
+    }
+
+    /**
+     * Returns the hash code value for given object.
+     *
+     * @param obj       the target for hash calculation
+     * @param initVal hash code initial value
+     * @param factor  hash factor
+     * @return a hash code value for this object.
+     */
+    public static int hash(final Object obj, final int initVal, final int factor) {
+        try {
+            return serialize(obj).hashCode();
+        } catch (IOException e) {
+            return System.identityHashCode(obj);
+        }
+    }
+
+
+    // =========================
+    private static byte[] serialize(Object obj) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        serialize(obj, baos);
+        baos.close();
+        return baos.toByteArray();
+    }
+
+    private static Object deserialize(byte[] ba) throws IOException {
+        return deserialize(new ByteArrayInputStream(ba));
+    }
+
+
 }
--- a/src/se/classes/com/oracle/dio/registry/RegistryData.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/classes/com/oracle/dio/registry/RegistryData.java	Fri Sep 09 13:20:20 2016 +0300
@@ -25,8 +25,10 @@
 
 package com.oracle.dio.registry;
 
+import java.util.Enumeration;
 import java.util.Hashtable;
-import java.util.Enumeration;
+
+import com.oracle.dio.utils.Logging;
 
 public final class RegistryData {
     private final Hashtable<String, Object> data;
@@ -44,6 +46,11 @@
     }
 
     public void putCharacterProperty(String key, String value) {
+        if (null == value) {
+            Logging.reportInformation("RegistryData ignores null element");
+            return;
+        }
+
         data.put(key, value);
     }
 
--- a/src/se/classes/com/oracle/dio/registry/RegistryImpl.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/classes/com/oracle/dio/registry/RegistryImpl.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,20 +76,16 @@
     }
 
     @Override
-    public synchronized void register(int id, Class<T> intf,
-                                      DeviceConfig<? super T> config,
-                                      String name,
-                                      String... properties)
+    public synchronized int register(PeripheralDescriptorImpl<? super T> descriptor)
                                       throws UnsupportedOperationException, IOException {
+        int id = super.register(descriptor);
+        Class<? extends Device> intf = descriptor.getInterface();
         Properties registry = loadRegistry();
         RegistryContent content = readRegistryContent(registry);
         String factory = DeviceRegistryFactory.registryFactoryName(intf);
         if (factory == null) {
             throw new UnsupportedDeviceTypeException("Unsupported type: " + intf.getName());
         }
-        DeviceDescriptor<? super T> descriptor = new PeripheralDescriptorImpl(id, name, config, intf, properties);
-
-        Registry.checkPermission(descriptor, DeviceMgmtPermission.REGISTER);
 
         RegistryData data = null;
         try {
@@ -106,10 +102,15 @@
             registry.remove(Integer.toString(id));
             throw e;
         }
+
+        return id;
     }
 
     @Override
     public synchronized DeviceDescriptor unregister(int id) {
+        Registry.checkPermission(null, id, DeviceMgmtPermission.UNREGISTER);
+        Registry.checkID(id);
+
         Properties registry = loadRegistry();
         RegistryContent content = readRegistryContent(registry);
         RegistryData config = content.get(id);
@@ -122,8 +123,6 @@
             throw new IllegalArgumentException("Device cannot be unregistered");
         }
 
-        Registry.checkPermission(d, DeviceMgmtPermission.UNREGISTER);
-
         content.remove(id);
         registry.remove(Integer.toString(id));
         try {
@@ -166,7 +165,7 @@
     }
 
     private void saveRegistry(Properties registry) throws IOException {
-        String path = Configuration.getSystemProperty(REGISTRY_FILE_PATH);
+        final String path = Configuration.getSystemProperty(REGISTRY_FILE_PATH);
         if (path == null) {
             throw new IOException("Registry is not available");
         }
--- a/src/se/classes/com/oracle/dio/registry/RegistryList.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/classes/com/oracle/dio/registry/RegistryList.java	Fri Sep 09 13:20:20 2016 +0300
@@ -25,11 +25,11 @@
 
 package com.oracle.dio.registry;
 
+import java.util.Arrays;
+import java.util.Enumeration;
 import java.util.Vector;
-import java.util.Enumeration;
-import java.util.Arrays;
-import java.lang.Cloneable;
 
+import com.oracle.dio.utils.Logging;
 public final class RegistryList implements Cloneable {
     private final Vector data;
 
@@ -42,6 +42,10 @@
     }
 
     public void add(Object element) {
+        if (null == element) {
+            Logging.reportInformation("RegistryList ignores null element");
+            return;
+        }
         data.add(element);
     }
 
--- a/src/se/classes/com/oracle/dio/uart/impl/ModemSignalDispatcher.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/classes/com/oracle/dio/uart/impl/ModemSignalDispatcher.java	Fri Sep 09 13:20:20 2016 +0300
@@ -24,12 +24,15 @@
  */
 package com.oracle.dio.uart.impl;
 
+import java.nio.Buffer;
+import java.util.*;
+
+import com.oracle.dio.impl.Event;
+import com.oracle.dio.impl.EventHandler;
+import com.oracle.dio.impl.EventQueue;
 import com.oracle.dio.utils.Constants;
-import com.oracle.dio.impl.EventQueue;
-import com.oracle.dio.impl.EventHandler;
-import com.oracle.dio.impl.Event;
-import java.util.*;
-import java.nio.Buffer;
+
+import jdk.dio.uart.ModemUART;
 
 /**
  * Serial signal proxy
@@ -61,11 +64,10 @@
 
     private static ModemSignalDispatcher instance;
     private static final int QUEUE_BUFFER_SIZE = 4096;
-    private final EventQueue queue =
-                             EventQueue.createEventQueue(QUEUE_BUFFER_SIZE);
+    private final EventQueue queue = EventQueue.getSharedEventQueue();
 
     private ModemSignalDispatcher() {
-        queue.registerForEvent(SignalEvent.class, this);
+        queue.registerForEvent(ModemUART.class, this);
     }
 
     private static class SerialContext {
@@ -150,6 +152,11 @@
     }
 
     private static class SignalEvent extends Event {
+
+        SignalEvent(byte[] payload) {
+            super(ModemUART.class, payload);
+        }
+
         int getHandler() {
             byte[] payload = getPayload();
             int handler = (((int)(0x00ff & payload[0])) << 24) | (((int)(0x00ff & payload[1])) << 16) |
@@ -175,7 +182,7 @@
      * @param event a previously queued event to handle
      */
     public boolean handleEvent(Event event) {
-        SignalEvent e = (SignalEvent)event;
+        SignalEvent e = new SignalEvent(event.getPayload());
 
         int serialHandler = e.getHandler();
         int signalLine = e.getLine();
@@ -191,13 +198,6 @@
         return true;
     }
 
-    static {
-        setNativeEntries(instance.queue.getNativeBuffer(), SignalEvent.class);
-    }
-
-    private static native void setNativeEntries(Buffer buffer,
-                                                Class<SignalEvent> eventClass);
-
     /**
      * Starts serial signal listening
      *
--- a/src/se/classes/com/oracle/dio/uart/impl/UARTEventHandler.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.dio.uart.impl;
-
-import com.oracle.dio.impl.EventQueue;
-import com.oracle.dio.impl.EventHandler;
-import com.oracle.dio.impl.Event;
-import java.util.Hashtable;
-import java.nio.Buffer;
-
-class UARTEventHandler implements EventHandler {
-
-    private static class UARTHash {
-        final int port;
-        final int eventType;
-        final int hash;
-
-        UARTHash(int port, int eventType) {
-            this.port = port;
-            this.eventType = eventType;
-            long lHash = 17 + port;
-            lHash = 17 * lHash + eventType;
-            hash = (int)lHash;
-        }
-
-        @Override
-        public int hashCode() {
-            return hash;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof UARTHash) {
-                return (((UARTHash)obj).port == port &&
-                        ((UARTHash)obj).eventType == eventType);
-            } else {
-                return super.equals(obj);
-            }
-        }
-    }
-
-    private final Hashtable<UARTHash, UARTImpl> listenerRegistry = new Hashtable();
-    private static final UARTEventHandler instance = new UARTEventHandler();
-    private static final int QUEUE_BUFFER_SIZE = 4096;
-    private final EventQueue queue =
-                             EventQueue.createEventQueue(QUEUE_BUFFER_SIZE);
-
-    static UARTEventHandler getInstance() {
-        return instance;
-    }
-
-    private UARTEventHandler() {
-        queue.registerForEvent(UARTEvent.class, this);
-    }
-
-    void addEventListener(int eventType, UARTImpl uart) {
-        if (null == uart) {
-            throw new NullPointerException("uart == null");
-        }
-        int port = uart.getHandle().getNativeHandle();
-        listenerRegistry.put(new UARTHash(port, eventType), uart);
-    }
-
-    UARTImpl getEventListener(int port, int eventType) {
-        return listenerRegistry.get(new UARTHash(port, eventType));
-    }
-
-    void removeEventListener(int eventType, UARTImpl uart) {
-        int port = uart.getHandle().getNativeHandle();
-        listenerRegistry.remove(new UARTHash(port, eventType));
-    }
-
-    protected static class UARTEvent extends Event {
-        UARTEvent(byte[] payload) {
-            super(payload);
-        }
-
-        public UARTEvent() {
-            super();
-        }
-
-        int getPort() {
-            byte[] payload = getPayload();
-            int port = (((int)(0x00ff & payload[0])) << 24) | (((int)(0x00ff & payload[1])) << 16) |
-                       (((int)(0x00ff & payload[2])) << 8 ) | (((int)(0x00ff & payload[3])));
-            return port;
-        }
-        int getEventType() {
-            byte[] payload = getPayload();
-            int type = (((int)(0x00ff & payload[4])) << 24) | (((int)(0x00ff & payload[5])) << 16) |
-                       (((int)(0x00ff & payload[6]) << 8 ) | (((int)(0x00ff & payload[7]))));
-            return type;
-        }
-        int getBytesProcessed() {
-            byte[] payload = getPayload();
-            int bytes = (((int)(0x00ff & payload[8]))  << 24) | (((int)(0x00ff & payload[9]) << 16)) |
-                        (((int)(0x00ff & payload[10])) << 8 ) | (((int)(0x00ff & payload[11])));
-            return bytes;
-        }
-    }
-
-    public void sendTimeoutEvent(int handle) {
-        int type = jdk.dio.uart.UARTEvent.INPUT_DATA_AVAILABLE;
-        int bytes = -1;
-        byte[] payload = new byte[] {
-                (byte)(handle >> 24), (byte)(handle >> 16), (byte)(handle >> 8), (byte)(handle),
-                (byte)(type >> 24), (byte)(type >> 16), (byte)(type >> 8), (byte)(type),
-                (byte)(bytes >> 24), (byte)(bytes >> 16), (byte)(bytes >> 8), (byte)(bytes),
-            };
-        UARTEvent event = new UARTEvent(payload);
-        queue.postEvent(event);
-    }
-
-    /**
-     * This method is called by EventQueue.dispatch(). Each call is made on a
-     * separate thread.
-     * @param event a previously queued event to handle
-     */
-    public boolean handleEvent(Event event) {
-        UARTEvent e = (UARTEvent)event;
-        int port = e.getPort();
-        int type = e.getEventType();
-        int bytesProcessed = e.getBytesProcessed();
-        UARTImpl uart = listenerRegistry.get(new UARTHash(port, type));
-        if (uart != null) {
-            uart.processEvent(type, bytesProcessed);
-        }
-        return true;
-    }
-
-    static {
-        setNativeEntries(instance.queue.getNativeBuffer(), UARTEvent.class);
-    }
-
-    private static native void setNativeEntries(Buffer buffer,
-                                                Class<UARTEvent> eventClass);
-
-    public boolean isDispatchThread() {
-        /*
-         * because of nature of dispatch for se where an event processed in separate thread
-         */
-        return false;
-    }
-}
--- a/src/se/classes/com/oracle/dio/utils/ExceptionMessage.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/classes/com/oracle/dio/utils/ExceptionMessage.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,16 +57,18 @@
     public static final int DEVICE_READONLY_PERMISSION_COLLECTION    = DEVICE_FIRST + 21;
     public static final int DEVICE_OPEN_WITH_DEVICENAME_UNSUPPORTED  = DEVICE_FIRST + 22;
     public static final int BUFFER_IS_MODIFIED                       = DEVICE_FIRST + 23;
-    public static final int DEVICE_LAST = BUFFER_IS_MODIFIED;
+    public static final int CLONE_ERROR                              = DEVICE_FIRST + 24;
+    public static final int ZERO_CAPACITY_BUFFER                     = DEVICE_FIRST + 25;
+    public static final int NULL_LISTENER                            = DEVICE_FIRST + 26;
+    public static final int DEVICE_LAST = NULL_LISTENER;
 
     public static final int ADC_FIRST = DEVICE_LAST + 1;
     public static final int ADC_ANOTHER_OPERATION_PROGRESS           = ADC_FIRST + 0;
     public static final int ADC_NONPOSITIVE_INTERVAL                 = ADC_FIRST + 1;
-    public static final int ADC_LESS_MINIMAL_INTERVAL                = ADC_FIRST + 2;
+    public static final int ADC_OUT_OF_RANGE_INTERVAL                = ADC_FIRST + 2;
     public static final int ADC_CANNOT_START_ACQUISITION             = ADC_FIRST + 3;
     public static final int ADC_ARGUMENT_LOW_GREATER_THAN_HIGH       = ADC_FIRST + 4;
-    public static final int ADC_BUFFER_NO_SPACE                      = ADC_FIRST + 5;
-    public static final int ADC_LAST = ADC_BUFFER_NO_SPACE;
+    public static final int ADC_LAST = ADC_ARGUMENT_LOW_GREATER_THAN_HIGH;
 
     public static final int ATCMD_FIRST = ADC_LAST + 1;
     public static final int ATCMD_DATA_CONNECTION_UNSUPPORTED        = ATCMD_FIRST + 0;
@@ -81,46 +83,42 @@
     public static final int COUNTER_NOT_SUSPENDED                    = COUNTER_FIRST + 5;
     public static final int COUNTER_IS_STARTED                       = COUNTER_FIRST + 6;
     public static final int COUNTER_NONPOSITIVE_LIMIT_AND_INTERVAL   = COUNTER_FIRST + 7;
-    public static final int COUNTER_NULL_LISTENER                    = COUNTER_FIRST + 8;
-    public static final int COUNTER_IS_SUSPENDED                     = COUNTER_FIRST + 9;
+    public static final int COUNTER_IS_SUSPENDED                     = COUNTER_FIRST + 8;
     public static final int COUNTER_LAST = COUNTER_IS_SUSPENDED;
 
     public static final int DAC_FIRST = COUNTER_LAST + 1;
     public static final int DAC_GENERATION_IS_ACTIVE                 = DAC_FIRST + 0;
-    public static final int DAC_NO_BUFFER_DATA                       = DAC_FIRST + 1;
-    public static final int DAC_NONPOSITIVE_INTERVAL                 = DAC_FIRST + 2;
-    public static final int DAC_LESS_MINIMAL_INTERVAL                = DAC_FIRST + 3;
-    public static final int DAC_UNACCEPTABLE_VALUE                   = DAC_FIRST + 4;
-    public static final int DAC_CANNOT_START_CONVERSION              = DAC_FIRST + 5;
+    public static final int DAC_NONPOSITIVE_INTERVAL                 = DAC_FIRST + 1;
+    public static final int DAC_OUT_OF_RANGE_INTERVAL                = DAC_FIRST + 2;
+    public static final int DAC_UNACCEPTABLE_VALUE                   = DAC_FIRST + 3;
+    public static final int DAC_CANNOT_START_CONVERSION              = DAC_FIRST + 4;
     public static final int DAC_LAST = DAC_CANNOT_START_CONVERSION;
 
     public static final int GPIO_FIRST = DAC_LAST + 1;
-    public static final int GPIO_TRIGGER_OR_MODE                     = GPIO_FIRST + 0;
-    public static final int GPIO_MODE_NOT_FOR_DIRINPUTONLY           = GPIO_FIRST + 1;
-    public static final int GPIO_MODE_NOT_FOR_DIROUTPUTONLY          = GPIO_FIRST + 2;
-    public static final int GPIO_MODE_NOT_FOR_DIRBOTH                = GPIO_FIRST + 3;
-    public static final int GPIO_INVALID_DIRECTION                   = GPIO_FIRST + 4;
-    public static final int GPIO_ILLEGAL_DIRECTION_OR_INIT_VALUE     = GPIO_FIRST + 5;
-    public static final int GPIO_DIR_UNSUPPORTED_BY_PIN_CONFIG       = GPIO_FIRST + 6;
-    public static final int GPIO_SET_TO_INPUT_PIN                    = GPIO_FIRST + 7;
-    public static final int GPIO_REGISTER_LISTENER_TO_OUTPUT_PIN     = GPIO_FIRST + 8;
-    public static final int GPIO_CANNOT_START_NOTIFICATION           = GPIO_FIRST + 9;
-    public static final int GPIO_LISTENER_ALREADY_ASSIGNED           = GPIO_FIRST + 10;
-    public static final int GPIO_DIR_SHOULD_BE_INPUT_OR_OUTPUT       = GPIO_FIRST + 11;
-    public static final int GPIO_INCOMPATIBLE_DIR                    = GPIO_FIRST + 12;
-    public static final int GPIO_WRITE_TO_INPUT_PORT                 = GPIO_FIRST + 13;
-    public static final int GPIO_REGISTER_LISTENER_TO_OUTPUT_PORT    = GPIO_FIRST + 14;
-    public static final int GPIO_LAST = GPIO_REGISTER_LISTENER_TO_OUTPUT_PORT;
+    public static final int GPIO_INVALID_TRIGGER                     = GPIO_FIRST + 0;
+    public static final int GPIO_INVALID_DIRECTION                   = GPIO_FIRST + 1;
+    public static final int GPIO_INVALID_MODE                        = GPIO_FIRST + 2;
+    public static final int GPIO_ILLEGAL_DIR                         = GPIO_FIRST + 3;
+    public static final int GPIO_DIR_UNSUPPORTED_BY_PIN_CONFIG       = GPIO_FIRST + 4;
+    public static final int GPIO_SET_TO_INPUT_PIN                    = GPIO_FIRST + 5;
+    public static final int GPIO_REGISTER_LISTENER_TO_OUTPUT_PIN     = GPIO_FIRST + 6;
+    public static final int GPIO_CANNOT_START_NOTIFICATION           = GPIO_FIRST + 7;
+    public static final int GPIO_LISTENER_ALREADY_ASSIGNED           = GPIO_FIRST + 8;
+    public static final int GPIO_DIR_SHOULD_BE_INPUT_OR_OUTPUT       = GPIO_FIRST + 9;
+    public static final int GPIO_INCOMPATIBLE_DIR                    = GPIO_FIRST + 10;
+    public static final int GPIO_WRITE_TO_INPUT_PORT                 = GPIO_FIRST + 11;
+    public static final int GPIO_REGISTER_LISTENER_TO_OUTPUT_PORT    = GPIO_FIRST + 12;
+    public static final int GPIO_INCOMPATIBLE_MODE                   = GPIO_FIRST + 13;
+    public static final int GPIO_LAST = GPIO_INCOMPATIBLE_MODE;
 
     public static final int I2CBUS_FIRST = GPIO_LAST + 1;
     public static final int I2CBUS_ALREADY_TRANSFERRED_MESSAGE       = I2CBUS_FIRST + 0;
-    public static final int I2CBUS_NULL_BUFFER                       = I2CBUS_FIRST + 1;
-    public static final int I2CBUS_NEGATIVE_SKIP_ARG                 = I2CBUS_FIRST + 2;
-    public static final int I2CBUS_DIFFERENT_BUS_SLAVE_OPERATION     = I2CBUS_FIRST + 3;
-    public static final int I2CBUS_BUFFER_GIVEN_TWICE                = I2CBUS_FIRST + 4;
-    public static final int I2CBUS_CLOSED_DEVICE                     = I2CBUS_FIRST + 5;
-    public static final int I2CBUS_FIRST_MESSAGE                     = I2CBUS_FIRST + 6;
-    public static final int I2CBUS_LAST_MESSAGE                      = I2CBUS_FIRST + 7;
+    public static final int I2CBUS_NEGATIVE_SKIP_ARG                 = I2CBUS_FIRST + 1;
+    public static final int I2CBUS_DIFFERENT_BUS_SLAVE_OPERATION     = I2CBUS_FIRST + 2;
+    public static final int I2CBUS_BUFFER_GIVEN_TWICE                = I2CBUS_FIRST + 3;
+    public static final int I2CBUS_CLOSED_DEVICE                     = I2CBUS_FIRST + 4;
+    public static final int I2CBUS_FIRST_MESSAGE                     = I2CBUS_FIRST + 5;
+    public static final int I2CBUS_LAST_MESSAGE                      = I2CBUS_FIRST + 6;
     public static final int I2CBUS_LAST = I2CBUS_LAST_MESSAGE;
 
     public static final int MMIO_FIRST = I2CBUS_LAST + 1;
@@ -148,32 +146,25 @@
     public static final int PWM_NONPOSITIVE_PERIOD                   = PWM_FIRST + 1;
     public static final int PWM_OUT_OF_RANGE_PERIOD                  = PWM_FIRST + 2;
     public static final int PWM_ILLEGAL_WIDTH_OR_COUNT               = PWM_FIRST + 3;
-    public static final int PWM_NULL_SRC                             = PWM_FIRST + 4;
-    public static final int PWM_NULL_LISTENER                        = PWM_FIRST + 5;
-    public static final int PWM_NO_DATA                              = PWM_FIRST + 6;
-    public static final int PWM_NULL_SRC1_OR_SRC2                    = PWM_FIRST + 7;
-    public static final int PWM_GENERATION_SESSION_ACTIVE            = PWM_FIRST + 8;
+    public static final int PWM_GENERATION_SESSION_ACTIVE            = PWM_FIRST + 4;
     public static final int PWM_LAST = PWM_GENERATION_SESSION_ACTIVE;
 
     public static final int SPIBUS_FIRST = PWM_LAST + 1;
-    public static final int SPIBUS_NULL_BUFFER                       = SPIBUS_FIRST + 0;
-    public static final int SPIBUS_SLAVE_WORD_LENGTH                 = SPIBUS_FIRST + 1;
-    public static final int SPIBUS_BYTE_NUMBER_BELIES_WORD_LENGTH    = SPIBUS_FIRST + 2;
-    public static final int SPIBUS_LAST = SPIBUS_BYTE_NUMBER_BELIES_WORD_LENGTH;
+    public static final int SPIBUS_SLAVE_WORD_LENGTH                 = SPIBUS_FIRST + 0;
+    public static final int SPIBUS_BYTE_NUMBER_BELIES_WORD_LENGTH    = SPIBUS_FIRST + 1;
+    public static final int SPIBUS_BYTE_BUFFER_MODIFICATION          = SPIBUS_FIRST + 2;
+    public static final int SPIBUS_TRANSFER_INTERRUPTED              = SPIBUS_FIRST + 3;
+    public static final int SPIBUS_LAST = SPIBUS_TRANSFER_INTERRUPTED;
 
     public static final int UART_FIRST = SPIBUS_LAST + 1;
-    public static final int UART_CANT_GET_PORT_NAME               = UART_FIRST + 0;
+    public static final int UART_CANT_GET_PORT_NAME                  = UART_FIRST + 0;
     public static final int UART_UTF8_UNCONVERTIBLE_DEVNAME          = UART_FIRST + 1;
-    public static final int UART_NULL_SRC_OR_LISTENER                = UART_FIRST + 2;
-    public static final int UART_NULL_SRC1_OR_SRC2_OR_LISTENER       = UART_FIRST + 3;
-    public static final int UART_NULL_DST                            = UART_FIRST + 4;
-    public static final int UART_NULL_SRC                            = UART_FIRST + 5;
-    public static final int UART_ACTIVE_READ_OPERATION               = UART_FIRST + 6;
-    public static final int UART_ACTIVE_WRITE_OPERATION              = UART_FIRST + 7;
-    public static final int UART_UNKNOWN_SIGNAL_ID                   = UART_FIRST + 8;
-    public static final int UART_SIGNALS_NOT_BITWISE_COMBINATION     = UART_FIRST + 9;
-    public static final int UART_LISTENER_ALREADY_REGISTERED         = UART_FIRST + 10;
-    public static final int UART_NEGATIVE_TIMEOUT                    = UART_FIRST + 11;
+    public static final int UART_ACTIVE_READ_OPERATION               = UART_FIRST + 2;
+    public static final int UART_ACTIVE_WRITE_OPERATION              = UART_FIRST + 3;
+    public static final int UART_UNKNOWN_SIGNAL_ID                   = UART_FIRST + 4;
+    public static final int UART_SIGNALS_NOT_BITWISE_COMBINATION     = UART_FIRST + 5;
+    public static final int UART_LISTENER_ALREADY_REGISTERED         = UART_FIRST + 6;
+    public static final int UART_NEGATIVE_TIMEOUT                    = UART_FIRST + 7;
 
     private static final String strings[] = {
 
@@ -200,16 +191,18 @@
         "actions are empty",
         "Invalid permission class: %s",
         "Cannot add a Permission to a readonly PermissionCollection",
-        "Opening with deviceName is unsupported",
+        "Opening with controllerName is unsupported",
         "Buffer was modified by application",
+        "The object can't be cloned",
+        "The buffer has a zero-capacity",
+        "listener is null",
 
         // adc messages
         "Another operation on ADC channel is in progress",
         "'interval' is negative or 0",
-        "'interval' is less than minimal sampling interval",
+        "'interval' is out of the supported range",
         "Cannot start acquisition",
         "Argument 'low' is greater than 'high'",
-        "No free space in buffer",
 
         // atcmd messages
         "Emulator does not support data connection",
@@ -223,23 +216,19 @@
         "Counting wasn't suspended",
         "Counting is already started",
         "Both limit and interval are equal or less than 0",
-        "Counting listener is null",
         "Counting is already suspended",
 
         // dac messages
         "Generation is already active",
-        "No data in buffer",
         "'interval' is negative or 0",
-        "'interval' is less than minimal sampling interval",
+        "'interval' is out of the supported range",
         "'value' is out of an allowed range",
         "Cannot start conversion",
 
         // gpio messages
-        "Trigger or mode",
-        "mode is not for DIR_INPUT_ONLY",
-        "mode is not for DIR_OUTPUT_ONLY",
-        "mode is not for DIR_BOTH: %d",
+        "Invalid trigger",
         "Invalid direction",
+        "Invalid mode",
         "Illegal direction or initValue",
         "Pin config does not support required direction",
         "Try to Set value to input pin",
@@ -250,10 +239,11 @@
         "Incompatible direction",
         "Trying to write to input port",
         "Try to register Listener to output port",
+        "Incompatible mode",
+
 
         // i2c bus messages
         "the message has already been transferred once",
-        "buffer is null",
         "'skip' argument is negative",
         "operation to a slave on a different bus",
         "the same buffer is given twice",
@@ -284,24 +274,17 @@
         "Period %d is negative or zero ",
         "Period %d is out of the supported range",
         "width or count is illegal",
-        "src buffer is null ",
-        "listener is null",
-        "No data in the buffer",
-        "src1 or src2 buffer is null",
         "pulse generation session is already active",
 
         // spi bus messages
-        "Buffer is null",
         "Slave Word Length is %d",
         "the number of bytes to receive/send belies word length",
+        "The original read buffer was modified after append",
+        "Delay operation in composite message was interrupted",
 
         // uart messages
         "Cannot get serial port name",
         "Unable to convert dev name to UTF-8",
-        "src buffer or listener is null",
-        "src1, src2 buffer or listener is null",
-        "dst buffer is null",
-        "src buffer is null",
         "another synchronous or asynchronous read operation is already active",
         "another synchronous or asynchronous write operation is already active",
         "signalID is not one of the defined values",
--- a/src/se/classes/com/oracle/dio/utils/Logging.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/classes/com/oracle/dio/utils/Logging.java	Fri Sep 09 13:20:20 2016 +0300
@@ -24,6 +24,8 @@
  */
 
 package com.oracle.dio.utils;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 public final class Logging {
 
@@ -32,26 +34,30 @@
     }
 
     public static void reportError(String message) {
-        //  add an implementation
+        log(Level.SEVERE, message);
     }
 
     public static void reportError(String message1, String message2) {
-        //  add an implementation
+        reportError(message1 + message2);
     }
 
     public static void reportWarning(String message) {
-        //  add an implementation
+        log(Level.WARNING, message);
     }
 
     public static void reportWarning(String message1, String message2) {
-        //  add an implementation
+        reportWarning(message1 + message2);
     }
 
     public static void reportInformation(String message) {
-        //  add an implementation
+        log(Level.INFO, message);
     }
 
     public static void reportInformation(String message1, String message2) {
-        //  add an implementation
+        reportInformation(message1 + message2);
+    }
+
+    private static void log(Level level, String message) {
+        Logger.getLogger("DIO").log(level, message);
     }
 }
--- a/src/se/classes/jdk/dio/mmio/AccessOutOfBoundsException.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.dio.mmio;
-
-/**
- * Thrown by an instance of {@link MMIODevice} if an offset used is out of valid boundary of the specified memory block.
- *
- * @since 1.0
- */
-@SuppressWarnings("serial")
-@apimarker.API("device-io_1.0")
-public class AccessOutOfBoundsException extends RuntimeException {
-
-    /**
-     * Constructs a new {@code AccessOutOfBoundsException} with {@code null} as its detailed reason message.
-     */
-    public AccessOutOfBoundsException() {
-        super();
-    }
-
-    /**
-     * Constructs a new {@code AccessOutOfBoundsException} with the specified detail message. The error message string
-     * {@code message} can later be retrieved by the {@link Throwable#getMessage getMessage} method.
-     *
-     * @param message
-     *            the detailed reason of the exception
-     */
-    public AccessOutOfBoundsException(String message) {
-        super(message);
-    }
-}
--- a/src/se/classes/jdk/dio/mmio/MMIODevice.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,281 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.dio.mmio;
-
-import jdk.dio.ClosedDeviceException;
-import jdk.dio.Device;
-import jdk.dio.DeviceManager;
-import jdk.dio.UnavailableDeviceException;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import romizer.WeakDontRenameClass;
-
-/**
- * The {@code MMIODevice} class provides methods to retrieve memory-mapped registers and memory blocks of a device
- * device.
- * <p />
- * An MMIO device may be identified by the numeric ID and by the name (if any defined) that correspond to its
- * registered configuration. An {@code MMIODevice} instance can be opened by a call to one of the
- * {@link DeviceManager#open(int) DeviceManager.open(id,...)} methods using its ID or by a call to one of the
- * {@link DeviceManager#open(java.lang.String, java.lang.Class, java.lang.String[])
- * DeviceManager.open(name,...)} methods using its name. When an {@code MMIODevice} instance is opened with an
- * ad-hoc {@link MMIODeviceConfig} configuration (which includes its hardware addressing information) using one of the
- * {@link DeviceManager#open(jdk.dio.DeviceConfig) DeviceManager.open(config,...)} it is not
- * assigned any ID nor name.
- * <p />
- * With memory-mapped I/O, devices can be controlled by directly reading or writing to memory areas
- * representing the registers or memory blocks of the device. Each register or memory block is represented by
- * a {@link RawMemory} instance. Each register or memory block is also usually assigned a name which can be used for
- * name-based lookup. The complete memory area the device is mapped to can also be retrieved as single
- * {@link RawBlock} instance, allowing for offset-based access to all the registers and memory blocks of the device.
- * <p/>
- * An application can register an {@link MMIOEventListener} instance to monitor native events of the designated type
- * fired by the device. To register a {@link MMIOEventListener} instance, the application must call the
- * {@link #setMMIOEventListener(int, MMIOEventListener)} method. The registered listener can later on be removed by
- * calling the same method with a {@code null} listener parameter. Asynchronous notification may not be supported by all
- * memory-mapped devices. An attempt to set a listener on a memory-mapped device which does not supports it will result
- * in an {@link UnsupportedOperationException} being thrown.
- * <p />
- * When done, an application should call the {@link #close MMIODevice.close} method to close the MMIO device. Any
- * further attempt to access an MMIO device which has been closed will result in a {@link ClosedDeviceException}
- * been thrown.
- * <p />
- * Opening a {@link MMIODevice} instance is subject to permission checks (see {@link MMIOPermission}).
- * <p />
- * The event types (IDs) supported by a memory-mapped device are device as well as platform specific. For
- * example, each interrupt request line of a device may be mapped to a distinct event type ID. Refer to the
- * device data sheet and the platform configuration.
- * <p />
- * The {@code byte}, {@code short} and {@code int} values passed to and returned by this API have to be
- * interpreted as 8 bit, 16 bit and 32 bit unsigned quantities. Proper handling is needed when performing integer
- * arithmetic on these quantities.
- *
- * @see MMIOPermission
- * @see ClosedDeviceException
- * @since 1.0
- */
-@apimarker.API("device-io_1.0")
-@WeakDontRenameClass
-public interface MMIODevice extends Device<MMIODevice> {
-
-    /**
-     * Gets the complete memory area this device is mapped to as a {@code RawBlock} instance.
-     *
-     * @return a {@link RawBlock} object encapsulating whole memory area this device is mapped to.
-     * @throws IOException
-     *             if some other I/O error occurs.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    RawBlock getAsRawBlock() throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Gets the designated memory block.
-     *
-     * @param name
-     *            name of the memory block.
-     * @return a {@link RawBlock} object encapsulating the designated memory block.
-     * @throws IOException
-     *             if some other I/O error occurs.
-     * @throws IllegalArgumentException
-     *             if the provided name does not correspond to any memory block.
-     * @throws NullPointerException
-     *             if {@code name} is {@code null}.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    RawBlock getBlock(String name) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Returns the byte ordering of this memory-mapped device.
-     *
-     * @return {@link #BIG_ENDIAN} if big-endian; {@link #LITTLE_ENDIAN} if little-endian; {@link #MIXED_ENDIAN}
-     *         otherwise.
-     * @throws IOException
-     *             if some other I/O error occurs.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    int getByteOrdering() throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Gets the designated register holding a value of the designated type.
-     *
-     * @param name
-     *            the name of the register.
-     * @param type
-     *            the type of the value held in the register.
-     * @return a {@link RawRegister} object encapsulating the value of the designated register.
-     * @throws IllegalArgumentException
-     *             if the provided name does not correspond to any register or if the type of of the value held in the
-     *             register does not match.
-     * @throws NullPointerException
-     *             if {@code name} or {@code type} is {@code null}.
-     * @throws IOException
-     *             if some other I/O error occurs.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    <T extends Number> RawRegister<T> getRegister(String name, Class<T> type) throws IOException,
-            UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Registers a {@link MMIOEventListener} instance to monitor native events of the designated type fired by the
-     * device mapped to this </code>MMIODevice</code> object and capture the content of designated memory
-     * area.
-     * <p />
-     * While the listener can be triggered by hardware interrupts, there are no real-time guarantees of when the
-     * listener will be called.
-     * <p />
-     * The content of the designated memory area will be captured upon the occurrence of the designated event.
-     * Upon notification of the corresponding {@link MMIOEvent}, the captured content of a designated memory area
-     * may be retrieved using {@link MMIOEvent#getCapturedMemoryContent MMIOEvent.getCapturedMemoryContent}.
-      * <p />
-     * If this {@code MMIODevice} is open in {@link DeviceManager#SHARED} access mode
-     * the listeners registered by all the applications sharing the underlying device will get
-     * notified of the events they registered for.
-     * <p />
-     * If {@code listener} is {@code null} then listener previously registered for the specified event type will be
-     * removed.
-     * <p />
-     * Only one listener can be registered at a particular time for a particular event type.
-     *
-     * @param eventId
-     *            ID of the native event to listen to.
-     * @param capturedIndex
-     *            the byte index in this device mapped raw memory area to capture.
-     * @param captureBuffer
-     *            the direct {@link ByteBuffer} to save the captured memory area in; up to {@code captureBuffer.remaining()} bytes will
-     *            be copied from this device mapped raw memory area starting at {@code capturedIndex}
-     *            into this buffer starting at the buffer's position at the moment this method is called.
-     * @param listener
-     *            the {@link MMIOEventListener} instance to be notified upon occurrence of the designated event.
-     * @throws IOException
-     *             if some other I/O error occurs.
-     * @throws AccessOutOfBoundsException
-     *             if {@code capturedIndex} and/or {@code captureBuffer.remaining()} would result in pointing outside this device
-     *             mapped raw memory area.
-     * @throws IllegalArgumentException
-     *             if {@code eventId} does not correspond to any supported event or if {@code captureBuffer} is not a direct {@link ByteBuffer}.
-     * @throws UnsupportedOperationException
-     *             if this {@code MMIODevice} object does not support asynchronous event notification.
-     * @throws IllegalStateException
-     *             if {@code listener} is not {@code null} and a listener is already registered for the specified event
-     *             type.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     * @throws NullPointerException
-     *             if {@code captureBuffer} is {@code null}.
-     */
-    void setMMIOEventListener(int eventId, int capturedIndex, ByteBuffer captureBuffer,
-            MMIOEventListener listener) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Registers a {@link MMIOEventListener} instance to monitor native events of the designated type fired by the
-     * device mapped to this </code>MMIODevice</code> object. While the listener can be triggered by hardware
-     * interrupts, there are no real-time guarantees of when the listener will be called.
-     * <p />
-     * If this {@code MMIODevice} is open in {@link DeviceManager#SHARED} access mode
-     * the listeners registered by all the applications sharing the underlying device will get
-     * notified of the events they registered for.
-     * <p />
-     * If {@code listener} is {@code null} then listener previously registered for the specified event type will be
-     * removed.
-     * <p />
-     * Only one listener can be registered at a particular time for a particular event type.
-     *
-     * @param eventId
-     *            ID of the native event to listen to.
-     * @param listener
-     *            the {@link MMIOEventListener} instance to be notified upon occurrence of the designated event.
-     * @throws IOException
-     *             if some other I/O error occurs.
-     * @throws IllegalArgumentException
-     *             if {@code eventId} does not correspond to any supported event.
-     * @throws UnsupportedOperationException
-     *             if this {@code MMIODevice} object does not support asynchronous event notification.
-     * @throws IllegalStateException
-     *             if {@code listener} is not {@code null} and a listener is already registered for the specified event
-     *             type.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    void setMMIOEventListener(int eventId, MMIOEventListener listener) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Registers a {@link MMIOEventListener} instance to monitor native events of the designated type fired by the
-     * device mapped to this </code>MMIODevice</code> object and capture the content of designated register
-     * or block.
-     * <p />
-     * While the listener can be triggered by hardware interrupts, there are no real-time guarantees of when the
-     * listener will be called.
-     * <p />
-     * The content of the designated register or block will be captured upon the occurrence of the designated event.
-     * Upon notification of the corresponding {@link MMIOEvent}, the captured value of a designated register may
-     * be retrieved using {@link MMIOEvent#getCapturedRegisterValue MMIOEvent.getCapturedRegisterValue} while the captured content of a designated block
-     * may be retrieved using {@link MMIOEvent#getCapturedMemoryContent MMIOEvent.getCapturedMemoryContent}.
-     * <p />
-     * If this {@code MMIODevice} is open in {@link DeviceManager#SHARED} access mode
-     * the listeners registered by all the applications sharing the underlying device will get
-     * notified of the events they registered for.
-     * <p />
-     * If {@code listener} is {@code null} then listener previously registered for the specified event type will be
-     * removed.
-     * <p />
-     * Only one listener can be registered at a particular time for a particular event type.
-     *
-     * @param eventId
-     *            ID of the native event to listen to.
-     * @param capturedName
-     *            the name of the register or memory block whose content is to be captured at the time of the underlying
-     *            event occurs.
-     * @param listener
-     *            the {@link MMIOEventListener} instance to be notified upon occurrence of the designated event.
-     * @throws IOException
-     *             if some other I/O error occurs.
-     * @throws IllegalArgumentException
-     *             if {@code eventId} does not correspond to any supported event; or if the provided name does not
-     *             correspond to any memory block or register.
-     * @throws UnsupportedOperationException
-     *             if this {@code MMIODevice} object does not support asynchronous event notification.
-     * @throws IllegalStateException
-     *             if {@code listener} is not {@code null} and a listener is already registered for the specified event
-     *             type.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     * @throws NullPointerException
-     *             if {@code capturedName} is {@code null}.
-     */
-    void setMMIOEventListener(int eventId, String capturedName, MMIOEventListener listener) throws IOException,
-            UnavailableDeviceException, ClosedDeviceException;
-}
--- a/src/se/classes/jdk/dio/mmio/MMIODeviceConfig.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,520 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.dio.mmio;
-
-import jdk.dio.DeviceConfig;
-import jdk.dio.InvalidDeviceConfigException;
-import jdk.dio.DeviceManager;
-import java.util.Arrays;
-import java.util.Objects;
-
-import serializator.*;
-import romizer.*;
-
-/**
- * The {@code MMIODeviceConfig} class encapsulates the hardware addressing information, and static and dynamic
- * configuration parameters of an MMIO device.
- * <p />
- * Some hardware addressing parameter, and static and dynamic configuration parameters may be set to {@link #DEFAULT}.
- * Whether such default settings are supported is platform- as well as device driver-dependent.
- * <p />
- * An instance of {@code MMIODeviceConfig} can be passed to the {@link DeviceManager#open(DeviceConfig)} or
- * {@link DeviceManager#open(Class, DeviceConfig)} method to open the designated MMIO device with the specified
- * configuration. A {@link InvalidDeviceConfigException} is thrown when attempting to open a device with
- * an invalid or unsupported configuration.
- *
- * @see DeviceManager#open(DeviceConfig)
- * @see DeviceManager#open(Class, DeviceConfig)
- * @since 1.0
- */
-@SerializeMe
-@DontRenameClass
-@apimarker.API("device-io_1.0")
-public final class MMIODeviceConfig implements DeviceConfig<MMIODevice>, DeviceConfig.HardwareAddressing {
-
-    /**
-     * The {@code RawBlockConfig} class encapsulates the configuration parameters of a memory block.
-     */
-    public static final class RawBlockConfig extends RawMemoryConfig {
-
-        private int size;
-
-        /**
-         * Constructs a new {@code RawBlockConfig} with the provided parameters.
-         *
-         * @param offset
-         *            the offset of the register from the base address (a positive or zero integer).
-         * @param name
-         *            the name for the register.
-         * @param size
-         *            the size in bytes of the memory block (a positive integer).
-         *
-         * @throws IllegalArgumentException
-         *             if any of the following is true:
-         *             <ul>
-         *             <li>{@code offset} is lesser than {@code 0};</li>
-         *             <li>{@code size} is lesser than or equal to {@code 0}.</li>
-         *             </ul>
-         * @throws NullPointerException
-         *             if {@code name} is {@code null}.
-         */
-        public RawBlockConfig(int offset, String name, int size) {
-            super(offset, name);
-            this.size = size;
-        }
-
-        /**
-         * Gets the configured size in bytes of the memory block.
-         *
-         * @return the size in bytes of the memory block (a positive integer).
-         */
-        public int getSize() {
-            return size;
-        }
-
-    /**
-     * Returns the hash code value for this object.
-     *
-     * @return a hash code value for this object.
-     */
-        @Override
-        public int hashCode() {
-            int hash = 3;
-            hash = 37 * hash + this.size;
-            return hash;
-        }
-
-    /**
-     * Checks two {@code RawBlockConfig} objects for equality.
-     *
-     * @param obj
-     *            the object to test for equality with this object.
-     *
-     * @return {@code true} if {@code obj} is a {@code RawBlockConfig} and has
-     * the same hardware addressing information and configuration parameter values
-     * as this {@code RawBlockConfig} object.
-     */
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            final RawBlockConfig other = (RawBlockConfig) obj;
-            if (this.size != other.size) {
-                return false;
-            }
-            return true;
-        }
-
-    }
-
-    /**
-     * The {@code RawMemoryConfig} class encapsulates the configuration parameters of a generic raw memory area.
-     */
-    @SerializeMe
-    @DontRenameClass
-    @apimarker.API("device-io_1.0")
-    public static abstract class RawMemoryConfig {
-
-        private String name;
-        private int offset;
-
-        /**
-         * Constructs a new {@code RawMemoryConfig} with the provided parameters.
-         *
-         * @param offset
-         *            the offset of the raw memory area from the base address (a positive or zero integer).
-         * @param name
-         *            the name for the raw memory area.
-         *
-         * @throws IllegalArgumentException
-         *             if {@code offset} is lesser than {@code 0}.
-         * @throws NullPointerException
-         *             if {@code name} is {@code null}.
-         */
-        RawMemoryConfig(int offset, String name) {
-            this.offset = offset;
-            this.name = name;
-        }
-
-        /**
-         * Gets the configured name for the raw memory area.
-         *
-         * @return the name for the raw memory area.
-         */
-        public String getName() {
-            return name;
-        }
-
-        /**
-         * Gets the configured offset of the raw memory area from the base address.
-         *
-         * @return the offset of the raw memory area from the base address (a positive or zero integer).
-         */
-        public int getOffset() {
-            return offset;
-        }
-
-    /**
-     * Returns the hash code value for this object.
-     *
-     * @return a hash code value for this object.
-     */
-        @Override
-        public int hashCode() {
-            int hash = 7;
-            hash = 97 * hash + Objects.hashCode(this.name);
-            hash = 97 * hash + this.offset;
-            return hash;
-        }
-
-    /**
-     * Checks two {@code RawMemoryConfig} objects for equality.
-     *
-     * @param obj
-     *            the object to test for equality with this object.
-     *
-     * @return {@code true} if {@code obj} is a {@code RawMemoryConfig} and has
-     * the same hardware addressing information and configuration parameter values
-     * as this {@code RawMemoryConfig} object.
-     */
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            final RawMemoryConfig other = (RawMemoryConfig) obj;
-            if (!Objects.equals(this.name, other.name)) {
-                return false;
-            }
-            if (this.offset != other.offset) {
-                return false;
-            }
-            return true;
-        }
-
-    }
-
-    /**
-     * The {@code RawRegisterConfig} class encapsulates the configuration parameters of a register.
-     *
-     * @param <T>
-     *            the type of the value held by the register.
-     */
-    public static final class RawRegisterConfig<T extends Number> extends RawMemoryConfig {
-        private Class<T> type;
-
-        /**
-         * Constructs a new {@code RawRegisterConfig} with the provided parameters.
-         *
-         * @param offset
-         *            the offset of the register from the base address (a positive or zero integer).
-         * @param name
-         *            the name for the register.
-         * @param type
-         *            the type of the value held by the register, one of: {@link Byte}, {@link Short} or {@link Integer}
-         *            .
-         *
-         * @throws IllegalArgumentException
-         *             if any of the following is true:
-         *             <ul>
-         *             <li>{@code offset} is lesser than {@code 0};</li>
-         *             <li>{@code type} is not one of the defined values.</li>
-         *             </ul>
-         * @throws NullPointerException
-         *             if {@code name} is {@code null}.
-         */
-        public RawRegisterConfig(int offset, String name, Class<T> type) {
-            super(offset, name);
-            this.type = type;
-        }
-
-        /**
-         * Gets the configured type of the value held by the register.
-         *
-         * @return the type of the value held by the register, one of: {@link Byte}, {@link Short} or {@link Integer}.
-         */
-        public Class<T> getType() {
-            return type;
-        }
-
-    /**
-     * Returns the hash code value for this object.
-     *
-     * @return a hash code value for this object.
-     */
-        @Override
-        public int hashCode() {
-            int hash = 5;
-            hash = 67 * hash + Objects.hashCode(this.type);
-            return hash;
-        }
-
-    /**
-     * Checks two {@code RawRegisterConfig} objects for equality.
-     *
-     * @param obj
-     *            the object to test for equality with this object.
-     *
-     * @return {@code true} if {@code obj} is a {@code RawRegisterConfig} and has
-     * the same hardware addressing information and configuration parameter values
-     * as this {@code RawRegisterConfig} object.
-     */
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            final RawRegisterConfig<T> other = (RawRegisterConfig<T>) obj;
-            if (!Objects.equals(this.type, other.type)) {
-                return false;
-            }
-            return true;
-        }
-    }
-
-    private long address;
-    private int controllerNumber = DEFAULT;
-    private String controllerName = null;
-
-    private int byteOrdering = DEFAULT;
-
-    private RawMemoryConfig[] memConfigs = null;
-
-    private int size;
-
-    /**
-     * Creates a new {@code MMIODeviceConfig} with the specified hardware addressing information and configuration
-     * parameters.
-     * <p />
-     * If no raw block and raw register configuration is provided, the specified memory area will be mapped to
-     * the {@link RawBlock} instance returned by a call to {@link MMIODevice#getAsRawBlock MMIODevice.getAsRawBlock}.
-     * <p />
-     * If the designated memory region is protected or if it overlaps with that of an existing
-     * MMIO device configuration and the requested access mode ({@link DeviceManager#EXCLUSIVE} or
-     * {@link DeviceManager#SHARED}) is incompatible or unsupported, attempting to open an {@code MMIODevice}
-     * device using this configuration may result in either a {@code SecurityException} or
-     * a {@link InvalidDeviceConfigException} to be thrown.
-     *
-    * @param address
-     *            the memory address of the device (a positive or zero integer).
-     * @param size
-     *            the size of the memory-mapped area of the device (a positive integer).
-     * @param byteOrdering
-     *            the byte ordering of the device, one of: {@link MMIODevice#BIG_ENDIAN},
-     *            {@link MMIODevice#LITTLE_ENDIAN}, {@link MMIODevice#MIXED_ENDIAN} or {@link MMIODeviceConfig#DEFAULT}.
-     * @param memConfigs
-     *            the raw block and raw register configurations (may be {@code null} or empty).
-     *
-     * @throws IllegalArgumentException
-     *             if any of the following is true:
-     *             <ul>
-     *             <li>{@code address} is not in the defined range;</li>
-     *             <li>{@code size} is not in the defined range;</li>
-     *             <li>{@code byteOrdering} is not one of the defined values.</li>
-     *             </ul>
-     * @throws IndexOutOfBoundsException
-     *             if any of the {@code memConfigs} elements is pointing outside of the defined address range ([
-     *             {@code 0}-</code>size</code>]).
-     */
-    public MMIODeviceConfig(long address, int size, int byteOrdering, RawMemoryConfig... memConfigs) {
-        this.address = address;
-        this.size = size;
-        this.byteOrdering = byteOrdering;
-        if (memConfigs != null) {
-            this.memConfigs = memConfigs.clone();
-        }
-    }
-
-    /**
-     * Creates a new {@code MMIODeviceConfig} with the specified hardware addressing information and configuration
-     * parameters.
-     * <p />
-     * If no raw block and raw register configuration is provided, the specified memory area will be mapped to
-     * the {@link RawBlock} instance returned by a call to {@link MMIODevice#getAsRawBlock MMIODevice.getAsRawBlock}.
-     *
-     * @param controllerName
-     *            the controller name (such as its <em>device file</em> name on UNIX systems).
-     * @param address
-     *            the memory address of the device (a positive or zero integer)or {@link MMIODeviceConfig#DEFAULT}.
-     * @param size
-     *            the size of the memory-mapped area of the device (a positive integer).
-     * @param byteOrdering
-     *            the byte ordering of the device, one of: {@link MMIODevice#BIG_ENDIAN},
-     *            {@link MMIODevice#LITTLE_ENDIAN}, {@link MMIODevice#MIXED_ENDIAN} or {@link MMIODeviceConfig#DEFAULT}.
-     * @param memConfigs
-     *            the raw block and raw register configurations (may be {@code null} or empty).
-     *
-     * @throws IllegalArgumentException
-     *             if any of the following is true:
-     *             <ul>
-     *             <li>{@code address} is not in the defined range;</li>
-     *             <li>{@code size} is not in the defined range;</li>
-     *             <li>{@code byteOrdering} is not one of the defined values.</li>
-     *             </ul>
-     * @throws NullPointerException
-     *             if {@code controllerName} is {@code null}.
-     * @throws IndexOutOfBoundsException
-     *             if any of the {@code memConfigs} elements is pointing outside of the defined address range ([
-     *             {@code 0}-</code>size</code>]).
-     */
-    public MMIODeviceConfig(String controllerName, long address, int size, int byteOrdering, RawMemoryConfig... memConfigs) {
-        this.controllerName = controllerName;
-        this.address = address;
-        this.size = size;
-        this.byteOrdering = byteOrdering;
-        if (memConfigs != null) {
-            this.memConfigs = memConfigs.clone();
-        }
-    }
-
-    /**
-     * Gets the configured memory address of the MMIO device.
-     *
-     * @return the memory address of the MMIO device (a positive or zero integer) or {@link MMIODeviceConfig#DEFAULT}..
-     */
-    public long getAddress() {
-        return address;
-    }
-
-    /**
-     * Gets the configured controller name (such as its <em>device file</em> name on UNIX systems).
-     *
-     * @return the controller name or {@code null}.
-     */
-    @Override
-    public String getControllerName() {
-        return controllerName;
-    }
-
-    /**
-     * Gets the configured controller number.
-     *
-     * @return {@link #DEFAULT}.
-     */
-    @Override
-    public int getControllerNumber() {
-        return controllerNumber;
-    }
-
-    /**
-     * Gets the configured byte ordering of the MMIO device.
-     *
-     * @return the byte ordering of the MMIO device, one of: {@link MMIODevice#BIG_ENDIAN},
-     *         {@link MMIODevice#LITTLE_ENDIAN}, {@link MMIODevice#MIXED_ENDIAN} or {@link MMIODeviceConfig#DEFAULT}.
-     */
-    public int getByteOrdering() {
-        return byteOrdering;
-    }
-
-    /**
-     * Gets the set of configured registers and memory blocks.
-     *
-     * @return an array (a defensive copy thereof) containing the set of configured registers and memory blocks or
-     *         {@code null} if none is defined.
-     */
-    public RawMemoryConfig[] getRawMemoryConfigs() {
-        if (memConfigs != null) {
-            return memConfigs.clone();
-        }
-        return null;
-    }
-
-    /**
-     * Gets the configured size of the memory-mapped area of the MMIO device.
-     *
-     * @return the size of the memory-mapped area of the device (a positive integer).
-     */
-    public int getSize() {
-        return size;
-    }
-
-    /**
-     * Returns the hash code value for this object.
-     *
-     * @return a hash code value for this object.
-     */
-    @Override
-    public int hashCode() {
-        int hash = 5;
-        hash = 97 * hash + (int) (this.address ^ (this.address >>> 32));
-        hash = 97 * hash + this.controllerNumber;
-        hash = 97 * hash + Objects.hashCode(this.controllerName);
-        hash = 97 * hash + this.byteOrdering;
-        for (RawMemoryConfig memConfig : this.memConfigs) {
-            hash = 97 * hash + Objects.hashCode(memConfig);       }
-        hash = 97 * hash + this.size;
-        return hash;
-    }
-
-    /**
-     * Checks two {@code MMIODeviceConfig} objects for equality.
-     *
-     * @param obj
-     *            the object to test for equality with this object.
-     *
-     * @return {@code true} if {@code obj} is a {@code MMIODeviceConfig} and has
-     * the same hardware addressing information and configuration parameter values
-     * as this {@code MMIODeviceConfig} object.
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final MMIODeviceConfig other = (MMIODeviceConfig) obj;
-        if (this.address != other.address) {
-            return false;
-        }
-        if (this.controllerNumber != other.controllerNumber) {
-            return false;
-        }
-        if (!Objects.equals(this.controllerName, other.controllerName)) {
-            return false;
-        }
-        if (this.byteOrdering != other.byteOrdering) {
-            return false;
-        }
-        if (!Arrays.equals(this.memConfigs, other.memConfigs)) {
-            return false;
-        }
-        if (this.size != other.size) {
-            return false;
-        }
-        return true;
-    }
-}
--- a/src/se/classes/jdk/dio/mmio/MMIOEvent.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.dio.mmio;
-
-import jdk.dio.DeviceEvent;
-import java.nio.ByteBuffer;
-
-/**
- * The {@code MMIOEvent} class encapsulates events fired by devices mapped to memory.
- *
- * @see MMIODevice
- * @see MMIOEventListener
- * @since 1.0
- */
-@apimarker.API("device-io_1.0")
-public class MMIOEvent extends DeviceEvent<MMIODevice> {
-
-    /**
-     * The captured content of the memory area or memory block designated upon registration.
-     */
-    private ByteBuffer capturedMemoryContent = null;
-
-    /**
-     * The captured value of the register designated upon registration.
-     */
-    private Number capturedRegisterValue = null;
-
-    /**
-     * This event ID.
-     */
-    private int id;
-
-    /**
-     * Creates a new {@link MMIOEvent} with the specified event ID and time-stamped
-     * with the current time.
-     *
-     * @param device
-     *            the source device.
-     * @param id
-     *            the event ID.
-     * @throws NullPointerException
-     *             if {@code device} is {@code null}.
-     * @throws IllegalArgumentException
-     *             if {@code id} is negative.
-     */
-    public MMIOEvent(MMIODevice device, int id) {
-        this(device, id, System.currentTimeMillis(), 0);
-    }
-
-    /**
-     * Creates a new {@link MMIOEvent} with the specified event ID and timestamp, and
-     * with the captured content of the memory area or memory block designated upon registration.
-     *
-     * @param device
-     *            the source device.
-     * @param id
-     *            the event ID.
-     * @param capturedMemoryContent
-     *            the captured content of the memory area or memory block designated upon registration.
-     * @param timeStamp
-     *            the timestamp (in milliseconds).
-     * @param timeStampMicros
-     *            the additional microseconds to the timestamp.
-     * @throws NullPointerException
-     *             if {@code device} or {@code capturedMemoryContent} is {@code null}.
-     * @throws IllegalArgumentException
-     *             if {@code id}, {@code timeStamp} or {@code timeStampMicros} is negative.
-     */
-    public MMIOEvent(MMIODevice device, int id, ByteBuffer capturedMemoryContent, long timeStamp, int timeStampMicros) {
-        this.device = device;
-        this.id = id;
-        this.capturedRegisterValue = null;
-        this.capturedMemoryContent = capturedMemoryContent;
-        this.timeStamp = timeStamp;
-        this.timeStampMicros = timeStampMicros;
-        this.count = 1;
-    }
-
-    /**
-     * Creates a new {@link MMIOEvent} with the specified event ID and timestamp.
-     *
-     * @param device
-     *            the source device.
-     * @param id
-     *            the event ID.
-     * @param timeStamp
-     *            the timestamp (in milliseconds).
-     * @param timeStampMicros
-     *            the additional microseconds to the timestamp.
-     * @throws NullPointerException
-     *             if {@code device} is {@code null}.
-     * @throws IllegalArgumentException
-     *             if {@code id}, {@code timeStamp} or {@code timeStampMicros} is negative.
-     */
-    public MMIOEvent(MMIODevice device, int id, long timeStamp, int timeStampMicros) {
-        this.device = device;
-        this.id = id;
-        this.capturedRegisterValue = null;
-        this.capturedMemoryContent = null;
-        this.timeStamp = timeStamp;
-        this.timeStampMicros = timeStampMicros;
-        this.count = 1;
-    }
-
-    /**
-     * Creates a new {@link MMIOEvent} with the specified event ID and timestamp, and
-     * the captured value of the register designated upon registration.
-     *
-     * @param <T> the type of the captured value.
-     *
-     * @param device
-     *            the source device.
-     * @param id
-     *            the event ID.
-     * @param capturedRegisterValue
-     *            the captured value of the register designated upon registration.
-     * @param timeStamp
-     *            the timestamp (in milliseconds).
-     * @param timeStampMicros
-     *            the additional microseconds to the timestamp.
-     * @throws NullPointerException
-     *             if {@code device} or {@code capturedRegisterValue} is {@code null}.
-     * @throws IllegalArgumentException
-     *             if {@code id}, {@code timeStamp} or {@code timeStampMicros} is negative.
-     */
-    public <T extends Number> MMIOEvent(MMIODevice device, int id, T capturedRegisterValue, long timeStamp,
-            int timeStampMicros) {
-        this.device = device;
-        this.id = id;
-        this.capturedRegisterValue = capturedRegisterValue;
-        this.capturedMemoryContent = null;
-        this.timeStamp = timeStamp;
-        this.timeStampMicros = timeStampMicros;
-        this.count = 1;
-    }
-
-    /**
-     * Gets the captured content of the memory area or memory block designated upon registration.
-     *
-     * @return the captured content of the memory area or block; or {@code null} if no memory area or block content was
-     *         captured. If the listener was registered using the MMIODevice#setMMIOEventListener(int, int, ByteBuffer, jdk.dio.mmio.MMIOEventListener) method
-     *         the {@code ByteBuffer} returned is the {@code ByteBuffer} that was passed as the {@code captureBuffer} parameter.
-     *
-     * @see MMIODevice#setMMIOEventListener(int, java.lang.String, jdk.dio.mmio.MMIOEventListener)
-     * @see MMIODevice#setMMIOEventListener(int, int, ByteBuffer, jdk.dio.mmio.MMIOEventListener)
-     */
-    public ByteBuffer getCapturedMemoryContent() {
-        return capturedMemoryContent;
-    }
-
-    /**
-     * Gets the captured value of the register designated upon registration.
-     *
-     * @param <T>
-     *            the type of the value held by the register.
-     * @return the captured value of the register designated upon registration or {@code null} if no register value was captured.
-     *
-     * @see MMIODevice#setMMIOEventListener(int, java.lang.String, jdk.dio.mmio.MMIOEventListener)
-     */
-    @SuppressWarnings("unchecked")
-    public <T extends Number> T getCapturedRegisterValue() {
-        return (T) capturedRegisterValue;
-    }
-
-    /**
-     * Returns this event ID.
-     *
-     * @return this event ID.
-     */
-    public int getID() {
-        return id;
-    }
-}
\ No newline at end of file
--- a/src/se/classes/jdk/dio/mmio/MMIOEventListener.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.dio.mmio;
-
-import jdk.dio.DeviceEventListener;
-
-/**
- * The {@code MMIOEventListener} interface defines methods for getting notified of events fired by devices mapped to
- * memory. <br />
- * A {@code MMIOEventListener} can be registered using one of the
- * {@link MMIODevice#setMMIOEventListener(int, MMIOEventListener) setMMIOEventListener} methods.
- *
- * @see MMIODevice#setMMIOEventListener MMIODevice.setMMIOEventListener
- * @see MMIOEvent
- * @since 1.0
- */
-@apimarker.API("device-io_1.0")
-public interface MMIOEventListener extends DeviceEventListener {
-
-    /**
-     * Invoked when an event is fired by a memory-mapped device.
-     *
-     * @param event
-     *            the event that occurred.
-     */
-    void eventDispatched(MMIOEvent event);
-}
\ No newline at end of file
--- a/src/se/classes/jdk/dio/mmio/MMIOPermission.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.dio.mmio;
-
-import com.oracle.dio.utils.ActionFactory;
-
-import jdk.dio.DevicePermission;
-
-/**
- * The {@code MMIOPermission} class defines permissions for MMIO device access.
- * <p />
- * A {@code MMIOPermission} permission has a target name and a list of actions.
- * <p />
- * The target name contains hardware addressing information. The format is the one defined for the base {@link DevicePermission} class
- * with the following addition:
- * <dl>
- * <dt><code>{channel-desc}</code></dt>
- * <dd>
- * The <code>{channel-desc}</code> string (described in {@link DevicePermission}) is
- * a memory-address (in hexadecimal format) as may be returned by a call to {@link MMIODeviceConfig#getAddress MMIODeviceConfig.getAddress}.
- * The characters in the string must all be hexadecimal digits.
- * </dd>
- * </dl>
- * The supported actions are {@code open} and {@code powermanage}. Their meaning is defined as follows:
- * <dl>
- * <dt>{@code open}</dt>
- * <dd>open and access an MMIO device functions (see {@link DeviceManager#open DeviceManager.open})</dd>
- * <dt>{@code powermanage}</dt>
- * <dd>manage the power saving mode of a device (see {@link jdk.dio.power.PowerManaged})</dd>
- * </dl>
- *
- * @see DeviceManager#open DeviceManager.open
- * @see jdk.dio.power.PowerManaged
- */
-@SuppressWarnings("serial")
-@apimarker.API("device-io_1.0")
-public class MMIOPermission extends DevicePermission  {
-
-    /**
-     * Constructs a new {@code MMIOPermission} with the specified target name and the implicit {@code open} action.
-     *
-     * @param name
-     *            the target name (as defined above).
-     * @throws NullPointerException
-     *             if {@code name} is {@code null}.
-     *
-     * @see #getName getName
-     */
-    public MMIOPermission(String name) {
-        super(name);
-    }
-
-    /**
-     * Constructs a new {@code MMIOPermission} instance with the specified target name and action list.
-     *
-     * @param name
-     *            the target name (as defined above).
-     * @param actions
-     *            comma-separated list of device operations: {@code open} or {@code powermanage}.
-     * @throws NullPointerException
-     *             if {@code name} is {@code null}.
-     * @throws IllegalArgumentException
-     *             if actions is {@code null}, empty or contains an action other than the
-     *             specified possible actions.
-     *
-     * @see #getName getName
-     */
-    public MMIOPermission(String name, String actions) {
-        super(name, ActionFactory.verifyAndOrderDeviceActions(actions));
-    }
-}
--- a/src/se/classes/jdk/dio/mmio/RawBlock.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.dio.mmio;
-
-import jdk.dio.ClosedDeviceException;
-import jdk.dio.UnavailableDeviceException;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * The {@code RawBlock} interface provides methods to access a continuous range of physical memory (raw memory) as a
- * {@link ByteBuffer}. A {@code RawBlock} instance can be obtained from a {@link MMIODevice} instance.
- * <p />
- * The {@code index} parameter of {@code ByteBuffer} <i>absolute</i> operations map to physical memory addresses. The
- * {@code index} values are relative to the base address of the raw memory area. The {@code index} value {@code 0}
- * corresponds to the base address of the raw memory area.
- * @since 1.0
- */
-@apimarker.API("device-io_1.0")
-public interface RawBlock extends RawMemory {
-    /**
-     * Gets the complete memory area this {@code RawBlock} is mapped to as a <em>direct</em> {@link ByteBuffer}. The
-     * byte order of the retrieved buffer will be that of this device unless the byte ordering is not standard (as
-     * indicated by the value {@link MMIODevice#MIXED_ENDIAN}; in which case the buffer's byte order will be set to
-     * {@link ByteOrder#BIG_ENDIAN}.
-     * <p />
-     * When the returned {@code ByteBuffer} instance is invalidated because the device is either closed or in
-     * exclusive use by some other application then an attempt to access the {@code ByteBuffer} instance will not change
-     * the buffer's content and will cause a {@code ClosedDeviceException} or some other unspecified exception to be
-     * thrown either at the time of the access or at some later time.
-     *
-     * @return the <em>direct</em> {@link ByteBuffer} for the complete raw memory area associated with this
-     *         {@code RawBlock}.
-     * @throws IOException
-     *             if some other I/O error occurs.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    ByteBuffer asDirectBuffer() throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Returns the name assigned to this {@code RawBlock} instance.
-     *
-     * @return this {@code RawBlock} instance's name or {@code null} if this {@code RawBlock} instance was obtained by a
-     *         call to {@link MMIODevice#getAsRawBlock MMIODevice.getAsRawBlock}.
-     */
-    @Override
-    String getName();
-}
\ No newline at end of file
--- a/src/se/classes/jdk/dio/mmio/RawMemory.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.dio.mmio;
-
-/**
- * The {@code RawMemory} interface provides generic methods for the different types of raw memory area a device
- * device's registers may be mapped to.
- * @since 1.0
- */
-@apimarker.API("device-io_1.0")
-public interface RawMemory {
-
-    /**
-     * Returns the name assigned to this {@code RawMemory} instance.
-     *
-     * @return this {@code RawMemory} instance's name.
-     */
-    String getName();
-}
\ No newline at end of file
--- a/src/se/classes/jdk/dio/mmio/RawRegister.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.dio.mmio;
-
-import jdk.dio.ClosedDeviceException;
-import jdk.dio.UnavailableDeviceException;
-import java.io.IOException;
-
-/**
- * The {@code RawRegister} interface provides methods for setting and getting the value of a register or memory area
- * holding a value of type {@code byte}, {@code short}, {@code int} or {@code long}. A {@code RawRegister} instance can
- * be obtained from a {@link MMIODevice} instance.
- * <p />
- * Developers should be aware when using this API of the potential performance and memory allocation penalty induced by
- * primitive auto-boxing. For intensive reading and writing of registers such as data input and data output registers,
- * the use of the {@link RawBlock} returned by {@link MMIODevice#getAsRawBlock() } should be preferred.
- *
- * @param <T>
- *            the type of the value held by the register.
- * @since 1.0
- */
-@apimarker.API("device-io_1.0")
-public interface RawRegister<T extends Number> extends RawMemory {
-
-    /**
-     * Sets the value at the memory area associated with this object to the result of performing a logical AND of the
-     * value at the memory area with the argument value.
-     *
-     * @param value
-     *            the value to perform a logical AND with.
-     * @throws IOException
-     *             if the associated memory area is not writable.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    void and(T value) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Clears (sets to {@code 0}) the designated bit value at the memory area associated with this object.
-     *
-     * @param index
-     *            the index of the bit.
-     * @throws IOException
-     *             if the associated memory area is not writable.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     * @throws IllegalArgumentException
-     *             if {@code index} is less than {@code 0} or greater or equal to the size in bits of the value at the
-     *             memory area associated with this object.
-     */
-    void clearBit(int index) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Clears (sets to {@code 0}) the specified bits at the memory area associated with this object.
-     *
-     * @param mask
-     *            the bit mask.
-     * @throws IOException
-     *             if the associated memory area is not writable.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    void clearBits(T mask) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Gets the value at the memory area associated with this object.
-     *
-     * @return the value.
-     * @throws IOException
-     *             if the associated memory area is not readable.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    T get() throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Returns the type of the value this {@code RawRegister} instance can hold.
-     *
-     * @return this {@code RawRegister} instance's value type.
-     */
-    Class<T> getType();
-
-    /**
-     * Checks whether the designated bit value at the memory area associated with this object is set (equal to {@code 1}
-     * )
-     *
-     * @param index
-     *            the index of the bit.
-     * @return the bit value.
-     * @throws IOException
-     *             if the associated memory area is not readable.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     * @throws IllegalArgumentException
-     *             if {@code index} is less than {@code 0} or greater or equal to the size in bits of the value at the
-     *             memory area associated with this object.
-     */
-    boolean isBitSet(int index) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Sets the value at the memory area associated with this object to the result of performing a logical OR of the
-     * value at the memory area with the argument value.
-     *
-     * @param value
-     *            the value to perform a logical OR with.
-     * @throws IOException
-     *             if the associated memory area is not writable.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    void or(T value) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Sets the value at the memory area associated with this object.
-     *
-     * @param value
-     *            the value to set.
-     * @throws IOException
-     *             if the associated memory area is not writable.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    void set(T value) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Sets (to {@code 1}) the designated bit value at the memory area associated with this object.
-     *
-     * @param index
-     *            the index of the bit.
-     * @throws IOException
-     *             if the associated memory area is not writable.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     * @throws IllegalArgumentException
-     *             if {@code index} is less than {@code 0} or greater or equal to the size in bits of the value at the
-     *             memory area associated with this object.
-     */
-    void setBit(int index) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Sets (to {@code 1}) the specified bits at the memory area associated with this object.
-     *
-     * @param mask
-     *            the bit mask.
-     * @throws IOException
-     *             if the associated memory area is not writable.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    void setBits(T mask) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-
-    /**
-     * Sets the value at the memory area associated with this object to the result of performing a logical XOR of the
-     * value at the memory area with the argument value.
-     *
-     * @param value
-     *            the value to perform a logical XOR with.
-     * @throws IOException
-     *             if the associated memory area is not writable.
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another application.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     */
-    void xor(T value) throws IOException, UnavailableDeviceException, ClosedDeviceException;
-}
\ No newline at end of file
--- a/src/se/classes/jdk/dio/mmio/package-info.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-/**
- * Interfaces and classes for performing memory-mapped I/O.
- * <p />
- * Memory mapped I/O is typically used for controlling hardware devices by reading from and writing to registers or
- * memory blocks of the hardware mapped to the system memory. The MMIO APIs allows for low level control over the
- * device.
- * <p />
- * In order to access a specific memory block a device has been mapped to, an application should first open and obtain
- * an {@link jdk.dio.mmio.MMIODevice} instance for the memory-mapped I/O device the application wants to
- * control and access, using its numeric ID, name, type (interface) and/or properties:
- * <dl>
- * <dt>Using its ID</dt>
- * <dd>
- * <blockquote>
- *
- * <pre>
- * MMIODevice device = (MMIODevice) DeviceManager.open(7);
- * </pre>
- *
- * </blockquote></dd>
- * <dt>Using its name and interface</dt>
- * <dd>
- * <blockquote>
- *
- * <pre>
- * MMIODevice device = DeviceManager.open(&quot;RTC&quot;, MMIODevice.class, null);
- * </pre>
- *
- * </blockquote></dd>
- * </dl>
- * Once the device opened, the application can retrieve registers using methods of the
- * {@link jdk.dio.mmio.MMIODevice MMIODevice} interface such as the
- * {@link jdk.dio.mmio.MMIODevice#getRegister MMIODevice.getRegister} method. <blockquote>
- *
- * <pre>
- * device.getRegister(&quot;Seconds&quot;, Byte.class);
- * </pre>
- *
- * </blockquote> When done, the application should call the {@link jdk.dio.mmio.MMIODevice#close MMIODevice.close}
- * method to close the MMIO device. <blockquote>
- *
- * <pre>
- * device.close();
- * </pre>
- *
- * </blockquote> The following sample codes give examples of using the MMIO API to communicate Real Time Clock device:
- * <blockquote>
- *
- * <pre>
- * static final int INTERRUPT = 0;
- *
- * try (MMIODevice rtc = DeviceManager.open("RTC", MMIODevice.class, null)) {
- *     //The RTC device has 14 bytes of clock and control registers and 50 bytes
- *     // of general purpose RAM (see the data sheet of the 146818 Real Time Clock such as HITACHI HD146818).
- *     RawRegister<Byte> seconds = rtc.getRegister("Seconds", Byte.class);
- *     RawRegister<Byte> secAlarm = rtc.getRegister("SecAlarm", Byte.class);
- *     RawRegister<Byte> minutes = rtc.getRegister("Minutes", Byte.class);
- *     RawRegister<Byte> minAlarm = rtc.getRegister("MinAlarm", Byte.class);
- *     RawRegister<Byte> hours = rtc.getRegister("Hours", Byte.class);
- *     RawRegister<Byte> hrAlarm = rtc.getRegister("HrAlarm", Byte.class);
- *     ... // More registers
- *     RawRegister<Byte> registerA = rtc.getRegister("RegisterA", Byte.class);
- *     RawRegister<Byte> registerB = rtc.getRegister("RegisterB", Byte.class);
- *     RawRegister<Byte> registerC = rtc.getRegister("RegisterC", Byte.class);
- *     RawRegister<Byte> registerD = rtc.getRegister("RegisterD", Byte.class);
- *     RawBlock userRAM = rtc.getBlock("UserRam");
- *     ...
- * } catch (IOException ioe) {
- *     // handle exception
- * }
- * </pre>
- *
- * </blockquote> The preceding example is using a <em>try-with-resources</em> statement; the
- * {@link jdk.dio.mmio.MMIODevice#close MMI0Device.close} method is automatically invoked by the
- * platform at the end of the statement. <blockquote>
- *
- * <pre>
- * // Sets the daily alarm for after some delay
- * public void setAlarm(MMIODevice rtc, byte delaySeconds, byte delayMinutes, byte delayHours) throws IOException,
- *         DeviceException {
- *     Register&lt;Byte&gt; seconds = rtc.getByteRegister(&quot;Seconds&quot;, Byte.class);
- *     Register&lt;Byte&gt; secAlarm = rtc.getByteRegister(&quot;SecAlarm&quot;, Byte.class);
- *     Register&lt;Byte&gt; minutes = rtc.getByteRegister(&quot;Minutes&quot;, Byte.class);
- *     Register&lt;Byte&gt; minAlarm = rtc.getByteRegister(&quot;MinAlarm&quot;, Byte.class);
- *     Register&lt;Byte&gt; hours = rtc.getByteRegister(&quot;Hours&quot;, Byte.class);
- *     Register&lt;Byte&gt; hrAlarm = rtc.getByteRegister(&quot;HrAlarm&quot;, Byte.class);
- *     Register&lt;Byte&gt; registerB = rtc.getByteRegister(&quot;RegisterB&quot;, Byte.class);
- *     RawBlock userRAM = rtc.getBlock(&quot;UserRam&quot;, Byte.class);
- *
- *     // Directly read from/write to the registers using RawByte instances.
- *     byte currentSeconds = seconds.get();
- *     byte currentMinutes = minutes.get();
- *     byte currentHours = hours.get();
- *     int i = (currentSeconds + delaySeconds) % 60;
- *     int j = (currentSeconds + delaySeconds) / 60;
- *     secAlarm.set((byte) i);
- *     i = (currentMinutes + delayMinutes + j) % 60;
- *     j = (currentMinutes + delayMinutes + j) / 60;
- *     minAlarm.set((byte) i);
- *     i = (currentHours + delayHours + j) % 24;
- *     hrAlarm.set((byte) i);
- *     rtc.setMMIOEventListener(INTERRUPT, new MMIOEventListener() {
- *
- *         public void eventDispatched(MMIOEvent event) {
- *             try {
- *                 MMIODevice rtc = event.getDevice();
- *                 Register&lt;Byte&gt; registerC = rtc.getByteRegister(&quot;RegisterC&quot;, Byte.class);
- *                 // Check the Alarm Interrupt Flag (AF)
- *                 if ((registerC.get() &amp; 0X20) != 0) {
- *                     // Notify application of alarm
- *                 }
- *             } catch (IOException ioe) {
- *                 // handle exception
- *             }
- *         }
- *     });
- *     // Set the Alarm Interrupt Enabled (AIE) flag
- *     registerB.set((byte) (registerB.get() | 0X20));
- * }
- * </pre>
- *
- * </blockquote> Alternatively, in this example, the value of {@code RegisterC} could be automatically captured upon
- * occurrence of an interrupt request from the Real Time Clock device as follows: <blockquote>
- *
- * <pre>
- * rtc.setMMIOEventListener(INTERRUPT, &quot;RegisterC&quot;, new MMIOEventListener() {
- *
- *     public void eventDispatched(MMIOEvent event) {
- *         Byte v = event.getCapturedRegisterValue();
- *         // Check the Alarm Interrupt Flag (AF)
- *         if ((v.byteValue() &amp; 0X20) != 0) {
- *             // Notify application of alarm
- *         }
- *     }
- * });
- * </pre>
- *
- * </blockquote>
- * <p />
- * Unless otherwise noted, passing a {@code null} argument to a constructor or method in any class
- * or interface in this package will cause a {@link java.lang.NullPointerException NullPointerException} to be thrown.
- *
- * @since 1.0
- */
-package jdk.dio.mmio;
-
--- a/src/se/linux/native/com/oracle/dio/rs485_enabler.cpp	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/linux/native/com/oracle/dio/rs485_enabler.cpp	Fri Sep 09 13:20:20 2016 +0300
@@ -51,8 +51,10 @@
     memset(&rs485conf, 0x0, sizeof(struct serial_rs485));
     /* Enable RS485 mode */
     rs485conf.flags |= SER_RS485_ENABLED;
-    /* Set logical level for RTS pin equal to 1 when sending */
-    rs485conf.flags |= SER_RS485_RTS_ON_SEND;
+    if (rts_on_send) {
+        /* Set logical level for RTS pin equal to 1 when sending */
+        rs485conf.flags |= SER_RS485_RTS_ON_SEND;
+    }
     /* need some field test to detect whether this value is necessary */
     rs485conf.delay_rts_before_send = 0x00000001;
     if (ioctl (handle, TIOCSRS485, &rs485conf) < 0) {
--- a/src/se/native/com/oracle/dio/dio_event_queue.cpp	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/native/com/oracle/dio/dio_event_queue.cpp	Fri Sep 09 13:20:20 2016 +0300
@@ -25,31 +25,19 @@
 
 #include "dio_event_queue.h"
 #include <string.h>
+#include "javacall_logging.h"
 
-static const int JCLASS_SIZE = sizeof(jclass);
+/* Entities required for sending notifications */
+static jobject eventBuffer = NULL;
 
 extern "C" {
 
-JNIEXPORT jclass JNICALL Java_com_oracle_dio_impl_EventQueue_getEventClass
-  (JNIEnv* env, jclass clazz, jobject buffer, jint currPos) {
-    // required methods references
-    jclass bufferClass = env->GetObjectClass(buffer);
-
-    jmethodID setPositionID = bufferClass ? env->GetMethodID(bufferClass, "position", "(I)Ljava/nio/Buffer;") :
-                                            NULL;
-
-    // Not necessary to synchronize on buffer, it's always called from protected section
-    jbyte* buf = setPositionID ? (jbyte*)env->GetDirectBufferAddress(buffer) :
-                                 NULL;
-
-    jclass eventClass = NULL;
-    if (buf) {
-        memcpy(&eventClass, buf + currPos, JCLASS_SIZE);
-        // update buffer position
-        env->CallObjectMethod(buffer, setPositionID, currPos + JCLASS_SIZE);
+JNIEXPORT void JNICALL Java_com_oracle_dio_impl_EventQueue_setNativeEntries
+  (JNIEnv* env, jobject this_obj, jobject buffer) {
+    if (eventBuffer) {
+        env->DeleteGlobalRef(eventBuffer);
     }
-
-    return eventClass;
+    eventBuffer = env->NewGlobalRef(buffer);
 }
 
 } /* extern "C */
@@ -60,11 +48,15 @@
  * of the com.oracle.dio.impl.EventQueue class for details.
  */
 void event_queue_put_native_event
-  (JavaVM* cachedJVM, jobject eventBufferRef, jclass eventClass, const char *payload, int payload_size) {
+  (JavaVM* cachedJVM, const char* device_type, const char *payload, int payload_size) {
     JNIEnv* env;
-    cachedJVM->AttachCurrentThread((void**)&env, NULL);
+    if (NULL == eventBuffer) {
+        JAVACALL_REPORT_ERROR(JC_DIO, "Event queue is not initialized properly");
+        return;
+    }
+    cachedJVM->AttachCurrentThread((void **)&env, NULL);
 
-    jclass bufferClass = env->GetObjectClass(eventBufferRef);
+    jclass bufferClass = env->GetObjectClass(eventBuffer);
     jmethodID notifyID = bufferClass ? env->GetMethodID(bufferClass, "notify", "()V") :
                                        NULL;
     jmethodID limitID = notifyID ? env->GetMethodID(bufferClass, "limit", "()I") :
@@ -72,34 +64,35 @@
     jmethodID setLimitID = limitID ? env->GetMethodID(bufferClass, "limit", "(I)Ljava/nio/Buffer;") :
                                      NULL;
 
+    const int device_type_len = strlen(device_type) + 1;
     if (setLimitID) {
-        env->MonitorEnter(eventBufferRef);
+        env->MonitorEnter(eventBuffer);
 
         if (env->ExceptionCheck() != JNI_TRUE) {
             // check enough space in direct buffer
-            jlong capacity = env->GetDirectBufferCapacity(eventBufferRef);
-            jint limit = env->CallIntMethod(eventBufferRef, limitID);
+            jlong capacity = env->GetDirectBufferCapacity(eventBuffer);
+            jint limit = env->CallIntMethod(eventBuffer, limitID);
 
-            jint newLimit = limit + JCLASS_SIZE + payload_size + 2;
+            jint newLimit = limit + device_type_len + payload_size + 2;
 
             if (newLimit < capacity) {
-                jbyte* buf = (jbyte*)env->GetDirectBufferAddress(eventBufferRef);
+                jbyte* buf = (jbyte*)env->GetDirectBufferAddress(eventBuffer);
 
                 buf += limit;
 
-                memcpy(buf, &eventClass, JCLASS_SIZE);
-                buf += JCLASS_SIZE;
+                memcpy(buf, device_type, device_type_len);
+                buf += device_type_len;
 
                 // payload
                 *buf++ = (jbyte)((payload_size & 0xFF00) >> 8); // high byte
                 *buf++ = (jbyte)(payload_size & 0xFF);          // then low byte
                 memcpy(buf, payload, payload_size);
 
-                env->CallObjectMethod(eventBufferRef, setLimitID, newLimit);
+                env->CallObjectMethod(eventBuffer, setLimitID, newLimit);
             }
-            env->CallVoidMethod(eventBufferRef, notifyID);
+            env->CallVoidMethod(eventBuffer, notifyID);
         }
-        env->MonitorExit(eventBufferRef);
+        env->MonitorExit(eventBuffer);
     }
     cachedJVM->DetachCurrentThread();
 }
--- a/src/se/native/com/oracle/dio/dio_event_queue.h	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/native/com/oracle/dio/dio_event_queue.h	Fri Sep 09 13:20:20 2016 +0300
@@ -34,6 +34,6 @@
  * of the com.oracle.dio.impl.EventQueue class for details.
  */
 void event_queue_put_native_event
-  (JavaVM* cachedJVM, jobject eventBufferRef, jclass eventClass, const char* payload, int payload_size);
+  (JavaVM* cachedJVM, const char* device_type, const char *payload, int payload_size);
 
 #endif /* __DEVICEACCESS_EVENT_QUEUE_H */
--- a/src/se/native/com/oracle/dio/gpio/impl/jni_gpio.cpp	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/native/com/oracle/dio/gpio/impl/jni_gpio.cpp	Fri Sep 09 13:20:20 2016 +0300
@@ -357,64 +357,8 @@
     return (jint)value;
 }
 
-/*
- * Sets the GPIOPortConfig.pins private field.
- * Class:     com_oracle_dio_gpio_impl_GPIOPortImpl
- * Method:    assignPins0
- */
-JNIEXPORT void JNICALL Java_com_oracle_dio_gpio_impl_GPIOPortImpl_assignPins0
-  (JNIEnv* env, jobject obj, jobject cfg, jobjectArray pins) {
-    jclass cfgClass = env->GetObjectClass(cfg);
-    jfieldID pinsField = cfgClass ? env->GetFieldID(cfgClass, "pins", "[Ljdk/dio/gpio/GPIOPin;") :
-                                    NULL;
-    if (pinsField) {
-        env->SetObjectField(cfg, pinsField, pins);
-    }
-}
 
 
-/* Entities required for sending GPIO pin notifications */
-static jobject pinEventBuffer = NULL;
-static jclass pinEventClass = NULL;
-
-/*
- * Sets references to the Java entities required for sending notifications.
- * Class:     com_oracle_dio_gpio_impl_GPIOPinEventHandler
- * Method:    setNativeEntries
- */
-JNIEXPORT void JNICALL Java_com_oracle_dio_gpio_impl_GPIOPinEventHandler_setNativeEntries
-  (JNIEnv* env, jclass clazz, jobject buffer, jclass event) {
-    if (pinEventBuffer) {
-        env->DeleteGlobalRef(pinEventBuffer);
-    }
-    pinEventBuffer = env->NewGlobalRef(buffer);
-    if (pinEventClass) {
-        env->DeleteGlobalRef(pinEventClass);
-    }
-    pinEventClass = (jclass)env->NewGlobalRef(event);
-}
-
-/* Entities required for sending GPIO port notifications */
-static jobject portEventBuffer = NULL;
-static jclass portEventClass = NULL;
-
-/*
- * Sets references to the Java entities required for sending notifications.
- * Class:     com_oracle_dio_gpio_impl_GPIOPinEventHandler
- * Method:    setNativeEntries
- */
-JNIEXPORT void JNICALL Java_com_oracle_dio_gpio_impl_GPIOPortEventHandler_setNativeEntries
-  (JNIEnv* env, jclass clazz, jobject buffer, jclass event) {
-    if (portEventBuffer) {
-        env->DeleteGlobalRef(portEventBuffer);
-    }
-    portEventBuffer = env->NewGlobalRef(buffer);
-    if (portEventClass) {
-        env->DeleteGlobalRef(portEventClass);
-    }
-    portEventClass = (jclass)env->NewGlobalRef(event);
-}
-
 /*
  * Sends a pin value change event.
  * @param handle    open pin handle
@@ -422,21 +366,19 @@
  */
 void javanotify_gpio_pin_value_changed
   (const javacall_handle handle, const javacall_int32 value) {
-    if (pinEventBuffer == NULL || pinEventClass == NULL) {
-        return;
-    }
     device_reference device = getDeviceReference(handle);
     if (device == INVALID_DEVICE_REFERENCE) {
         return;
     }
-    const int size = 8; // reserve 4 bytes for the handle and 4 bytes for the value
+    const int size = 12; // reserve 4 bytes for the handle, 4 for subevent (0 in this case), and 4 bytes for the value
     char payload[size];
+    memset(payload, 0, size);
     payload[0] = (unsigned int)device >> 24, payload[1] = (unsigned int)device >> 16;
     payload[2] = (unsigned int)device >> 8,  payload[3] = (unsigned int)device;
-    payload[4] = value >> 24, payload[5] = value >> 16;
-    payload[6] = value >> 8,  payload[7] = value;
+    payload[8] = value >> 24, payload[9] = value >> 16;
+    payload[10] = value >> 8,  payload[11] = value;
     JavaVM* vm = getGlobalJavaVM();
-    event_queue_put_native_event(vm, pinEventBuffer, pinEventClass, payload, size);
+    event_queue_put_native_event(vm, "jdk.dio.gpio.GPIOPin", payload, size);
 }
 
 /*
@@ -446,21 +388,19 @@
  */
 void javanotify_gpio_port_value_changed
   (const javacall_handle handle, const javacall_int32 value) {
-    if (portEventBuffer == NULL || portEventClass == NULL) {
-        return;
-    }
     device_reference device = getDeviceReference(handle);
     if (device == INVALID_DEVICE_REFERENCE) {
         return;
     }
-    const int size = 8; // reserve 4 bytes for the handle and 4 bytes for the value
+    const int size = 12; // reserve 4 bytes for the handle, 4 for subevent (0 in this case),  and 4 bytes for the value
     char payload[size];
+    memset(payload, 0, size);
     payload[0] = (unsigned int)device >> 24, payload[1] = (unsigned int)device >> 16;
     payload[2] = (unsigned int)device >> 8,  payload[3] = (unsigned int)device;
-    payload[4] = value >> 24, payload[5] = value >> 16;
-    payload[6] = value >> 8,  payload[7] = value;
+    payload[8] = value >> 24, payload[9] = value >> 16;
+    payload[10] = value >> 8,  payload[11] = value;
     JavaVM* vm = getGlobalJavaVM();
-    event_queue_put_native_event(vm, portEventBuffer, portEventClass, payload, size);
+    event_queue_put_native_event(vm, "jdk.dio.gpio.GPIOPort", payload, size);
 }
 
 } // extern "C"
--- a/src/se/native/com/oracle/dio/uart/impl/jni_signal_dispatcher.cpp	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/native/com/oracle/dio/uart/impl/jni_signal_dispatcher.cpp	Fri Sep 09 13:20:20 2016 +0300
@@ -31,27 +31,6 @@
 
 extern "C" {
 
-/* Entities required for sending modem signal notifications */
-static jobject eventBuffer = NULL;
-static jclass eventClass = NULL;
-
-/*
- * Class      com_oracle_dio_uart_impl_ModemSignalDispatcher
- * Method:    setNativeEntries
- * Signature: (Ljava/nio/Buffer;Ljava/lang/Class;)V
- */
-JNIEXPORT void JNICALL Java_com_oracle_dio_uart_impl_ModemSignalDispatcher_setNativeEntries
-  (JNIEnv* env, jclass clazz, jobject buffer, jclass event) {
-    if (eventBuffer) {
-        env->DeleteGlobalRef(eventBuffer);
-    }
-    eventBuffer = env->NewGlobalRef(buffer);
-    if (eventClass) {
-        env->DeleteGlobalRef(eventClass);
-    }
-    eventClass = (jclass)env->NewGlobalRef(event);
-}
-
 /*
  * Class:     com_oracle_dio_uart_impl_ModemSignalDispatcher
  * Method:    startListening0
@@ -93,9 +72,6 @@
  */
 void javanotify_serial_signal
   (javacall_handle port, javacall_handle target, javacall_serial_signal_type signal, javacall_bool value) {
-    if (eventBuffer == NULL || eventClass == NULL) {
-        return;
-    }
 
     device_reference device = getDeviceReference(port);
     if (device == INVALID_DEVICE_REFERENCE) {
@@ -103,10 +79,10 @@
     }
 
     // reserve 4 bytes for the port handler, 4 bytes for the signal line,
-    // and 1 byte for the value
-    const int size = 9;
+    // and 4 byte for the value
+    const int size = 12;
     char payload[size];
-
+    memset(payload, 0, size);
     payload[0] = (jint)device >> 24, payload[1] = (jint)device >> 16;
     payload[2] = (jint)device >> 8,  payload[3] = (jint)device >> 0;
     payload[4] = (jint)signal >> 24, payload[5] = (jint)signal >> 16;
@@ -114,7 +90,7 @@
     payload[8] = (value != JAVACALL_FALSE ? 1 : 0);
 
     JavaVM* vm = getGlobalJavaVM();
-    event_queue_put_native_event(vm, eventBuffer, eventClass, payload, size);
+    event_queue_put_native_event(vm, "jdk.dio.uart.ModemUART", payload, size);
 }
 
 } // extern "C"
--- a/src/se/native/com/oracle/dio/uart/impl/jni_uart.cpp	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/se/native/com/oracle/dio/uart/impl/jni_uart.cpp	Fri Sep 09 13:20:20 2016 +0300
@@ -33,30 +33,11 @@
 
 extern "C" {
 
-/* Entities required for sending uart notifications */
-static jobject eventBuffer = NULL;
-static jclass eventClass = NULL;
-
 /* Cleanup function */
 static javacall_dio_result uart_cleanup(javacall_handle handle) {
     return javacall_uart_close_start(handle, NULL);
 }
 
-/*
- * Class      com_oracle_dio_uart_impl_UARTEventHandler
- * Method:    setNativeEntries
- */
-JNIEXPORT void JNICALL Java_com_oracle_dio_uart_impl_UARTEventHandler_setNativeEntries
-  (JNIEnv* env, jclass clazz, jobject buffer, jclass event) {
-    if (eventBuffer) {
-        env->DeleteGlobalRef(eventBuffer);
-    }
-    eventBuffer = env->NewGlobalRef(buffer);
-    if (eventClass) {
-        env->DeleteGlobalRef(eventClass);
-    }
-    eventClass = (jclass)env->NewGlobalRef(event);
-}
 
 /*
  * Class:     com_oracle_dio_uart_impl_UARTImpl
@@ -79,7 +60,7 @@
     javacall_dio_result result;
     result = javacall_uart_open_start(devName, baudRate,
                                      (javacall_uart_stop_bits)stopBits,
-                                     flowControl,
+                                     (javacall_serial_flowcontrol)flowControl,
                                      (javacall_uart_bits_per_char)bitsPerChar,
                                      (javacall_uart_parity)parity,
                                      (exclusive != JNI_FALSE ? JAVACALL_TRUE : JAVACALL_FALSE),
@@ -517,6 +498,32 @@
 
 /*
  * Class:     com_oracle_dio_uart_impl_UARTImpl
+ * Method:    getFlowControlMode0
+ */
+JNIEXPORT jint JNICALL Java_com_oracle_dio_uart_impl_UARTImpl_getFlowControlMode0
+  (JNIEnv* env, jobject obj) {
+    device_reference device = getDeviceReferenceFromDeviceObject(env, obj);
+    javacall_serial_flowcontrol flow_control;
+    javacall_dio_result result = javacall_uart_get_flowcontrol(getDeviceHandle(device), &flow_control);
+
+    checkJavacallFailure(env, result);
+    return (jint)flow_control;
+}
+
+/*
+ * Class:     com_oracle_dio_uart_impl_UARTImpl
+ * Method:    setFlowControlMode0
+ */
+JNIEXPORT void JNICALL Java_com_oracle_dio_uart_impl_UARTImpl_setFlowControlMode0
+  (JNIEnv* env, jobject obj, jint flow_control) {
+    device_reference device = getDeviceReferenceFromDeviceObject(env, obj);
+    javacall_dio_result result = javacall_uart_set_flowcontrol(getDeviceHandle(device),
+                                        (javacall_serial_flowcontrol)flow_control);
+    checkJavacallFailure(env, result);
+}
+
+/*
+ * Class:     com_oracle_dio_uart_impl_UARTImpl
  * Method:    stopWriting0
  */
 JNIEXPORT void JNICALL Java_com_oracle_dio_uart_impl_UARTImpl_stopWriting0
@@ -620,9 +627,6 @@
 void javanotify_uart_event
   (javacall_uart_event_type type, javacall_handle port, javacall_int32 bytes,
    javacall_result result) {
-    if (eventBuffer == NULL || eventClass == NULL) {
-        return;
-    }
 
     device_reference device = getDeviceReference(port);
     if (device == INVALID_DEVICE_REFERENCE) {
@@ -642,7 +646,7 @@
     payload[10] = (jint)bytes >> 8,  payload[11] = (jint)bytes >> 0;
 
     JavaVM* vm = getGlobalJavaVM();
-    event_queue_put_native_event(vm, eventBuffer, eventClass, payload, size);
+    event_queue_put_native_event(vm, "jdk.dio.uart.UART", payload, size);
 }
 
 /**
--- a/src/share/classes/com/oracle/dio/gpio/impl/GPIOPinImpl.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/gpio/impl/GPIOPinImpl.java	Fri Sep 09 13:20:20 2016 +0300
@@ -29,15 +29,17 @@
 import java.io.IOException;
 import java.security.AccessController;
 
+import com.oracle.dio.impl.EventQueueManager;
+import com.oracle.dio.impl.Handle;
 import com.oracle.dio.power.impl.PowerManagedBase;
 import com.oracle.dio.utils.Constants;
 import com.oracle.dio.utils.ExceptionMessage;
-import com.oracle.dio.impl.Handle;
 
 import jdk.dio.*;
 import jdk.dio.gpio.GPIOPin;
 import jdk.dio.gpio.GPIOPinConfig;
 import jdk.dio.gpio.GPIOPinPermission;
+import jdk.dio.gpio.PinEvent;
 import jdk.dio.gpio.PinListener;
 
 import romizer.*;
@@ -51,6 +53,9 @@
     DeviceNotFoundException, InvalidDeviceConfigException{
         super(dscr, mode);
 
+        GPIOPinPermission permission = new GPIOPinPermission(getSecurityName());
+        AccessController.checkPermission(permission);
+
         GPIOPinConfig cfg = dscr.getConfiguration();
 
         if(cfg.getControllerName() != null) {
@@ -59,9 +64,6 @@
             );
         }
 
-        GPIOPinPermission permission = new GPIOPinPermission(getSecurityName());
-        AccessController.checkPermission(permission);
-
         openPinByConfig0( cfg.getControllerNumber(), cfg.getPinNumber(),
                           cfg.getDirection(), cfg.getDriveMode(),
                           cfg.getTrigger(), cfg.getInitValue(),
@@ -83,14 +85,16 @@
 
     @Override
     public synchronized void setTrigger(int trigger)
-    throws java.io.IOException,
-    UnavailableDeviceException,
-    ClosedDeviceException {
-        checkOpen();
+    throws java.io.IOException, UnavailableDeviceException, ClosedDeviceException {
+        checkPowerState();
         if (GPIOPinConfig.TRIGGER_NONE > trigger ||
             GPIOPinConfig.TRIGGER_BOTH_LEVELS < trigger) {
             throw new IllegalArgumentException(String.valueOf(trigger));
         }
+        if (getOutputMode0()) {
+            throw new UnsupportedOperationException(
+                ExceptionMessage.format(ExceptionMessage.GPIO_INCOMPATIBLE_DIR));
+        }
         setTrigger0( trigger);
     }
 
@@ -109,9 +113,6 @@
         * @return     true if pin is currently high
         */
     public synchronized boolean getValue() throws IOException,UnavailableDeviceException, ClosedDeviceException {
-
-        checkOpen();
-
         checkPowerState();
 
         int ret = readPin0();
@@ -128,9 +129,6 @@
         */
     public synchronized void setValue(boolean value)
     throws IOException,UnavailableDeviceException{
-
-        checkOpen();
-
         checkPowerState();
 
         if (getOutputMode0() == false) {
@@ -155,6 +153,15 @@
         return(getOutputMode0() ? OUTPUT : INPUT );
     }
 
+    @Override
+    protected void processNativeEvent(int event, int... data) {
+        final int value = data[0];
+        PinListener listener = this.listener;
+        if (null != listener) {
+            listener.valueChanged(new PinEvent(this, value > 0));
+        }
+    }
+
     public synchronized void setInputListener(PinListener listener) throws java.io.IOException,
     UnavailableDeviceException,
     ClosedDeviceException{
@@ -168,7 +175,7 @@
         }
 
         if (null == listener) {
-            GPIOPinEventHandler.getInstance().removeEventListener(this);
+            EventQueueManager.getInstance().removeEventListener(GPIOPin.class, 0, this);
             if (null != this.listener) {
                 try {
                     stopNoti0();
@@ -178,12 +185,11 @@
             }
             this.listener = null;
         } else if (this.listener == null) {
-            GPIOPinEventHandler.getInstance().setEventListener(this, listener);
             this.listener = listener;
+            EventQueueManager.getInstance().setEventListener(GPIOPin.class, 0, this);
             try {
                 startNoti0();
             } catch (IOException ex) {
-                GPIOPinEventHandler.getInstance().removeEventListener(this);
                 this.listener = null;
                 throw new UnsupportedOperationException(
                     ExceptionMessage.format(ExceptionMessage.GPIO_CANNOT_START_NOTIFICATION)
@@ -201,8 +207,6 @@
 
         AccessController.checkPermission(new GPIOPinPermission(getSecurityName(), GPIOPinPermission.SET_DIRECTION));
 
-        checkOpen();
-
         checkPowerState();
 
         int dir = ((GPIOPinConfig)dscr.getConfiguration()).getDirection();
--- a/src/share/classes/com/oracle/dio/gpio/impl/GPIOPortImpl.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/gpio/impl/GPIOPortImpl.java	Fri Sep 09 13:20:20 2016 +0300
@@ -27,24 +27,27 @@
 
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.security.AccessController;
+
+import com.oracle.dio.impl.AbstractPeripheral;
+import com.oracle.dio.impl.EventQueueManager;
+import com.oracle.dio.utils.Constants;
+import com.oracle.dio.utils.ExceptionMessage;
 
 import jdk.dio.ClosedDeviceException;
-import jdk.dio.InvalidDeviceConfigException;
 import jdk.dio.DeviceDescriptor;
 import jdk.dio.DeviceManager;
 import jdk.dio.DeviceNotFoundException;
+import jdk.dio.InvalidDeviceConfigException;
+import jdk.dio.UnavailableDeviceException;
 import jdk.dio.UnsupportedDeviceTypeException;
-import jdk.dio.UnavailableDeviceException;
 import jdk.dio.gpio.GPIOPin;
 import jdk.dio.gpio.GPIOPinConfig;
 import jdk.dio.gpio.GPIOPort;
 import jdk.dio.gpio.GPIOPortConfig;
+import jdk.dio.gpio.GPIOPortPermission;
+import jdk.dio.gpio.PortEvent;
 import jdk.dio.gpio.PortListener;
-import com.oracle.dio.impl.AbstractPeripheral;
-import com.oracle.dio.utils.Constants;
-import com.oracle.dio.utils.ExceptionMessage;
-import jdk.dio.gpio.GPIOPortPermission;
-import java.security.AccessController;
 
 import romizer.*;
 
@@ -52,6 +55,7 @@
 
     private PortListener listener;
     private int maxVal;
+    private GPIOPinFake[] pins;
 
     public GPIOPortImpl(DeviceDescriptor<GPIOPort> dscr, int mode) throws
                                     DeviceNotFoundException, InvalidDeviceConfigException {
@@ -83,12 +87,11 @@
                                    mode == DeviceManager.EXCLUSIVE);
 
         maxVal = getMaxVal0();
-        GPIOPinFake[] pins  = new GPIOPinFake[pinCfgs.length];
+        pins  = new GPIOPinFake[pinCfgs.length];
         for (int i = 0; i < pins.length; i++) {
             pins[i] = new GPIOPinFake(pinCfgs[i]);
         }
 
-        assignPins0(cfg, pins);
     }
 
     @Override
@@ -163,6 +166,13 @@
         setOutputMode0(((OUTPUT == direction)?true:false) );
     }
 
+    public void processNativeEvent(int event, int data) {
+        PortListener listener = this.listener;
+        if (null != listener) {
+            listener.valueChanged(new PortEvent(this, data));
+        }
+    }
+
     @Override
     public synchronized void setInputListener(PortListener listener) throws java.io.IOException,
                          UnavailableDeviceException,
@@ -176,7 +186,7 @@
         }
 
         if(null == listener){
-            GPIOPortEventHandler.getInstance().removeEventListener(this);
+            EventQueueManager.getInstance().removeEventListener(GPIOPort.class, 0, this);
             if(null != this.listener){
                 try {
                     stopNoti0();
@@ -186,18 +196,16 @@
             this.listener = null;
 
         }else if (null == this.listener) {
-            GPIOPortEventHandler.getInstance().setEventListener(this, listener);
             this.listener = listener;
             try {
                 startNoti0();
             } catch (IOException ex) {
-                GPIOPortEventHandler.getInstance().removeEventListener(this);
                 this.listener = null;
                 throw new UnsupportedOperationException (
                     ExceptionMessage.format(ExceptionMessage.GPIO_CANNOT_START_NOTIFICATION)
                 );
             }
-
+            EventQueueManager.getInstance().setEventListener(GPIOPort.class, 0, this);
         }else{
             throw new IllegalStateException (
                 ExceptionMessage.format(ExceptionMessage.GPIO_LISTENER_ALREADY_ASSIGNED)
@@ -213,16 +221,19 @@
                 }catch(IOException ex){
                 }
             }
-            GPIOPortConfig cfg = dscr.getConfiguration();
-            for(GPIOPin pin: cfg.getPins()) {
-                ((GPIOPinFake)pin).closeInternal();
+            for(GPIOPinFake pin: pins) {
+               pin.closeInternal();
             }
             // for DM.register: nullifying to remove redundant information from serialized class
-            assignPins0(cfg, null);
             super.close();
         }
     }
 
+    @Override
+    public GPIOPin[] getPins() {
+        return pins;
+    }
+
     @Local(DontRemoveFields = {
         "com.oracle.dio.impl.Handle.unlock_func_ptr",
         "com.oracle.dio.impl.Handle.native_handle",
@@ -268,9 +279,5 @@
     })
     private native void stopNoti0() throws IOException;
 
-    @Local(DontRemoveFields = {
-        "jdk.dio.gpio.GPIOPortConfig.pins",
-    })
-    private native void assignPins0(GPIOPortConfig cfg, GPIOPin[] pins);
 }
 
--- a/src/share/classes/com/oracle/dio/i2cbus/impl/I2CCombinedMessage.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/i2cbus/impl/I2CCombinedMessage.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,8 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
 
 import com.oracle.dio.utils.ExceptionMessage;
 import com.oracle.dio.utils.Logging;
@@ -43,12 +45,14 @@
     int messageBus = DeviceConfig.DEFAULT;
     boolean isAlreadyTransferedOnce;
     int rxMessageCount;
+    int stopConditionIndex = -1;
 
     private class Message<P extends I2CDevice> {
         public P device;
         public ByteBuffer buf;
         public int skip;
         public boolean isRx;
+
         public Message(P device, ByteBuffer buf, int skip, boolean isRx) {
             this.device = device;
             this.buf = buf;
@@ -57,48 +61,58 @@
         }
     }
 
-    void check(Message message) throws ClosedDeviceException {
+    void validateAndAppend(Message message) throws ClosedDeviceException {
+        synchronized (messageList) {
+            if (isAlreadyTransferedOnce) {
+                throw new IllegalStateException(
+                        ExceptionMessage.format(ExceptionMessage.I2CBUS_ALREADY_TRANSFERRED_MESSAGE)
+                );
+            }
 
-        if (isAlreadyTransferedOnce) {
-            throw new IllegalStateException(
-                ExceptionMessage.format(ExceptionMessage.I2CBUS_ALREADY_TRANSFERRED_MESSAGE)
-            );
-        }
+            if (0 > message.skip) {
+                throw new IllegalArgumentException(
+                        ExceptionMessage.format(ExceptionMessage.I2CBUS_NEGATIVE_SKIP_ARG)
+                );
+            }
 
-        if (null == message.buf) {
-            throw new NullPointerException(
-                ExceptionMessage.format(ExceptionMessage.I2CBUS_NULL_BUFFER)
-            );
-        }
-
-        if (0 > message.skip) {
-            throw new IllegalArgumentException(
-                ExceptionMessage.format(ExceptionMessage.I2CBUS_NEGATIVE_SKIP_ARG)
-            );
-        }
-
-        if (!message.device.isOpen()) {
-            throw new ClosedDeviceException();
-        }
+            if (!message.device.isOpen()) {
+                throw new ClosedDeviceException();
+            }
 
         /*  check that can get '-1' here */
-        int busNumber = ((I2CDeviceConfig) message.device.getDescriptor().getConfiguration()).getControllerNumber();
+            int busNumber = ((I2CDeviceConfig) message.device.getDescriptor().getConfiguration()).getControllerNumber();
 
-        if (DeviceConfig.DEFAULT == messageBus) {
-            messageBus = busNumber;
-        } else {
-            if (messageBus != busNumber) {
-                throw new IllegalArgumentException(
-                    ExceptionMessage.format(ExceptionMessage.I2CBUS_DIFFERENT_BUS_SLAVE_OPERATION)
-                );
+            if (DeviceConfig.DEFAULT == messageBus) {
+                messageBus = busNumber;
+            } else {
+                if (messageBus != busNumber) {
+                    throw new IllegalArgumentException(
+                            ExceptionMessage.format(ExceptionMessage.I2CBUS_DIFFERENT_BUS_SLAVE_OPERATION)
+                    );
+                }
             }
-        }
 
-        for (int i = 0; i < messageList.size(); i++) {
-            if (messageList.get(i).buf == message.buf) {
-                throw new IllegalArgumentException(
-                    ExceptionMessage.format(ExceptionMessage.I2CBUS_BUFFER_GIVEN_TWICE)
-                );
+            // null check and mark for stopCondition.
+            if (message.buf.remaining() != 0  || message.skip > 0) {
+                boolean alreadyAppended = false;
+                for (Message<I2CSlaveImpl> already : messageList) {
+                    if (already.buf == message.buf) {
+                        alreadyAppended = true;
+                        break;
+                    }
+                }
+
+                // if the buffer is used several times, stop condition must occur only once,
+                // on first use,
+                if (!alreadyAppended)
+                    stopConditionIndex = messageList.size();
+            }
+
+
+            messageList.add(message);
+
+            if (message.isRx) {
+                ++rxMessageCount;
             }
         }
     }
@@ -113,28 +127,17 @@
      * Appends a read message/operation from the provided I2C slave device. Reads up to
      * {@code rwBuf.remaining()} bytes of data from this slave device into the buffer {@code rxBuf}.
      *
-     * @param slave
-     *            the I2C slave device to read from.
-     * @param rxBuf
-     *            the buffer into which the data is read.
+     * @param slave the I2C slave device to read from.
+     * @param rxBuf the buffer into which the data is read.
      * @return a reference to this {@code I2CCombinedMessage} object.
-     * @throws NullPointerException
-     *             If {@code rxBuf} is {@code null}.
-     * @throws IllegalStateException
-     *             if this message has already been transferred once.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     * @throws IllegalArgumentException
-     *             if appending the read operation to a slave on a different bus.
+     * @throws NullPointerException     If {@code rxBuf} is {@code null}.
+     * @throws IllegalStateException    if this message has already been transferred once.
+     * @throws ClosedDeviceException    if the device has been closed.
+     * @throws IllegalArgumentException if appending the read operation to a slave on a different bus.
      */
     public I2CCombinedMessage appendRead(I2CDevice slave, ByteBuffer rxBuf)
             throws ClosedDeviceException {
-        Message message = new Message(slave, rxBuf, 0, true);
-        synchronized (this) {
-            check(message);
-            messageList.add(message);
-            ++rxMessageCount;
-        }
+        validateAndAppend(new Message(slave, rxBuf, 0, true));
         return this;
     }
 
@@ -143,34 +146,21 @@
      * {@code rwBuf.remaining()} bytes of data from this slave device into the buffer skipping
      * {@code rxBuf} the first {@code rxSkip} bytes read.
      *
-     * @param slave
-     *            the I2C slave device to read from.
-     * @param rxSkip
-     *            the number of read bytes that must be ignored/skipped before filling in the
-     *            {@code rxBuf} buffer.
-     * @param rxBuf
-     *            the buffer into which the data is read.
+     * @param slave  the I2C slave device to read from.
+     * @param rxSkip the number of read bytes that must be ignored/skipped before filling in the
+     *               {@code rxBuf} buffer.
+     * @param rxBuf  the buffer into which the data is read.
      * @return a reference to this {@code I2CCombinedMessage} object.
-     * @throws IOException
-     *             if some other I/O error occurs.
-     * @throws NullPointerException
-     *             If {@code rxBuf} is {@code null}.
-     * @throws IllegalStateException
-     *             if this message has already been transferred once.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     * @throws IllegalArgumentException
-     *             if {@code rxSkip} is negative or if appending the read operation to a slave on a
-     *             different bus.
+     * @throws IOException              if some other I/O error occurs.
+     * @throws NullPointerException     If {@code rxBuf} is {@code null}.
+     * @throws IllegalStateException    if this message has already been transferred once.
+     * @throws ClosedDeviceException    if the device has been closed.
+     * @throws IllegalArgumentException if {@code rxSkip} is negative or if appending the read operation to a slave on a
+     *                                  different bus.
      */
     public I2CCombinedMessage appendRead(I2CDevice slave, int rxSkip,
-            ByteBuffer rxBuf) throws IOException, ClosedDeviceException {
-        Message message = new Message(slave, rxBuf, rxSkip, true);
-        synchronized (this) {
-            check(message);
-            messageList.add(message);
-            ++rxMessageCount;
-        }
+                                         ByteBuffer rxBuf) throws IOException, ClosedDeviceException {
+        validateAndAppend(new Message(slave, rxBuf, rxSkip, true));
         return this;
     }
 
@@ -178,32 +168,20 @@
      * Appends a write message/operation from the provided I2C slave device. Writes to this slave
      * device {@code txBuff.remaining()} bytes from the buffer {@code txBuf}.
      *
-     * @param slave
-     *            the I2C slave device to write to.
-     * @param txBuf
-     *            the buffer containing the bytes to write.
+     * @param slave the I2C slave device to write to.
+     * @param txBuf the buffer containing the bytes to write.
      * @return a reference to this {@code I2CCombinedMessage} object.
-     * @throws IOException
-     *             if some other I/O error occurs.
-     * @throws NullPointerException
-     *             If {@code txBuf} is {@code null}.
-     * @throws IndexOutOfBoundsException
-     *             {@code txOff} or {@code txLen} points or results in pointing outside
-     *             {@code txBuf}.
-     * @throws IllegalStateException
-     *             if this message has already been transferred once.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     * @throws IllegalArgumentException
-     *             if appending the write operation to a slave on a different bus.
+     * @throws IOException               if some other I/O error occurs.
+     * @throws NullPointerException      If {@code txBuf} is {@code null}.
+     * @throws IndexOutOfBoundsException {@code txOff} or {@code txLen} points or results in pointing outside
+     *                                   {@code txBuf}.
+     * @throws IllegalStateException     if this message has already been transferred once.
+     * @throws ClosedDeviceException     if the device has been closed.
+     * @throws IllegalArgumentException  if appending the write operation to a slave on a different bus.
      */
     public I2CCombinedMessage appendWrite(I2CDevice slave, ByteBuffer txBuf) throws IOException,
             ClosedDeviceException {
-        Message message = new Message(slave, txBuf, 0, false);
-        synchronized (this) {
-            check(message);
-            messageList.add(message);
-        }
+        validateAndAppend(new Message(slave, txBuf, 0, false));
         return this;
     }
 
@@ -211,66 +189,67 @@
      * Transfers this combined message. This will result in each of the contained
      * messages/operations to be sent/executed in the same order they have been appended to this
      * combined message.
-     * <p />
+     * <p>
      * Once transfer no additional operation can be appended anymore to this combined message. Any
      * such attempt will result in a {@link IllegalStateException} to be thrown. <br />
      * This combined message can be transferred several times.
      *
      * @return an array containing the number of bytes read for each of the read operations of this
-     *         combined message; the results of each read operations appear in the very same order
-     *         the read operations have been appended to this combined message.
-     * @throws IOException
-     *             if an I/O error occurred
-     * @throws UnavailableDeviceException
-     *             if this device is not currently available - such as it is locked by another
-     *             application.
-     * @throws ClosedDeviceException
-     *             if any of the targeted devices is not currently available (has been closed).
+     * combined message; the results of each read operations appear in the very same order
+     * the read operations have been appended to this combined message.
+     * @throws IOException                if an I/O error occurred
+     * @throws UnavailableDeviceException if this device is not currently available - such as it is locked by another
+     *                                    application.
+     * @throws ClosedDeviceException      if any of the targeted devices is not currently available (has been closed).
      */
     public int[] transfer() throws IOException, UnavailableDeviceException, ClosedDeviceException {
         int bytesRead[];
-        synchronized (this) {
+        synchronized (messageList) {
             /* Forbid adding more messages to this combined message */
             isAlreadyTransferedOnce = true;
             if (0 == messageList.size()) {
-                notifyAll();
                 return null;
             }
 
             bytesRead = new int[rxMessageCount];
             int bytesReadIdx = 0;
 
-            try {
-                final int size = messageList.size();
-                if (1 == size) {
-                    Message message = messageList.get(0);
+            final int size = messageList.size();
+
+            if (1 == size) {
+                Message message = messageList.get(0);
+                int skip = (message.isRx) ? message.skip : -1;
+                Logging.reportInformation(ExceptionMessage.format(ExceptionMessage.I2CBUS_LAST_MESSAGE));
+                int res = ((I2CSlaveImpl) message.device).transfer(I2CSlaveImpl.I2C_REGULAR, skip, message.buf);
+                if (rxMessageCount > 0) {
+                    bytesRead[0] = res;
+                }
+            } else {
+                int flag = I2CSlaveImpl.I2C_COMBINED_START;
+                Logging.reportInformation(ExceptionMessage.format(ExceptionMessage.I2CBUS_FIRST_MESSAGE));
+                Set<I2CSlaveImpl> slavesInUse = new HashSet<I2CSlaveImpl>();
+
+                for (int i = 0; i < messageList.size(); i++) {
+                    Message message = messageList.get(i);
+                    I2CSlaveImpl slave = (I2CSlaveImpl) message.device;
+                    slavesInUse.add(slave);
                     int skip = (message.isRx) ? message.skip : -1;
-                    Logging.reportInformation(ExceptionMessage.format(ExceptionMessage.I2CBUS_LAST_MESSAGE));
-                    int res = ((I2CSlaveImpl)message.device).transfer(I2CSlaveImpl.I2C_REGULAR, skip, message.buf);
-                    if (rxMessageCount > 0) {
-                        bytesRead[0] = res;
+                    if (i == stopConditionIndex) {
+                        Logging.reportInformation(ExceptionMessage.format(ExceptionMessage.I2CBUS_LAST_MESSAGE));
+                        flag = I2CSlaveImpl.I2C_COMBINED_END;
                     }
-                } else {
-                    int flag = I2CSlaveImpl.I2C_COMBINED_START;
-                    Logging.reportInformation(ExceptionMessage.format(ExceptionMessage.I2CBUS_FIRST_MESSAGE));
-                    for (int i = 0; i < messageList.size(); i++) {
-                        Message message = messageList.get(i);
-                        int skip = (message.isRx) ? message.skip : -1;
-                        if(i == messageList.size() - 1) {
-                            Logging.reportInformation(ExceptionMessage.format(ExceptionMessage.I2CBUS_LAST_MESSAGE));
-                            flag = I2CSlaveImpl.I2C_COMBINED_END;
-                        }
-                        int res = ((I2CSlaveImpl)message.device).transfer(flag, skip, message.buf);
-                        if (message.isRx) {
-                            bytesRead[bytesReadIdx++] = res;
-                        }
-                        flag = I2CSlaveImpl.I2C_COMBINED_BODY;
+
+                    int res = slave.transfer(flag, skip, message.buf);
+                    if (message.isRx) {
+                        bytesRead[bytesReadIdx++] = res;
                     }
+                    flag = I2CSlaveImpl.I2C_COMBINED_BODY;
                 }
-            } finally {
-                notifyAll();
+
+                for (I2CSlaveImpl usedSlave : slavesInUse) {
+                    usedSlave.applyDelayedConversions();
+                }
             }
-
         }
         return bytesRead;
     }
--- a/src/share/classes/com/oracle/dio/i2cbus/impl/I2CSlaveImpl.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/i2cbus/impl/I2CSlaveImpl.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,8 @@
 import java.io.IOException;
 import java.nio.*;
 import java.security.AccessController;
+import java.util.LinkedList;
+import java.util.List;
 
 import com.oracle.dio.power.impl.PowerManagedBase;
 import com.oracle.dio.utils.Constants;
@@ -51,17 +53,17 @@
             DeviceNotFoundException, InvalidDeviceConfigException {
         super(dscr, mode);
 
+        I2CPermission permission = new I2CPermission(getSecurityName());
+        AccessController.checkPermission(permission);
+
         I2CDeviceConfig cfg = dscr.getConfiguration();
 
         if (cfg.getControllerName() != null) {
             throw new InvalidDeviceConfigException(
-                ExceptionMessage.format(ExceptionMessage.DEVICE_OPEN_WITH_DEVICENAME_UNSUPPORTED)
+                    ExceptionMessage.format(ExceptionMessage.DEVICE_OPEN_WITH_DEVICENAME_UNSUPPORTED)
             );
         }
 
-        I2CPermission permission = new I2CPermission(getSecurityName());
-        AccessController.checkPermission(permission);
-
         open0(cfg, mode == DeviceManager.EXCLUSIVE);
 
         initPowerManagement();
@@ -69,24 +71,24 @@
 
     public Bus getBus() throws IOException {
         return new Bus() {
-                public jdk.dio.i2cbus.I2CCombinedMessage createCombinedMessage() {
-                    return new I2CCombinedMessage();
-                }
-            };
+            public jdk.dio.i2cbus.I2CCombinedMessage createCombinedMessage() {
+                return new I2CCombinedMessage();
+            }
+        };
     }
 
     private String getSecurityName() {
         I2CDeviceConfig cfg = dscr.getConfiguration();
         String securityName = (DeviceConfig.DEFAULT == cfg.getControllerNumber()) ?
-            "" : String.valueOf(cfg.getControllerNumber());
+                "" : String.valueOf(cfg.getControllerNumber());
         securityName = (DeviceConfig.DEFAULT == cfg.getAddress()) ?
-            securityName : securityName + ":" + cfg.getAddress();
+                securityName : securityName + ":" + cfg.getAddress();
         return securityName;
     }
 
     protected void checkPowerPermission() {
         AccessController.checkPermission(new I2CPermission(getSecurityName(),
-                                         DevicePermission.POWER_MANAGE));
+                DevicePermission.POWER_MANAGE));
     }
 
     private void doCheck(int skip, ByteBuffer buf) {
@@ -110,7 +112,7 @@
     }
 
     @Override
-    public  int read() throws IOException,
+    public int read() throws IOException,
             UnavailableDeviceException, ClosedDeviceException {
         ByteBuffer dst = ByteBuffer.allocateDirect(1);
         read(dst);
@@ -118,13 +120,13 @@
     }
 
     @Override
-    public  int read(ByteBuffer dst) throws IOException,
+    public int read(ByteBuffer dst) throws IOException,
             UnavailableDeviceException, ClosedDeviceException {
         return read(0, dst);
     }
 
     @Override
-    public  int read(int skip, ByteBuffer dst) throws IOException,
+    public int read(int skip, ByteBuffer dst) throws IOException,
             UnavailableDeviceException, ClosedDeviceException {
 
         doCheck(skip, dst);
@@ -133,15 +135,15 @@
     }
 
     @Override
-    public  int read(int subaddress, int subaddressSize,
-            ByteBuffer dst) throws IOException, UnavailableDeviceException,
+    public int read(int subaddress, int subaddressSize,
+                    ByteBuffer dst) throws IOException, UnavailableDeviceException,
             ClosedDeviceException {
         return read(subaddress, subaddressSize, 0, dst);
     }
 
     @Override
-    public  int read(int subaddress, int subaddressSize, int skip,
-            ByteBuffer dst) throws IOException, UnavailableDeviceException,
+    public int read(int subaddress, int subaddressSize, int skip,
+                    ByteBuffer dst) throws IOException, UnavailableDeviceException,
             ClosedDeviceException {
 
         if (subaddressSize <= 0 || subaddressSize > 4 || subaddress < 0)
@@ -152,7 +154,7 @@
         ByteBuffer tmp = ByteBuffer.wrap(new byte[4/*sizeof(int)*/]);
         tmp.order(ByteOrder.BIG_ENDIAN);
         tmp.putInt(subaddress);
-        tmp.position(4-subaddressSize);
+        tmp.position(4 - subaddressSize);
         I2CCombinedMessage msg = new I2CCombinedMessage();
         msg.appendWrite(this, tmp);
         msg.appendRead(this, skip, dst);
@@ -171,14 +173,14 @@
     public void write(int srcData) throws IOException,
             UnavailableDeviceException, ClosedDeviceException {
         ByteBuffer dst = ByteBuffer.allocateDirect(1);
-        dst.put((byte)srcData);
+        dst.put((byte) srcData);
         dst.flip();
         write(dst);
     }
 
     @Override
     public int write(int subaddress, int subaddressSize,
-            ByteBuffer src) throws IOException, UnavailableDeviceException,
+                     ByteBuffer src) throws IOException, UnavailableDeviceException,
             ClosedDeviceException {
         boolean callEnd = false;
 
@@ -192,29 +194,24 @@
         tmp.order(ByteOrder.BIG_ENDIAN);
         tmp.putInt(subaddress);
         tmp.put(src);
-        tmp.position(4-subaddressSize);
+        tmp.position(4 - subaddressSize);
         return write(tmp) - subaddressSize;
     }
 
     /**
      * @throws IllegalStateException if the bus is occupied for
-     *        communication with other peripheral or with other
-     *        transaction
+     *                               communication with other peripheral or with other
+     *                               transaction
      */
-    int transfer(int flag, int skip, ByteBuffer buf)  throws
+    int transfer(int flag, int skip, ByteBuffer appBuffer) throws
             UnavailableDeviceException, ClosedDeviceException, IOException {
         int ret = 0;
-        ByteBuffer toSend;
 
-        if (!buf.hasRemaining()) {
+        if (!appBuffer.hasRemaining() && skip <= 0) {
             return 0;
         }
 
-        if (skip > 0) {
-            toSend = ByteBuffer.allocateDirect(buf.remaining() + skip);
-        } else {
-            toSend = convert(buf, null);
-        }
+        ByteBuffer direct = toDirect(skip, appBuffer);
 
         checkPowerState();
         // if driver supports combined message
@@ -222,21 +219,64 @@
         // immediately if single shot is trying to interrupt ongoing I2C combined
         // message.
         // if not, then it is pipelining transfer request.
-        synchronized(handle) {
+        synchronized (handle) {
             try {
                 conditionalLock();
-                ret = transfer0(skip < 0, toSend, flag);
+                ret = transfer0(skip < 0, direct, flag);
             } finally {
                 conditionalUnlock();
             }
         }
 
-        toSend.limit(ret);
+        direct.limit(ret);
 
         if (skip > 0) {
-            if (ret > skip) {
+            ret = (ret > skip) ? ret - skip : 0;
+        }
+
+        BuffersMap conversion = new BuffersMap(skip, appBuffer, ret, direct);
+
+        return flag == I2CSlaveImpl.I2C_REGULAR ?
+                restoreFromDirect(conversion) :
+                addDelayedConversion(conversion);
+    }
+
+    static class BuffersMap {
+        int skip, ret;
+        ByteBuffer direct, nonDirect;
+
+        BuffersMap(int skip, ByteBuffer nonDirect, int ret, ByteBuffer direct) {
+            this.skip = skip;
+            this.ret = ret;
+            this.direct = direct;
+            this.nonDirect = nonDirect;
+        }
+    }
+
+    private List<BuffersMap> delayedConversions = new LinkedList<BuffersMap>();
+
+    private int addDelayedConversion(BuffersMap conversion) {
+        delayedConversions.add(conversion);
+        return conversion.ret;
+    }
+
+    void applyDelayedConversions() {
+        for (BuffersMap delayedConversion : delayedConversions) {
+            restoreFromDirect(delayedConversion);
+        }
+
+        delayedConversions.clear();
+    }
+
+    private int restoreFromDirect(BuffersMap conversion) {
+        ByteBuffer toSend = conversion.direct;
+        int ret = conversion.ret;
+        int skip = conversion.skip;
+        ByteBuffer buf = conversion.nonDirect;
+
+        if (skip > 0) {
+            if (ret > 0) {
                 // need to count only bytes transfered to recv buffer
-                ret -= skip;
                 toSend.position(skip);
                 try {
                     buf.put(toSend);
@@ -246,12 +286,10 @@
                     // position throws IllegalArgumentException
                     Logging.reportError(ExceptionMessage.format(ExceptionMessage.BUFFER_IS_MODIFIED));
                 }
-            } else {
-                ret = 0;
             }
         } else {
-            try{
-                // if write just update buffer postion
+            try {
+                // if write just update buffer position
                 if (skip < 0) {
                     buf.position(buf.position() + ret);
                 } else {
@@ -269,20 +307,35 @@
         return ret;
     }
 
+    private ByteBuffer toDirect(int skip, ByteBuffer buf) {
+        ByteBuffer toSend;
+        if (skip > 0) {
+            toSend = ByteBuffer.allocateDirect(buf.remaining() + skip);
+        } else {
+            toSend = convert(buf, null);
+        }
+        return toSend;
+    }
+
     protected synchronized int getGrpID() {
         return getGrpID0();
     }
 
+    @Override
+    public ByteBuffer prepareBuffer(ByteBuffer buffer, int size) throws IOException, ClosedDeviceException {
+        return (ByteBuffer) super.prepareBufferInt(buffer, size);
+    }
+
     @Local(DontRemoveFields = {
-        "jdk.dio.i2cbus.I2CDeviceConfig.controllerNumber",
-        "jdk.dio.i2cbus.I2CDeviceConfig.clockFrequency",
-        "jdk.dio.i2cbus.I2CDeviceConfig.addressSize",
-        "jdk.dio.i2cbus.I2CDeviceConfig.address",
-        "com.oracle.dio.impl.Handle.unlock_func_ptr",
-        "com.oracle.dio.impl.Handle.native_handle",
-        "com.oracle.dio.impl.Handle.lock_func_ptr",
-        "com.oracle.dio.impl.Handle.close_func_ptr",
-        "com.oracle.dio.impl.AbstractPeripheral.handle",
+            "jdk.dio.i2cbus.I2CDeviceConfig.controllerNumber",
+            "jdk.dio.i2cbus.I2CDeviceConfig.clockFrequency",
+            "jdk.dio.i2cbus.I2CDeviceConfig.addressSize",
+            "jdk.dio.i2cbus.I2CDeviceConfig.address",
+            "com.oracle.dio.impl.Handle.unlock_func_ptr",
+            "com.oracle.dio.impl.Handle.native_handle",
+            "com.oracle.dio.impl.Handle.lock_func_ptr",
+            "com.oracle.dio.impl.Handle.close_func_ptr",
+            "com.oracle.dio.impl.AbstractPeripheral.handle",
     })
     private native void open0(Object config, boolean isExclusive);
 
@@ -296,23 +349,22 @@
      *              {@code false} for read
      * @param dst   the buffer that holds the data or to store data
      *              to.
-     *
      * @return number of bytes was transfered over the bus.
      */
     @Local(DontRemoveFields = {
-        "java.nio.Buffer.position",
-        "java.nio.Buffer.limit",
-        "java.nio.Buffer.flags",
-        "java.nio.Buffer.data",
-        "java.nio.Buffer.arrayOffset",
-        "com.oracle.dio.impl.Handle.native_handle",
-        "com.oracle.dio.impl.AbstractPeripheral.handle",
+            "java.nio.Buffer.position",
+            "java.nio.Buffer.limit",
+            "java.nio.Buffer.flags",
+            "java.nio.Buffer.data",
+            "java.nio.Buffer.arrayOffset",
+            "com.oracle.dio.impl.Handle.native_handle",
+            "com.oracle.dio.impl.AbstractPeripheral.handle",
     })
     private native int transfer0(boolean write, ByteBuffer dst, int flag);
 
     @Local(DontRemoveFields = {
-        "com.oracle.dio.impl.Handle.native_handle",
-        "com.oracle.dio.impl.AbstractPeripheral.handle",
+            "com.oracle.dio.impl.Handle.native_handle",
+            "com.oracle.dio.impl.AbstractPeripheral.handle",
     })
     private native int getGrpID0();
 }
--- a/src/share/classes/com/oracle/dio/impl/AbstractPeripheral.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/impl/AbstractPeripheral.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,16 +25,19 @@
 
 package com.oracle.dio.impl;
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import com.oracle.dio.utils.Constants;
+import com.oracle.dio.utils.ExceptionMessage;
 
 import jdk.dio.ClosedDeviceException;
 import jdk.dio.Device;
 import jdk.dio.DeviceDescriptor;
+import jdk.dio.DeviceEvent;
 import jdk.dio.DeviceManager;
 import jdk.dio.UnavailableDeviceException;
-import com.oracle.dio.utils.Constants;
-import com.oracle.dio.utils.ExceptionMessage;
-import java.nio.Buffer;
 
 /* It is recommended to synchronize subclass native operation on {@code handle} lock.
    @see {@link #unlock()} for the reason
@@ -151,7 +154,7 @@
         called after native call on Buffer.clice() returns,
         and necessary shift original buffers position
     */
-    protected void shiftBufferPosition(Buffer buff, int newExpectedPosition) throws IOException {
+    protected void shiftBufferPosition(Buffer buff, int newExpectedPosition)  {
         synchronized (buff){
             if (newExpectedPosition > buff.position()){
                 //try/catch because of possible not synchronized change of buff in another thread
@@ -188,6 +191,23 @@
         return tmp;
     }
 
+    /* Ensures <code>buffer</code> is not null and not empty*/
+    protected void checkBuffer(Buffer buffer) {
+        if (0 == buffer.capacity()) {
+            throw new IllegalArgumentException(ExceptionMessage.format(ExceptionMessage.ZERO_CAPACITY_BUFFER));
+        }
+    }
+
+    /* dummy function to pass TCK */
+    protected Buffer prepareBufferInt(Buffer buffer, int size) {
+        // null check
+        buffer.limit();
+        if (0 > size) {
+            throw new IllegalArgumentException();
+        }
+        return null;
+    }
+
     /** Tries to lock given pripheral. Waits <code>timeout</code>
      *  time if device is locked by other application.
      *
@@ -200,4 +220,17 @@
      * Release peripheral for shared access
      */
     protected  void unlock0() { handle.unlock(); }
+
+    @Override
+    public ByteOrder getByteOrder() throws IOException, UnavailableDeviceException, ClosedDeviceException {
+        return ByteOrder.LITTLE_ENDIAN;
+    }
+
+    /* --------- functions to access from EventQueueManager --------------- */
+    /* Need to be overriden at childs */
+    protected void processDeviceEvent(int type, DeviceEvent event) {
+    }
+
+    protected void processNativeEvent(int type, int... data) {
+    }
 }
--- a/src/share/classes/com/oracle/dio/impl/PeripheralDescriptorImpl.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/impl/PeripheralDescriptorImpl.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,13 +24,20 @@
  */
 
 package com.oracle.dio.impl;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Objects;
 import java.util.Set;
 
+import com.oracle.dio.utils.Constants;
+import com.oracle.dio.utils.Logging;
+import com.oracle.dio.impl.Platform;
+
 import jdk.dio.Device;
 import jdk.dio.DeviceConfig;
 import jdk.dio.DeviceDescriptor;
-import com.oracle.dio.utils.Constants;
-import com.oracle.dio.utils.Logging;
+import jdk.dio.spi.DeviceProvider;
 
 import romizer.*;
 
@@ -42,23 +49,27 @@
  */
 @SerializeMe
 @DontRenameClass
-public class PeripheralDescriptorImpl<C extends DeviceConfig<T>, T extends Device<? super T>> implements DeviceDescriptor<T> {
+public final class PeripheralDescriptorImpl<T extends Device<? super T>> implements DeviceDescriptor<T> {
 
-    private C config;
+    private Object config;
     private String clazz;
     private int id = DeviceDescriptor.UNDEFINED_ID;
     private String name;
     private String[] props;
+    private String providerClazz;
 
+    // need for serializator
     public PeripheralDescriptorImpl() {
     }
 
-    public PeripheralDescriptorImpl(int id, String name, C config, Class<T> intf, String[] props) {
+    public PeripheralDescriptorImpl(int id, String name, DeviceConfig config, Class<T> intf, String[] props) {
+        Objects.requireNonNull(config);
         this.config = config;
-        if (null == config) {
-            throw new NullPointerException();
+        // see DeviceManager.openWithConfig where intf may be null
+        // however register/open-with-name/open-with-id always provides correct intf
+        if (null != intf) {
+            this.clazz = intf.getName();
         }
-        this.clazz = intf.getName();
         this.id = id;
         this.name = name;
         this.props = (props == null) ? props : props.clone();
@@ -66,16 +77,21 @@
     }
 
     @Override
-    public C getConfiguration() {
-        return config;
+    public <C extends DeviceConfig<? super T>> C getConfiguration() {
+        if (config instanceof DeviceConfig) {
+            return (C)config;
+        }
+        return null;
     }
 
     @Override
     public Class<T> getInterface() {
-        try {
-            return (Class<T>)Class.forName(clazz);
-        } catch (ClassNotFoundException | RuntimeException e) {
-            Logging.reportError("Can't restore class at PeripheralDescriptorImpl");
+        if (null != clazz) {
+            try {
+                return (Class<T>)Class.forName(clazz);
+            } catch (ClassNotFoundException | RuntimeException e) {
+                Logging.reportError("Can't restore class at PeripheralDescriptorImpl");
+            }
         }
         return null;
     }
@@ -94,5 +110,45 @@
     public String[] getProperties() {
         return (props == null) ? props : props.clone();
     }
+
+    public void setDeviceProvider(DeviceProvider provider) {
+        providerClazz = provider.getClass().getName();
+    }
+
+    public void prepareForSerilization() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        if (! (config instanceof byte[]) ) {
+            if (null != providerClazz) {
+                ((DeviceConfig)config).serialize(baos);
+            } else {
+                Platform.serialize(config, baos);
+            }
+            baos.close();
+            config = baos.toByteArray();
+        }
+    }
+
+    public void recoverFromSerialization() {
+        if (config instanceof byte[]) {
+            ByteArrayInputStream bais = new ByteArrayInputStream((byte[])config);
+            try {
+                config = Platform.deserialize(bais);
+            } catch (IOException e1) {
+                Logging.reportInformation("Config is custom DeviceConfig child");
+                try {
+                    bais.reset();
+                    DeviceProvider<T> provider = (DeviceProvider)Class.forName(providerClazz).newInstance();
+                    config = provider.deserialize(bais);
+                } catch (Exception e2) {
+                    Logging.reportError("Can't restore config object");
+                }
+            }
+        }
+    }
+
+    public void setNewID(int new_id) {
+        id = new_id;
+    }
+
 }
 
--- a/src/share/classes/com/oracle/dio/impl/Transaction.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/impl/Transaction.java	Fri Sep 09 13:20:20 2016 +0300
@@ -36,10 +36,6 @@
  */
 public abstract class Transaction<P extends Device<P>> extends PowerManagedBase<P>{
 
-    public static final int REGULAR_MESSAGE = -1;
-
-    protected int transaction = REGULAR_MESSAGE;
-
     protected Transaction(DeviceDescriptor<P> dscr, int mode) {
         super(dscr, mode);
     }
--- a/src/share/classes/com/oracle/dio/power/impl/PowerManagedBase.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/power/impl/PowerManagedBase.java	Fri Sep 09 13:20:20 2016 +0300
@@ -47,15 +47,7 @@
     final protected void clearPowerManagement() {
     }
 
-    protected abstract void checkPowerPermission();
-
-    protected void checkPowerState() throws IOException, ClosedDeviceException {
+    final protected void checkPowerState() throws IOException, ClosedDeviceException {
         checkOpen();
     }
-
-    public synchronized void close() throws IOException {
-        if (isOpen()) {
-            super.close();
-        }
-    }
 }
--- a/src/share/classes/com/oracle/dio/registry/Registry.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/registry/Registry.java	Fri Sep 09 13:20:20 2016 +0300
@@ -29,6 +29,12 @@
 import java.security.AccessController;
 import java.util.Hashtable;
 import java.util.Iterator;
+import java.util.Random;
+
+import com.oracle.dio.impl.PeripheralDescriptorImpl;
+import com.oracle.dio.utils.ExceptionMessage;
+import com.oracle.dio.utils.PrivilegeController;
+import com.oracle.dio.utils.PrivilegedAction;
 
 import jdk.dio.Device;
 import jdk.dio.DeviceAlreadyExistsException;
@@ -38,6 +44,7 @@
 import jdk.dio.DeviceMgmtPermission;
 import jdk.dio.DeviceNotFoundException;
 import jdk.dio.InvalidDeviceConfigException;
+import jdk.dio.UnavailableDeviceException;
 import jdk.dio.UnsupportedDeviceTypeException;
 /**
  * Device configuration registry.
@@ -85,6 +92,15 @@
      */
     public abstract Iterator<DeviceDescriptor<? super T>> get(String name, Class<T> intf, String... properties);
 
+    public static void checkID(int ID) throws IllegalArgumentException {
+        if (ID < 0) {
+            throw new IllegalArgumentException(
+                ExceptionMessage.format(ExceptionMessage.DEVICE_NEGATIVE_ID)
+            );
+        }
+    }
+
+
     /**
      *
      * @return new Periprheal ID
@@ -93,11 +109,83 @@
      * @see jdk.dio.DeviceManager#register(int,
      *      Class, DeviceConfig, String, String...)
      */
-    public abstract void register(int id, Class<T> intf,
-                                                        DeviceConfig<? super T> config,
-                                                        String name,
-                                                        String... properties)
-    throws UnsupportedOperationException, IOException;
+    public int register(PeripheralDescriptorImpl<? super T> d)
+    throws UnsupportedOperationException, IOException {
+        checkPermission(d.getName(), d.getID(), DeviceMgmtPermission.REGISTER);
+
+        if (!Registry.canRegister) {
+            throw new UnsupportedOperationException();
+        }
+
+        if (d.getID() < DeviceManager.UNSPECIFIED_ID) {
+            throw new IllegalArgumentException(
+                ExceptionMessage.format(ExceptionMessage.DEVICE_INVALID_ID)
+            );
+        }
+
+        int new_id = checkConfig(d);
+
+        return new_id;
+    }
+
+    private static int checkConfig(final DeviceDescriptor d)
+    throws IOException, UnsupportedDeviceTypeException, InvalidDeviceConfigException, DeviceNotFoundException, DeviceAlreadyExistsException {
+
+        int new_id = PrivilegeController.doPrivileged(new PrivilegedAction<Integer>() {
+                public Integer run() throws IOException {
+                    Random rnd = new Random();
+                    int new_id = d.getID();
+
+                    do {
+                        if (d.getID() == DeviceManager.UNSPECIFIED_ID) {
+                            //  verify generated ID
+                            new_id = rnd.nextInt();
+                            if (new_id < 1) {
+                                continue;
+                            }
+                        }
+                        try {
+                            Device p = DeviceManager.open(new_id);
+                            p.close();
+                        } catch (DeviceNotFoundException pnfe1) {
+                            // this is the only right way to break "while" condition
+                            break;
+                        } catch (UnavailableDeviceException pnae1) {}
+                        if (d.getID()  != DeviceManager.UNSPECIFIED_ID) {
+                            throw new DeviceAlreadyExistsException(
+                                ExceptionMessage.format(ExceptionMessage.DEVICE_NONUNIQUE_ID)
+                            );
+                        }
+                        continue;
+                    } while (true);
+
+                    do {
+                        try {
+                            Device p = DeviceManager.open(d.getName(), d.getInterface(), d.getProperties());
+                            p.close();
+                        } catch (DeviceNotFoundException | IllegalArgumentException e1) {
+                            // this is the only right way to continue.
+                            // catch IAE to avoid duplicate of name/properties verification
+                            break;
+                        } catch (UnavailableDeviceException pnae2) {}
+                        throw new DeviceAlreadyExistsException(
+                            ExceptionMessage.format(ExceptionMessage.DEVICE_ALREADY_EXISTING_CONFIG)
+                        );
+                    } while(false);
+
+                    try {
+                        Device p = DeviceManager.open(d.getInterface(), d.getConfiguration());
+                        p.close();
+                    } catch (UnavailableDeviceException pnae3) {}
+
+                    return new_id;
+                }
+
+        }).intValue();
+
+        return new_id;
+    }
+
 
     /**
      * @see
@@ -113,9 +201,9 @@
      * @param d      ID and NAME holder
      * @param action <code>DeviceMgmtPermission</code> action
      */
-    public static void checkPermission(DeviceDescriptor d, String action) {
-        String perm = (DeviceManager.UNSPECIFIED_ID == d.getID()) ? "" : ":"+d.getID();
-        perm = (null == d.getName()) ? perm : d.getName() + perm;
+    public static void checkPermission(String name, int id, String action) {
+        String perm = (DeviceManager.UNSPECIFIED_ID == id) ? ":*" : ":"+id;
+        perm = ((null == name) ? "*" : name) + perm;
         AccessController.checkPermission(new DeviceMgmtPermission(perm, action));
     }
 
--- a/src/share/classes/com/oracle/dio/spibus/impl/SPISlaveImpl.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/spibus/impl/SPISlaveImpl.java	Fri Sep 09 13:20:20 2016 +0300
@@ -26,17 +26,13 @@
 package com.oracle.dio.spibus.impl;
 
 import java.io.IOException;
-import java.lang.Runnable;
 import java.nio.ByteBuffer;
+import java.nio.Buffer;
 import java.security.AccessController;
-import java.util.Objects;
-import java.util.Vector;
 
 import com.oracle.dio.impl.Transaction;
-import com.oracle.dio.power.impl.PowerManagedBase;
 import com.oracle.dio.utils.Constants;
 import com.oracle.dio.utils.ExceptionMessage;
-import com.oracle.dio.utils.Logging;
 
 import jdk.dio.ClosedDeviceException;
 import jdk.dio.DeviceConfig;
@@ -45,11 +41,9 @@
 import jdk.dio.DeviceNotFoundException;
 import jdk.dio.DevicePermission;
 import jdk.dio.InvalidDeviceConfigException;
-import jdk.dio.InvalidDeviceConfigException;
-import jdk.dio.Transactional;
 import jdk.dio.UnavailableDeviceException;
 import jdk.dio.spibus.InvalidWordLengthException;
-import jdk.dio.spibus.InvalidWordLengthException;
+import jdk.dio.spibus.SPICompositeMessage;
 import jdk.dio.spibus.SPIDevice;
 import jdk.dio.spibus.SPIDeviceConfig;
 import jdk.dio.spibus.SPIPermission;
@@ -62,13 +56,15 @@
 
     //every call checkWordLen updates these two variables
     private int byteNum;
-    private int bitNum;
-
+    private int bitNum;   
 
     public SPISlaveImpl(DeviceDescriptor<SPIDevice> dscr, int mode) throws
             IOException, DeviceNotFoundException, InvalidDeviceConfigException {
         super(dscr, mode);
 
+        SPIPermission permission = new SPIPermission(getSecurityName());
+        AccessController.checkPermission(permission);
+
         SPIDeviceConfig cfg = dscr.getConfiguration();
         if(cfg.getControllerName() != null) {
             throw new InvalidDeviceConfigException(
@@ -76,9 +72,6 @@
             );
         }
 
-        SPIPermission permission = new SPIPermission(getSecurityName());
-        AccessController.checkPermission(permission);
-
         openSPIDeviceByConfig0(cfg.getControllerNumber(), cfg.getAddress(),
                                         cfg.getCSActiveLevel(), cfg.getClockFrequency(),
                                         cfg.getClockMode(), cfg.getWordLength(),
@@ -103,7 +96,7 @@
     private String getSecurityName(){
         SPIDeviceConfig cfg = dscr.getConfiguration();
         String securityName = (DeviceConfig.DEFAULT == cfg.getControllerNumber()) ? "" : String.valueOf(cfg.getControllerNumber());
-        securityName = (DeviceConfig.DEFAULT == cfg.getAddress()) ? securityName : securityName + ":" + cfg.getAddress();
+        securityName = (DeviceConfig.DEFAULT == cfg.getAddress()) ? securityName : securityName + ":" + Integer.toString(cfg.getAddress(), 16);
         return securityName;
     }
 
@@ -139,6 +132,11 @@
         return getWordLength0();
     }
 
+    @Override
+    public ByteBuffer prepareBuffer(ByteBuffer buffer, int size) throws IOException, ClosedDeviceException {
+        return (ByteBuffer)super.prepareBufferInt(buffer,size);
+    }
+
     /**
      * Reads one data word of up to 32 bits from this slave device.
      *
@@ -156,8 +154,8 @@
     @Override
     public int read() throws IOException, UnavailableDeviceException,
             ClosedDeviceException {
-        ByteBuffer dst = ByteBuffer.allocateDirect(byteNum);
-        transfer(null, 0, dst);
+        ByteBuffer dst = ByteBuffer.allocateDirect(byteNum);        
+        transferInternal(null, 0, dst);
         return byteArray2int(dst);
     }
 
@@ -223,14 +221,14 @@
             throw new IllegalArgumentException();
         }
         checkBuffer(dst);
-        return transfer(null, skip, dst);
+        return transferInternal(null, skip, dst);
     }
 
     @Override
     public int write(ByteBuffer src) throws IOException,
             UnavailableDeviceException, ClosedDeviceException {
         checkBuffer(src);
-        return transfer(src, 0, null);
+        return transferInternal(src, 0, null);
     }
 
     @Override
@@ -255,14 +253,14 @@
         }
         checkBuffer(src);
         checkBuffer(dst);
-        return transfer(src, skip, dst);
+        return transferInternal(src, skip, dst);
     }
 
     @Override
     public int writeAndRead(int txData) throws IOException, UnavailableDeviceException, ClosedDeviceException{
         ByteBuffer tx = int2byteArray(txData);
         ByteBuffer rx = tx.slice();
-        transfer(tx, 0, rx);
+        transferInternal(tx, 0, rx);
         return byteArray2int(rx);
     }
 
@@ -283,8 +281,8 @@
     }
 
     // checkWordLen ought to be called before checkBuffer to get byteNum is up to date
-    void checkBuffer(ByteBuffer buffer) {
-        Objects.requireNonNull(buffer, ExceptionMessage.format(ExceptionMessage.SPIBUS_NULL_BUFFER));
+    @Override
+    protected void checkBuffer(Buffer buffer) {
 
         if ((buffer.remaining() % byteNum) != 0) {
             throw new InvalidWordLengthException(
@@ -312,164 +310,56 @@
         }
         return retI;
     }
-
-    private int transfer(ByteBuffer src, int skip, ByteBuffer dst) throws IOException {
-        return transfer(src, skip, dst, transaction);
+    
+    /* Returns number of recevied bytes if dst is not NULL, or number of sent bytes otherwise */
+    private int transferInternal(ByteBuffer src, int skip, ByteBuffer dst) throws IOException {
+        int returnCount = dst != null ? dst.remaining() : src.remaining();
+        SPICompositeMessage message = this.createCompositeMessage();
+        
+        if(src == null && dst != null) {
+            message.appendRead(skip, dst);
+        } else if(dst == null && src != null) {
+            message.appendWrite(src);
+        } else {
+            message.appendWriteAndRead(src, skip, dst);            
+        }
+              
+        message.transfer();
+        
+        return returnCount;  
+    }
+    
+    
+    /**
+     * Performs a SPI transfer operation with locking the SPI peripheral
+     * The both buffers should be direct and same length
+     *
+     * @param src 
+     *            Direct byte buffer which will be sent to the slave device
+     * @param dst 
+     *            Direct byte buffer which will used for the saving all the 
+     *            data from slave 
+     *
+     */    
+    void transferWithLock(ByteBuffer src, ByteBuffer dst) throws IOException {
+        try {
+            conditionalLock();
+            
+            writeAndRead0(src, dst);
+            
+        } finally  {
+            conditionalUnlock();
+        }        
     }
 
-    /* Returns number of recevied bytes if dst is not NULL, or number of sent bytes otherwise */
-    int transfer(ByteBuffer src, int skip, ByteBuffer dst, int transaction) throws IOException {
-
-        synchronized(this) {
-            checkPowerState();
-        }
-
-        int xfered = 0;
-        final boolean count_recv = null != dst;
-        final boolean combined = (0 != skip || (null != dst && null != src && dst.remaining() != src.remaining()));
-        Vector<Runnable> localActions = null;
-
-        /* synchronized allows to avoid IllegaStateException for the case when transfer()
-           is called while previous operation is incomplete.
-           sync on handle to avoid dead lock on close() since close is synchronized on this instance.
-        */
-        synchronized(handle){
-
-        final boolean trStart = combined && transaction == Transaction.REGULAR_MESSAGE;
-
-        if (trStart) {
-            // can throw ISE
-            transaction = beginTransaction();
-            if (!(this instanceof Transactional)) {
-                localActions = new Vector<>();
-            }
-        }
-
-        try {
-            do {
-                // convert tries to align toSend and toRecv buffer length if src or dst are nondirect.
-                ByteBuffer toRecv = convert(dst, src);
-                ByteBuffer toSend = convert(src, toRecv);
-
-
-                // if there is nothing to send, use recv buffer as dummy send data
-                if (null == toSend) {
-                    if (null == toRecv) {
-                        // both empty buffers
-                        return xfered;
-                    }
-                    toSend = toRecv.slice();
-                }
-
-                if (null != toRecv) {
-                    // always align send and recv buffers len,
-                    // or recv to NULL buffer
-                    if (toSend.remaining() <= skip) {
-                        toRecv = null;
-                    }
-                }
-
-
-                try {
-                    conditionalLock();
-                    writeAndRead0(toSend, toRecv);
-                } finally {
-                    conditionalUnlock();
-                }
-
-                if (null != src) {
-
-                    if (null != localActions) {
-                        final ByteBuffer ref = toSend;
-                        localActions.add(new Runnable() {
-                                public void run() {
-                                    // dummy action to retain object refence
-                                    ref.remaining();
-                                };
-                            });
-                    }
-
-                    if (!count_recv) {
-                        xfered += toSend.remaining();
-                    }
-                    shiftBufferPosition(src, src.position() + toSend.remaining());
-                }
-
-                if (skip > 0) {
-                    if (null != toRecv) {
-                        // ability to fit 'skip' bytes was checked above (see if (toSend.remaining() <= skip) )
-                        toRecv.position(skip);
-                        skip = 0;
-                    } else {
-                        skip-=toSend.remaining();
-                    }
-                }
-                if (null != toRecv) {
-                    xfered += toRecv.remaining();
-                    // linux and similar accumulate packets and transfer them after endTrasaction call
-                    // transaction requires postponed reverse copying
-                    if (null != localActions) {
-                        final ByteBuffer to = dst.slice();
-                        final ByteBuffer from = toRecv.slice();
-                        localActions.add(new Runnable() {
-                                public void run() {
-                                    to.put(from);
-                                };
-                            });
-
-                        try {
-                            dst.position(dst.position() + toRecv.remaining());
-                        }catch (IllegalArgumentException e){
-                            // the buffer was updated in parallel
-                            Logging.reportWarning(ExceptionMessage.format(ExceptionMessage.BUFFER_IS_MODIFIED));
-                            //
-                            dst.position(dst.limit());
-                        }
-
-                    } else {
-                        dst.put(toRecv);
-                    }
-                }
-
-            } while ((null != dst && dst.hasRemaining()) || (null != src && src.hasRemaining()));
-
-        } finally  {
-            if (trStart) {
-                try {
-                    endTransaction(transaction);
-                    if (null != localActions) {
-                        for (Runnable toRun: localActions) {
-                            toRun.run();
-                        }
-                    }
-                } catch (IllegalStateException e) {
-                    // intentionally skip
-                }
-            }
-        }
-        }//synchronized(handle)
-        return xfered;
-    }
-
-    // transaction demarcator
-    private static int trans_counter;
-
-    protected int beginTransaction() throws IOException, IllegalStateException {
+    void beginTransaction() throws IOException, IllegalStateException {
         // interapp lock
         conditionalLock();
 
         begin0();
-        // it is enough to separate transactions in scope of current application enviroment.
-        // the rest is cared by javacall
-        synchronized(SPISlaveImpl.class) {
-            return (transaction = trans_counter++);
-        }
     }
 
-    protected void endTransaction(int transaction) throws IllegalStateException {
-        if (transaction != this.transaction) {
-            throw new IllegalStateException();
-        }
+    void endTransaction() throws IllegalStateException {
 
         end0();
 
--- a/src/share/classes/com/oracle/dio/uart/impl/UARTImpl.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/uart/impl/UARTImpl.java	Fri Sep 09 13:20:20 2016 +0300
@@ -26,14 +26,23 @@
 package com.oracle.dio.uart.impl;
 
 import java.io.*;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
+import java.nio.Buffer;
 import java.security.AccessControlException;
 import java.security.AccessController;
 import java.util.Hashtable;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Queue;
 import java.util.StringTokenizer;
 import java.util.Timer;
 import java.util.TimerTask;
+import java.util.Vector;
 
+import com.oracle.dio.impl.EventQueueManager;
 import com.oracle.dio.power.impl.PowerManagedBase;
 import com.oracle.dio.utils.Configuration;
 import com.oracle.dio.utils.Constants;
@@ -44,22 +53,23 @@
 
 import jdk.dio.*;
 import jdk.dio.uart.*;
+import jdk.dio.uart.UART;
+import jdk.dio.uart.UARTConfig;
+import jdk.dio.uart.UARTConfig.Builder;
+import jdk.dio.uart.UARTEvent;
+import jdk.dio.uart.UARTEventListener;
+import jdk.dio.uart.UARTPermission;
 
 import romizer.*;
 
 class UARTImpl extends PowerManagedBase<UART> implements UART {
     private boolean isWriting;
 
-    private Object synchReadLock = new Object();
+    private final Object synchReadLock = new Object();
+    private final Object synchWriteLock = new Object();
 
-    private ByteBuffer writeBuffers[] = new ByteBuffer[2];
-    private int writeBuffersPositions[] = new int[2];
-
-    private ByteBuffer readBuffers[] = new ByteBuffer[2];
-    private int readBuffersPositions[] = new int[2];
-
-    private int readBufferIdx = 0;
-    private int writeBufferIdx = 0;
+    private final Queue<ByteBuffer> writeBuffers = new LinkedList<ByteBuffer>();
+    private final Queue<ByteBuffer> readBuffers = new LinkedList<ByteBuffer>();
 
     private InputRoundListener<UART, ByteBuffer> inRoundListener;
     private OutputRoundListener<UART, ByteBuffer> outRoundListener;
@@ -74,17 +84,13 @@
                                 throws DeviceNotFoundException, InvalidDeviceConfigException, UnsupportedAccessModeException{
         super(dscr, mode);
 
-        String deviceName;
         byte[] devName; // UTF-8 device name
-
-        if( mode != DeviceManager.EXCLUSIVE){
-            throw new UnsupportedAccessModeException();
-        }
-
-        UARTConfig cfg = dscr.getConfiguration();
-
         //deviceName = uart device prefix + device number
-        deviceName = getSecurityName();
+        String deviceName = getSecurityName();
+        // in case of such device absence we try to check permission for all devices
+        // because non-existing device belongs to all devices set
+        UARTPermission permission = new UARTPermission(null != deviceName ? deviceName : "*");
+        AccessController.checkPermission(permission);
 
         if (deviceName == null){
             throw new DeviceNotFoundException(
@@ -92,8 +98,11 @@
             );
         }
 
-        UARTPermission permission = new UARTPermission(deviceName);
-        AccessController.checkPermission(permission);
+        if( mode != DeviceManager.EXCLUSIVE){
+            throw new UnsupportedAccessModeException();
+        }
+
+        UARTConfig cfg = dscr.getConfiguration();
 
         try{
             devName = deviceName.getBytes("UTF-8");
@@ -114,22 +123,36 @@
         UARTOptionsHandler.processOptions(this, dscr.getProperties());
     }
 
-    private InputRoundListener getLocalInputRoundListener(){
-        return new InputRoundListener<UART, ByteBuffer>() {
-                @Override
-                public void inputRoundCompleted(RoundCompletionEvent<UART, ByteBuffer> event) {
-                    synchronized(synchReadLock){
-                        synchReadLock.notifyAll();
+    private class InternalRoundListener implements  InputRoundListener<UART, ByteBuffer> {
+
+            private final int toRead;
+
+            private InternalRoundListener(int toRead) {
+                this.toRead = toRead;
+            }
+
+            private void stop() {
+                synchronized (synchReadLock) {
+                    try {
+                        stopReading(true);
+                    } catch (IOException e) {
+                        // intentionally ignored
                     }
+                    synchReadLock.notifyAll();
                 }
+            }
 
-                @Override
-                public void failed(Throwable ex, UART arg1) {
-                    synchronized(synchReadLock){
-                        synchReadLock.notifyAll();
-                    }
+            @Override
+            public void inputRoundCompleted(RoundCompletionEvent<UART, ByteBuffer> event) {
+                if (event.getNumber() >= toRead || !event.getBuffer().hasRemaining()) {
+                    stop();
                 }
-            };
+            }
+
+            @Override
+            public void failed(Throwable ex, UART arg1) {
+                stop();
+            }
     }
 
 
@@ -162,6 +185,7 @@
             if (devNum == DeviceConfig.DEFAULT) {
                 devNum = 0;
             }
+
             // first port in list is DEFAULT port
             try {
                 String ports = Configuration.getProperty("microedition.commports");
@@ -188,135 +212,182 @@
         AccessController.checkPermission(new UARTPermission(getSecurityName(), DevicePermission.POWER_MANAGE));
     }
 
-    protected synchronized void processEvent(int event, int bytesProcessed){
-        UARTEventListener listener = eventListeners.get(event);
-        if (listener != null){
-            try{
-                UARTEvent uartEvent = new UARTEvent(this, event);
-                listener.eventDispatched(uartEvent);
-            } catch(Throwable e){
-                //do nothing
+    private int totalBytesRead;
+    @Override
+    protected void processNativeEvent(int event, int... data) {
+        {
+            UARTEventListener listener = eventListeners.get(event);
+            if (listener != null){
+                try{
+                    UARTEvent uartEvent = new UARTEvent(this, event);
+                    listener.eventDispatched(uartEvent);
+                } catch(Throwable e){
+                    //do nothing
+                }
             }
         }
 
         switch(event){
         case UARTEvent.INPUT_DATA_AVAILABLE:
-            if (inRoundListener != null){
-                ByteBuffer buffer = readBuffers[readBufferIdx];
-                if (null == buffer) {
-                    try{
-                        inRoundListener.failed(new Exception("Event processing error. Read buffer is null"), this);
-                    }catch(Exception e){
-                        //do nothing
+            {
+                final InputRoundListener<UART, ByteBuffer> listener = inRoundListener;
+                if (listener != null){
+                    ByteBuffer buffer = readBuffers.peek();
+                    if (null == buffer) {
+                        Logging.reportError("[UART] No buffer is ready for read operation");
+                        return;
                     }
-                    return;
-                }
-                /*
-                    read0 is designed to copy available data from the javacall buffer to java buffer,
-                    because of that no slice() call is necessary, the following is redundand:
+                    /*
+                        read0 is designed to copy available data from the javacall buffer to java buffer,
+                        because of that no slice() call is necessary, the following is redundand:
 
-                    int bytesReaden = read0(buffer.slice());
+                        int bytesReaden = read0(buffer.slice());
 
-                */
-                int tmpPos = buffer.position();
-                int bytesRead = read0(buffer);
-                try{
-                    shiftBufferPosition(buffer, tmpPos + bytesRead);
-                }catch(IOException e){
+                    */
 
-                }
+                    final int bytesRead = read0(buffer);
+                    totalBytesRead += bytesRead;
+                    shiftBufferPosition(buffer, buffer.position() + bytesRead);
 
-                if(!buffer.hasRemaining() || ( receiveTriggerLevel !=0 && (buffer.position() - readBuffersPositions[readBufferIdx]) >= receiveTriggerLevel) || (-1 == bytesProcessed)){
-                    RoundCompletionEvent<UART,ByteBuffer> rcEvent =
-                        new RoundCompletionEvent(this, buffer, buffer.position() - readBuffersPositions[readBufferIdx]);
+                    final boolean syncRead = (listener instanceof InternalRoundListener);
+                    if(!buffer.hasRemaining() || syncRead){
 
-                    if (null != readBuffers[1]) {
-                        //2 buffers schema
-                        //switch buffers, than notify user
-                        readBufferIdx = readBufferIdx == 0 ? 1 : 0;
-                        buffer = readBuffers[readBufferIdx];
-                        readBuffersPositions[readBufferIdx] = buffer.position();
+                        RoundCompletionEvent<UART,ByteBuffer> rcEvent =
+                            new RoundCompletionEvent(this, buffer, totalBytesRead);
 
                         //notify user
                         try{
-                            inRoundListener.inputRoundCompleted(rcEvent);
+                            listener.inputRoundCompleted(rcEvent);
                         }catch(Exception e){
                             //do nothing, listener should not throw an exception
+                            Logging.reportWarning(e.toString());
                         }
-                    }else{
-                        //1 buffer
-                        //notify the user first, then keep reading
-                        try{
-                            inRoundListener.inputRoundCompleted(rcEvent);
-                            readBuffersPositions[readBufferIdx] = buffer.position();
-                        }catch(Exception e){
-                            //do nothing, listener should not throw an exception
+
+                        // sync read operates single buffer -> no need to rearrange the queue or reset total read counter
+                        // sync read alsways stops if buffer is full -> no need to resend notification
+                        if (!syncRead) {
+                            totalBytesRead = 0;
+                            // if not stopped
+                            if (inRoundListener != null) {
+                                // next time use another buffer.
+                                // stopRead() cleans readBuffers therefore .read() is moved here
+                                readBuffers.remove();
+                                if (buffer.hasRemaining()) {
+                                    readBuffers.add(buffer);
+                                } else {
+                                    // post notification
+                                    rcEvent = new RoundCompletionEvent(this, buffer, 0);
+                                    EventQueueManager.getInstance().postEvent(this, UARTEvent.INPUT_DATA_AVAILABLE, rcEvent);
+                                }
+                            }
                         }
-                    }//end of else 1 buffer
+                    }
                 }
             }
             break;
+        case UARTEvent.OUTPUT_BUFFER_EMPTY:
+            {
+                final int bytesProcessed = data[0];
+                final OutputRoundListener<UART, ByteBuffer> listener = outRoundListener;
+                if (listener != null){
+                    ByteBuffer buffer = writeBuffers.poll();
+                    if (null == buffer) {
+                        Logging.reportError("[UART] No buffer is ready for write operation");
+                        return;
+                    }
+                    // this event is sent if buffer is empty only
+                    shiftBufferPosition(buffer, buffer.limit());
+                    RoundCompletionEvent<UART,ByteBuffer> rcEvent = new RoundCompletionEvent(this, buffer, bytesProcessed);
 
-        case UARTEvent.INPUT_BUFFER_OVERRUN:
-            break;
-        case UARTEvent.OUTPUT_BUFFER_EMPTY:
-            if (outRoundListener != null){
-                ByteBuffer buffer = writeBuffers[writeBufferIdx];
-
-                if (null == buffer) {
+                    //notify user
                     try{
-                        outRoundListener.failed(new Exception("Event processing error. Write buffer is null"), this);
+                        listener.outputRoundCompleted(rcEvent);
                     }catch(Exception e){
                         //do nothing, listener should not throw an exception
+                        Logging.reportWarning(e.toString());
                     }
-                    return;
-                }
-                buffer.position(buffer.position() + bytesProcessed);
-
-                if (!buffer.hasRemaining()) {
-                    RoundCompletionEvent<UART,ByteBuffer> rcEvent = new RoundCompletionEvent(this, buffer, buffer.position() - writeBuffersPositions[writeBufferIdx]);
-
-                    if (null != writeBuffers[1]) {
-                        //2 byffers
-                        //switch buffers, than notify user
-                        writeBufferIdx = writeBufferIdx == 0 ? 1 : 0;
-                        buffer = writeBuffers[writeBufferIdx];
-                        //keep writing from the second buffer before user notice
-                        if(isWriting){
-                            if (buffer.hasRemaining()){
-                                writeAsynch0(buffer);
-                            }
+                    if(isWriting){
+                        if (buffer.hasRemaining()) {
+                            writeBuffers.add(buffer);
+                        } else {
+                            // post notification
+                            rcEvent = new RoundCompletionEvent(this, buffer, 0);
+                            EventQueueManager.getInstance().postEvent(this, UARTEvent.OUTPUT_BUFFER_EMPTY, rcEvent);
                         }
-                        //notify user
-                        try{
-                            outRoundListener.outputRoundCompleted(rcEvent);
-                        }catch(Exception e){
-                            //do nothing, listener should not throw an exception
+                        buffer = writeBuffers.peek();
+                        if (null != buffer){
+                            writeAsynch0(buffer);
                         }
-                    }else{
-                        //1 buffer
-                        //notify user first, then keep writing
-                        try{
-                            outRoundListener.outputRoundCompleted(rcEvent);
-                        }catch(Exception e){
-                            //do nothing, listener should not throw an exception
-                        }
-                        if(isWriting){
-                            if (buffer.hasRemaining()){
-                                writeAsynch0(buffer);
-                            }
-                        }
-                    }//end of else 1 buffer
-                }else{ //buffer has remaining, keep writing
-                    if(isWriting){
-                        write0(buffer);
                     }
-                }
-            }//if (outRoundListener != null)
+                }//if (outRoundListener != null)
+            }
             break;
         }//switch(event)
     }
 
+    @Override
+    protected void processDeviceEvent(int eventType, DeviceEvent event) {
+        if (eventType == UARTEvent.OUTPUT_BUFFER_EMPTY) {
+            final OutputRoundListener<UART, ByteBuffer> listener = outRoundListener;
+            if (listener != null) {
+                //notify user
+                try{
+                    listener.outputRoundCompleted((RoundCompletionEvent)event);
+                }catch(Exception e){
+                    //do nothing, listener should not throw an exception
+                    Logging.reportWarning(e.toString());
+                }
+                if (isWriting) {
+                    final ByteBuffer buffer = ((RoundCompletionEvent<UART, ByteBuffer>)event).getBuffer();
+                    if (buffer.hasRemaining()) {
+                        // if no write process is ongoing
+                        if (writeBuffers.peek() == null) {
+                            writeAsynch0(buffer);
+                        }
+                        // no sync is required since event processing is single thread operation
+                        writeBuffers.add(buffer);
+                    } else {
+                        // send again
+                        EventQueueManager.getInstance().postEvent(this, UARTEvent.OUTPUT_BUFFER_EMPTY, event);
+                    }
+                }
+            }
+        } else if (eventType == UARTEvent.INPUT_DATA_AVAILABLE) {
+            final InputRoundListener<UART, ByteBuffer> listener = inRoundListener;
+            if (listener != null) {
+                //notify user
+                try{
+                    listener.inputRoundCompleted((RoundCompletionEvent)event);
+                }catch(Exception e){
+                    //do nothing, listener should not throw an exception
+                    Logging.reportWarning(e.toString());
+                }
+                // if not stopped
+                if (inRoundListener != null) {
+                    final ByteBuffer buffer = ((RoundCompletionEvent<UART, ByteBuffer>)event).getBuffer();
+                    if (buffer.hasRemaining()) {
+                        final ByteBuffer tmp = readBuffers.peek();
+                        readBuffers.add(buffer);
+                        if (tmp == null) {
+                            // by contract next INPUT_DATA_AVAILABLE is suppressed until read0->javacall_uart_read is called.
+                            // if previous InputRoundListener doesn't clear provided buffer we may get into situation when
+                            // processNativeEvent->readBuffer.peek() returns null and javacall flag is not cleared by read0.
+                            // to continue receviving we need to read cached data and clear javacall flags
+                            processNativeEvent(UARTEvent.INPUT_DATA_AVAILABLE, 0);
+                        }
+                    } else {
+                        // send again
+                        EventQueueManager.getInstance().postEvent(this, UARTEvent.INPUT_DATA_AVAILABLE, event);
+                    }
+                }
+            }
+        } else {
+            Logging.reportError("UART.processDeviceEvent: unknown event " + eventType);
+        }
+    }
+
+
+
     /**
      * Gets the current baud rate. If the baud rate was not set previously using {@link #setBaudRate(int)} the
      * peripheral configuration-specific default value is returned.
@@ -341,8 +412,8 @@
     }
 
     @Override
-    public int getFlowControlMode() throws IOException, UnavailableDeviceException, ClosedDeviceException {
-        throw new UnsupportedOperationException();
+    public synchronized int getFlowControlMode() throws IOException, UnavailableDeviceException, ClosedDeviceException {
+        return getFlowControlMode0();
     }
 
     /**
@@ -372,9 +443,7 @@
     @Override
     public synchronized void setBaudRate(int baudRate) throws IOException, UnavailableDeviceException, ClosedDeviceException{
         checkPowerState();
-        if(baudRate <= 0){
-            throw new java.lang.UnsupportedOperationException();
-        }
+        new UARTConfig.Builder().setBaudRate(baudRate);
         setBaudRate0( baudRate);
     }
 
@@ -385,6 +454,7 @@
     @Override
     public synchronized void setDataBits(int dataBits) throws IOException, UnavailableDeviceException, ClosedDeviceException{
         checkPowerState();
+        new UARTConfig.Builder().setDataBits(dataBits);
         setDataBits0( dataBits);
     }
 
@@ -421,7 +491,7 @@
     }
 
     private void subscribe(int eventId){
-        UARTEventHandler.getInstance().addEventListener(eventId, this);
+        EventQueueManager.getInstance().setEventListener(UART.class, eventId, this);
         setEventListener0(eventId);
     }
 
@@ -436,13 +506,15 @@
             }
         }
 
-        UARTEventHandler.getInstance().removeEventListener(eventId, this);
+        EventQueueManager.getInstance().removeEventListener(UART.class, eventId, this);
         removeEventListener0(eventId);
     }
 
     @Override
-    public void setFlowControlMode(int flowcontrol) throws IOException, UnavailableDeviceException, ClosedDeviceException {
-        throw new UnsupportedOperationException();
+    public synchronized void setFlowControlMode(int flowcontrol) throws IOException, UnavailableDeviceException, ClosedDeviceException {
+        checkPowerState();
+        new UARTConfig.Builder().setFlowControlMode(flowcontrol);
+        setFlowControlMode0(flowcontrol);
     }
 
     /**
@@ -451,6 +523,7 @@
     @Override
     public synchronized void setParity(int parity) throws IOException, UnavailableDeviceException, ClosedDeviceException{
         checkPowerState();
+        new UARTConfig.Builder().setParity(parity);
         setParity0(parity);
     }
 
@@ -461,6 +534,7 @@
     @Override
     public synchronized void setStopBits(int stopBits) throws IOException, UnavailableDeviceException, ClosedDeviceException{
         checkPowerState();
+        new UARTConfig.Builder().setStopBits(stopBits);
         setStopBits0(stopBits);
     }
 
@@ -472,55 +546,59 @@
      * from that very same buffer upon invocation od the provided {@link OutputRoundListener} instance.
      */
     @Override
-    public synchronized void startWriting(ByteBuffer src, OutputRoundListener<UART, ByteBuffer> listener) throws IOException, UnavailableDeviceException, ClosedDeviceException{
-        checkPowerState();
-        checkWrite();
+    public void startWriting(ByteBuffer src, OutputRoundListener<UART, ByteBuffer> listener) throws IOException, UnavailableDeviceException, ClosedDeviceException{
+        checkBuffer(src);
+        Objects.requireNonNull(listener, ExceptionMessage.format(ExceptionMessage.NULL_LISTENER));
 
-        if(src == null || listener == null){
-            throw new NullPointerException(
-                ExceptionMessage.format(ExceptionMessage.UART_NULL_SRC_OR_LISTENER)
-            );
-        }
-
-        writeBuffers[0] = src;
-        writeBuffersPositions[0] = src.position();
-        writeBufferIdx = 0;
-        outRoundListener = listener;
-        subscribe(UARTEvent.OUTPUT_BUFFER_EMPTY);
-        writeAsynch0(src);
-        isWriting = true;
+        writeAsync(src, null, listener);
     }
 
     /**
      * Starts asynchronous writing in successive rounds.
      */
     @Override
-    public synchronized void startWriting(ByteBuffer src1, ByteBuffer src2, OutputRoundListener<UART, ByteBuffer> listener) throws IOException,
+    public void startWriting(ByteBuffer src1, ByteBuffer src2, OutputRoundListener<UART, ByteBuffer> listener) throws IOException,
         UnavailableDeviceException, ClosedDeviceException{
 
-        if(src1 == null || src2 == null || listener == null){
-            throw new NullPointerException(
-                ExceptionMessage.format(ExceptionMessage.UART_NULL_SRC1_OR_SRC2_OR_LISTENER)
-            );
+        checkBuffer(src1);
+        checkBuffer(src2);
+        Objects.requireNonNull(listener, ExceptionMessage.format(ExceptionMessage.NULL_LISTENER));
+
+        writeAsync(src1, src2, listener);
+    }
+
+    private void writeAsync(ByteBuffer src1, ByteBuffer src2, OutputRoundListener<UART, ByteBuffer> listener) throws IOException,
+        UnavailableDeviceException, ClosedDeviceException {
+        checkPowerState();
+        synchronized(synchWriteLock) {
+            checkWrite();
+
+            writeBuffers.add(src1);
+            if (null != src2) {
+                writeBuffers.add(src2);
+            }
+
+            outRoundListener = listener;
+            subscribe(UARTEvent.OUTPUT_BUFFER_EMPTY);
+            writeAsynch0(src1);
+            isWriting = true;
         }
-
-        writeBuffers[1] = src2;
-        writeBuffersPositions[1] = src2.position();
-        startWriting(src1, listener);
     }
 
     /**
      * Stops (cancels) the currently active writing session.
      */
     @Override
-    public synchronized void stopWriting() throws IOException, UnavailableDeviceException, ClosedDeviceException{
+    public void stopWriting() throws IOException, UnavailableDeviceException, ClosedDeviceException{
         checkOpen();
-        if (isWriting){
-            outRoundListener = null;
-            unsubscribe(UARTEvent.OUTPUT_BUFFER_EMPTY);
-            writeBuffers[0] = writeBuffers[1] = null;
-            stopWriting0();
-            isWriting = false;
+        synchronized(synchWriteLock) {
+            if (isWriting){
+                writeBuffers.clear();
+                outRoundListener = null;
+                unsubscribe(UARTEvent.OUTPUT_BUFFER_EMPTY);
+                stopWriting0();
+                isWriting = false;
+            }
         }
     }
 
@@ -529,57 +607,67 @@
      * buffer.
      */
     @Override
-    public synchronized void startReading(ByteBuffer src, InputRoundListener<UART, ByteBuffer> listener) throws IOException, UnavailableDeviceException, ClosedDeviceException{
-        checkPowerState();
-        checkRead();
-
-        if(src == null || listener == null){
-            throw new NullPointerException(
-                ExceptionMessage.format(ExceptionMessage.UART_NULL_SRC_OR_LISTENER)
-            );
-        }
-
-        inRoundListener = listener;
-        readBuffers[0] = src;
-        readBuffersPositions[0] = src.position();
-        readBufferIdx = 0;
-        /*
-                        subscribe calls set_event_listener, in case of INPUT_DATA_AVAILABLE
-                        the native function checks if data available in the internal
-                        buffer and generates INPUT_DATA_AVAILABLE event if so.
-                */
-        subscribe(UARTEvent.INPUT_DATA_AVAILABLE);
+    public void startReading(ByteBuffer src, InputRoundListener<UART, ByteBuffer> listener) throws IOException, UnavailableDeviceException, ClosedDeviceException{
+        checkBuffer(src);
+        Objects.requireNonNull(listener, ExceptionMessage.format(ExceptionMessage.NULL_LISTENER));
+        readAsync(src, null, listener);
     }
 
     /**
      * Starts asynchronous reading in sucessive rounds.
      */
     @Override
-    public synchronized void startReading(ByteBuffer src1, ByteBuffer src2, InputRoundListener<UART, ByteBuffer> listener) throws IOException,
+    public void startReading(ByteBuffer src1, ByteBuffer src2, InputRoundListener<UART, ByteBuffer> listener) throws IOException,
             UnavailableDeviceException, ClosedDeviceException{
+        checkBuffer(src1);
+        checkBuffer(src2);
+        Objects.requireNonNull(listener, ExceptionMessage.format(ExceptionMessage.NULL_LISTENER));
+        readAsync(src1, src2, listener);
+    }
 
-        if(src1 == null || src2 == null || listener == null){
-            throw new NullPointerException(
-                ExceptionMessage.format(ExceptionMessage.UART_NULL_SRC1_OR_SRC2_OR_LISTENER)
-            );
+    private void readAsync(ByteBuffer src1, ByteBuffer src2, InputRoundListener<UART, ByteBuffer> listener)  throws IOException,
+            UnavailableDeviceException, ClosedDeviceException {
+        checkPowerState();
+        synchronized(synchReadLock){
+            checkRead();
+            totalBytesRead = 0;
+            inRoundListener = listener;
+            readBuffers.add(src1);
+            if (null != src2) {
+                readBuffers.add(src2);
+            }
+
+            /*
+                subscribe calls set_event_listener, in case of INPUT_DATA_AVAILABLE
+                the native function checks if data available in the internal
+                buffer and generates INPUT_DATA_AVAILABLE event if so.
+            */
+            subscribe(UARTEvent.INPUT_DATA_AVAILABLE);
         }
-        readBuffers[1] = src2;
-        readBuffersPositions[1] = src2.position();
-        startReading(src1, listener);
+    }
+
+
+    /* stop operation of required type only, e.g. public stopReading() doesn't affect read() */
+    private void stopReading(boolean syncVer) throws IOException, UnavailableDeviceException, ClosedDeviceException {
+        checkOpen();
+        synchronized(synchReadLock) {
+            if (null != inRoundListener && syncVer == (inRoundListener instanceof InternalRoundListener) ) {
+                readBuffers.clear();
+                inRoundListener = null;
+                unsubscribe(UARTEvent.INPUT_DATA_AVAILABLE);
+                // redundant function, remove later
+                stopReading0();
+                synchReadLock.notifyAll();
+            }
+        }
     }
 
     /**
      * Stops (cancels) the currently active reading session.
       */
     @Override
-    public synchronized void stopReading() throws IOException, UnavailableDeviceException, ClosedDeviceException{
-        checkOpen();
-        if (inRoundListener != null){
-            inRoundListener = null;
-            unsubscribe(UARTEvent.INPUT_DATA_AVAILABLE);
-            readBuffers[0] = readBuffers[1] = null;
-            stopReading0();
-        }
+    public void stopReading() throws IOException, UnavailableDeviceException, ClosedDeviceException{
+        stopReading(false);
     }
 
     /**
@@ -624,33 +712,25 @@
             UnavailableDeviceException, ClosedDeviceException{
         int ret;
 
-        synchronized(this){
-            checkRead();
-        }
+        if(!dst.hasRemaining()){
+            ret = 0;
+        }else{
+            ret = dst.position();
+            synchronized(synchReadLock){
 
+                checkRead();
 
-            if (dst == null){
-                throw new NullPointerException(
-                    ExceptionMessage.format(ExceptionMessage.UART_NULL_DST)
-                );
-            }
-
-            if(!dst.hasRemaining()){
-                ret = 0;
-            }else{
-                ret = dst.position();
                 /*read all data available*/
                 int readRes = read0(dst);
                 shiftBufferPosition(dst, ret + readRes);
-                if (dst.hasRemaining()) {
-                    if (!UARTEventHandler.getInstance().isDispatchThread()) {
+                if ((0 == receiveTriggerLevel || readRes < receiveTriggerLevel) && dst.hasRemaining()) {
+                    if (!EventQueueManager.getInstance().isDispatchThread() && inputTimeout > 0) {
                         /*
                          * the user calls read() from the event callback, or inputTimeout is 0
                          * exit immediatelly,
                          * else read with timeout
                          */
-                        startReading(dst, getLocalInputRoundListener());
-                        synchronized(synchReadLock){
+                        startReading(dst, new InternalRoundListener((0 != receiveTriggerLevel) ? receiveTriggerLevel - readRes : dst.remaining()));
                             try{
                                 if(inputTimeout == Integer.MAX_VALUE){
                                     //timeout disabled, wait forever or till the buffer is fullfilled
@@ -660,13 +740,15 @@
                                 }
                             }catch(InterruptedException iE){
                                 throw new IOException();
+                            } finally {
+                                stopReading(true);
                             }
-                        } // synch
-                        stopReading();
                     }
                 } // if !event thread
-                ret = dst.position() - ret;
-            } // if has Remaining
+            } // synch
+            ret = dst.position() - ret;
+        } // if has Remaining
+
         return ret;
     }
 
@@ -676,46 +758,36 @@
     @Override
     public int write(ByteBuffer src) throws IOException,
             UnavailableDeviceException, ClosedDeviceException{
-        if (src == null){
-            throw new NullPointerException(
-                ExceptionMessage.format(ExceptionMessage.UART_NULL_SRC)
-            );
+
+        checkPowerState();
+
+        int ret = 0;
+
+        synchronized(synchWriteLock) {
+            checkWrite();
+            isWriting = true;
         }
 
-        synchronized (this) {
-            checkPowerState();
-            checkWrite();
-        }
-
-        int ret = 0;
         try {
-            isWriting = true;
             /*
              * synchronous write0 returns number of written bytes
              * slice is needed to avoid memory corruption because src buffer modification
              * might happen during write0
              */
             ret = write0(src.slice());
-            try{
-                src.position(src.position() + ret);
-            }catch(IllegalArgumentException e){
-                //IAE happens if src.position() + ret < 0 (not expected) or src.position() + ret > limit
-                src.position(src.limit());
-            }
+            shiftBufferPosition(src, src.position() + ret);
         } finally {
             isWriting = false;
-            return ret;
         }
+        return ret;
     }
 
     @Override
-    public synchronized void close() throws IOException{
+    public void close() throws IOException{
         if (isOpen()) {
-            synchronized(synchReadLock){
-                synchReadLock.notifyAll();
-            }
             stopWriting();
-            stopReading();
+            // stops EVERY read thread
+            stopReading((inRoundListener instanceof InternalRoundListener));
             super.close();
         }
     }
@@ -730,9 +802,7 @@
     public synchronized void setReceiveTimeout(int timeout) throws IOException, UnavailableDeviceException, ClosedDeviceException {
         checkPowerState();
         if(timeout < 0 ){
-            throw new UnsupportedOperationException(
-                    ExceptionMessage.format(ExceptionMessage.UART_NEGATIVE_TIMEOUT)
-            );
+            throw new IllegalArgumentException(ExceptionMessage.format(ExceptionMessage.UART_NEGATIVE_TIMEOUT));
         }
         inputTimeout = timeout;
     }
@@ -759,16 +829,24 @@
         return getUartId0();
     }
 
+    @Override
     public synchronized ByteBuffer getInputBuffer() throws ClosedDeviceException,
             IOException {
         throw new java.lang.UnsupportedOperationException();
     }
 
+    @Override
     public synchronized ByteBuffer getOutputBuffer() throws ClosedDeviceException,
             IOException {
         throw new java.lang.UnsupportedOperationException();
     }
 
+    @Override
+    public ByteBuffer prepareBuffer(ByteBuffer buffer, int size) throws IOException, ClosedDeviceException {
+        return (ByteBuffer)super.prepareBufferInt(buffer,size);
+    }
+
+
     @Local(DontRemoveFields = {
         "com.oracle.dio.impl.Handle.native_handle",
         "com.oracle.dio.impl.AbstractPeripheral.handle",
@@ -891,6 +969,18 @@
         "com.oracle.dio.impl.Handle.native_handle",
         "com.oracle.dio.impl.AbstractPeripheral.handle",
     })
+    private native int setFlowControlMode0(int flowcontrol);
+
+    @Local(DontRemoveFields = {
+        "com.oracle.dio.impl.Handle.native_handle",
+        "com.oracle.dio.impl.AbstractPeripheral.handle",
+    })
+    private native int getFlowControlMode0();
+
+    @Local(DontRemoveFields = {
+        "com.oracle.dio.impl.Handle.native_handle",
+        "com.oracle.dio.impl.AbstractPeripheral.handle",
+    })
     private native int generateBreak0(int duration);
 
 }
--- a/src/share/classes/com/oracle/dio/utils/ActionFactory.java	Mon Aug 29 14:45:05 2016 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.oracle.dio.utils;
-
-import java.util.StringTokenizer;
-import jdk.dio.DevicePermission;
-
-/**
- * Utility class for device permission class
- */
-public class ActionFactory {
-    /**
-     * Checks if <code>actions1</code> list "implies"
-     * <code>actions2</code> list
-     *
-     * @param actions1 comma-separated list of verified and valid
-     *                 actions
-     * @param actions1 comma-separated list of verified and valid
-     *                 actions
-     *
-     * @return true <code>actions2</code> list is implied by
-     *         <code>actions1</code> list
-     */
-    public static boolean implies(String actions1, String actions2) {
-        int index = actions2.indexOf(",");
-        if (index == -1) {
-            return isIncluded(actions2, actions1);
-        } else {
-            return implies(actions1, actions2.substring(0, index)) &&
-                   implies(actions1, actions2.substring(index+1));
-        }
-    }
-
-    /**
-     * Checks if given <code>what</code> is included to
-     * <code>where</code> list
-     *
-     * @param what   string to compare
-     * @param where  coma-separated string list to search at
-     *
-     * @return <code>true</code> if <code>what</code> contains in
-     *         the list
-     */
-    private static boolean isIncluded(String what, String where) {
-        StringTokenizer tokens = new StringTokenizer(where, ",");
-        while (tokens.hasMoreElements()) {
-            if (tokens.nextToken().equals(what)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Return true for permission specified actions
-     *
-     * @param action for validation
-     * @param normalizedList allowed actions list
-     *
-     * @return true for valid
-     */
-    private static boolean isValidAction(String actions, String normalizedList) {
-        StringTokenizer tokez = new StringTokenizer(actions, ",");
-        while (tokez.hasMoreElements()) {
-            String action = tokez.nextToken();
-            if (!isIncluded(action, normalizedList)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Returns action list in spec required order
-     *
-     * @param actions unordered and unverified list
-     * @param normalizedList allowed actions list in normalized form
-     *
-     * @return ordered list
-     */
-    public static String verifyAndOrderActions(String actions, String normalizedList) {
-        if(actions == null){
-            throw new IllegalArgumentException(
-                ExceptionMessage.format(ExceptionMessage.DEVICE_NULL_ACTIONS)
-            );
-        }
-        if(actions.length() == 0){
-            throw new IllegalArgumentException(
-                ExceptionMessage.format(ExceptionMessage.DEVICE_EMPTY_ACTIONS)
-            );
-        }
-
-        if (!isValidAction(actions, normalizedList)) {
-            throw new IllegalArgumentException(actions);
-        }
-
-        boolean comma = false;
-        StringBuilder sb = new StringBuilder(30);
-        StringTokenizer tokez = new StringTokenizer(normalizedList, ",");
-        while (tokez.hasMoreElements()) {
-            String validAction = tokez.nextToken();
-            if (isIncluded(validAction, actions)) {
-                if (comma) {
-                    sb.append(',');
-                }
-                sb.append(validAction);
-                comma = true;
-            }
-        }
-
-        return sb.toString();
-    }
-
-    /**
-     * Verifies and order given <code>actions</code> against
-     * DevicePermission actions list
-     *
-     * @param actions unordered and unverified list
-     *
-     * @return ordered and verified list
-     */
-    public static String verifyAndOrderDeviceActions(String actions) {
-        return verifyAndOrderActions(actions, DevicePermission.OPEN + "," + DevicePermission.POWER_MANAGE);
-    }
-}
--- a/src/share/classes/com/oracle/dio/utils/Constants.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/com/oracle/dio/utils/Constants.java	Fri Sep 09 13:20:20 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,17 +33,18 @@
     public static final String FACTORY = "Factory";
     public static final String CONFIG = "Config";
     public static final int INVALID_HANDLE = -1;
-    public static final String PATH = "deviceName";
+    public static final String PATH = "controllerName";
     public static final String IMPL = ".impl.";
     public static final String TYPE = "type";
     public static final String DIRECTION= "direction";
     public static final String INIT_VALUE = "initValue";
     public static final int MAX_WORD_LEN = 32;
-    public static final String DEVICE_NUMBER = "deviceNumber";
+    public static final String DEVICE_NUMBER = "controllerNumber";
     public static final String CHANNEL_NUMBER = "channelNumber";
     public static final String PROPERTIES = "properties";
     public static final String RESOLUTION = "resolution";
     public static final String SAMPLING_INTERVAL = "samplingInterval";
     public static final String ADDRESS = "address";
     public static final String CLOCK_FREQUENCY = "clockFrequency";
+    public static final String SCALE_FACTOR = "scaleFactor";
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/oracle/dio/utils/Utils.java	Fri Sep 09 13:20:20 2016 +0300
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2014, 2015,  Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.dio.utils;
+
+import java.util.StringTokenizer;
+
+import jdk.dio.DeviceConfig;
+import jdk.dio.DevicePermission;
+
+/**
+ * Utility class for device permission class
+ */
+public final class Utils {
+
+    public static final int EMPTY = 0;
+    public static final int DECIMAL_DIGITS = 1;
+    public static final int HEXADECIMAL_DIGITS = 2;
+    public static final int HEXADECIMAL_DIGITS_INTERVAL = 3;
+    /**
+     * Checks if <code>actions1</code> list "implies"
+     * <code>actions2</code> list
+     *
+     * @param actions1 comma-separated list of verified and valid
+     *                 actions
+     * @param actions1 comma-separated list of verified and valid
+     *                 actions
+     *
+     * @return true <code>actions2</code> list is implied by
+     *         <code>actions1</code> list
+     */
+    public static boolean implies(String actions1, String actions2) {
+        int index = actions2.indexOf(",");
+        if (index == -1) {
+            return isIncluded(actions2, actions1);
+        } else {
+            return implies(actions1, actions2.substring(0, index)) &&
+                   implies(actions1, actions2.substring(index+1));
+        }
+    }
+
+    public static String[] getActionsList(String actions) {
+        StringTokenizer tokez = new StringTokenizer(actions, ",", false);
+
+        int count = tokez.countTokens();
+
+        String[] actionsList = new String[count];
+
+        for (int i = 0; i < count; i++) {
+            actionsList[i] = tokez.nextToken();
+        }
+        return actionsList;
+    }
+
+    /**
+     * Checks if given <code>what</code> is included to
+     * <code>where</code> list
+     *
+     * @param what   string to compare
+     * @param where  coma-separated string list to search at
+     *
+     * @return <code>true</code> if <code>what</code> contains in
+     *         the list
+     */
+    private static boolean isIncluded(String what, String where) {
+        StringTokenizer tokens = new StringTokenizer(where, ",");
+        while (tokens.hasMoreElements()) {
+            if (tokens.nextToken().equals(what)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return true for permission specified actions
+     *
+     * @param action for validation
+     * @param normalizedList allowed actions list
+     *
+     * @return true for valid
+     */
+    private static boolean isValidAction(String actions, String normalizedList) {
+        StringTokenizer tokez = new StringTokenizer(actions, ",", true);
+        // detect first empty token
+        boolean lastTokenIsComma = true;
+        while (tokez.hasMoreElements()) {
+            String action = tokez.nextToken();
+            // special case for empty actions that are not returned by StringTokenizer.nextToken() by default
+            if (action.equals(",")) {
+                if (lastTokenIsComma) {
+                    return false;
+                } else {
+                    lastTokenIsComma = true;
+                    continue;
+                }
+            } else {
+                lastTokenIsComma = false;
+            }
+            if (!isIncluded(action, normalizedList)) {
+                return false;
+            }
+        }
+        // detects last empty token as well
+        return !lastTokenIsComma;
+    }
+
+    /**
+     * Returns action list in spec required order
+     *
+     * @param actions unordered and unverified list
+     * @param normalizedList allowed actions list in normalized form
+     *
+     * @return ordered list
+     */
+    public static String verifyAndOrderActions(String actions, String normalizedList) {
+        if(actions == null){
+            throw new IllegalArgumentException(
+                ExceptionMessage.format(ExceptionMessage.DEVICE_NULL_ACTIONS)
+            );
+        }
+        if(actions.length() == 0){
+            throw new IllegalArgumentException(
+                ExceptionMessage.format(ExceptionMessage.DEVICE_EMPTY_ACTIONS)
+            );
+        }
+
+        if (!isValidAction(actions, normalizedList)) {
+            throw new IllegalArgumentException(actions);
+        }
+
+        boolean comma = false;
+        StringBuilder sb = new StringBuilder(30);
+        StringTokenizer tokez = new StringTokenizer(normalizedList, ",");
+        while (tokez.hasMoreElements()) {
+            String validAction = tokez.nextToken();
+            if (isIncluded(validAction, actions)) {
+                if (comma) {
+                    sb.append(',');
+                }
+                sb.append(validAction);
+                comma = true;
+            }
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Verifies and order given <code>actions</code> against
+     * DevicePermission actions list
+     *
+     * @param actions unordered and unverified list
+     *
+     * @return ordered and verified list
+     */
+    public static String verifyAndOrderDeviceActions(String actions) {
+        return verifyAndOrderActions(actions, DevicePermission.OPEN + "," + DevicePermission.POWER_MANAGE);
+    }
+
+    /**
+     * Checks if given value is zero or positive
+     *
+     */
+    public static void checkIntZeroOrPozitive(final int val) {
+        if (DeviceConfig.UNASSIGNED >= val) {
+            throw new IllegalArgumentException(Integer.toString(val));
+        }
+    }
+
+    /**
+     * Checks if given value is UNASSIGNED or zero or positive
+     *
+     */
+    public static void checkIntValue(final int val) {
+        if (DeviceConfig.UNASSIGNED > val) {
+            throw new IllegalArgumentException(Integer.toString(val));
+        }
+    }
+
+    /**
+     * Checks if given value is greater than 0 or UNASSIGNED
+     *
+     */
+    public static void checkGreaterThanZero(final int val) {
+        if (DeviceConfig.UNASSIGNED != val && val < 1){
+            throw new IllegalArgumentException(Integer.toString(val));
+        }
+    }
+
+    /**
+     * Checks if no NaN and positive value
+     */
+    public static void checkDoubleGreaterThanZero(double val) {
+        if (Double.compare(val, 1.0d) < 0 || Double.compare(val, Double.NaN) == 0 || Double.compare(val, Double.POSITIVE_INFINITY) == 0) {
+            throw new IllegalArgumentException(Double.toString(val));
+        }
+    }
+
+    public static String[] parseDevicePermissionName(String name) {
+        name = name.trim();
+        String[] ret = new String[2];
+        int idx = -1;
+        while (-1 != (idx = name.indexOf(':', idx + 1))) {
+            if (idx == 0 || '\\' != name.charAt(idx - 1)) {
+                break;
+            }
+        }
+        if (-1 == idx) {
+            ret[0] = name;
+            ret[1] = "";
+
+        } else {
+            ret[0] = name.substring(0, idx);
+            ret[1] = name.substring(idx + 1);
+        }
+        return ret;
+    }
+
+    // type 0 - decimal digit
+    // type 1 - hexadecimal digit
+    // any other type - check empty string
+    public static void checkDevicePermissionChannelFormat(String name, int type) {
+
+        String channel = parseDevicePermissionName(name)[1];
+
+        if (channel.equals("*") || channel.equals(""))
+            return;
+
+        switch(type) {
+            //decimal digit
+            case DECIMAL_DIGITS:
+               if (!isNonNegativeNumber(channel, 10)) {
+                    throw new IllegalArgumentException();
+                }
+                break;
+            //hexadecimal digit
+            case HEXADECIMAL_DIGITS:
+                if (!isNonNegativeNumber(channel, 16)) {
+                    throw new IllegalArgumentException();
+                }
+                break;
+            case HEXADECIMAL_DIGITS_INTERVAL:
+                if (!isNonNegativeNumberInterval(channel)) {
+                    throw new IllegalArgumentException();
+                }
+                break;
+            default:
+               throw new IllegalArgumentException(name);
+        }
+
+    }
+
+    /** Checks new requested scaled value range e.g. sampling interval range, pulse period range */
+    public static void checkNewScaledRange(final double min_er,
+                                        final double max_er,
+                                        final double new_factor
+                                        ) {
+        // new scaled ones
+        final double min_sr = min_er * new_factor;
+        final double max_sr = max_er * new_factor;
+
+        if (min_sr < 1.0d || max_sr > new Integer(Integer.MAX_VALUE).doubleValue())
+            throw new IllegalArgumentException();
+    }
+
+    // Check all characters in the string are decimal digits
+    private static boolean isNonNegativeNumber(String str, int radix) {
+        try {
+           return Integer.parseInt(str, radix) >= 0;
+        } catch (NumberFormatException e) {
+            return false;
+        }
+    }
+
+    // Check the string has format {hexadecimal}-{hexadecimal}
+    private static boolean isNonNegativeNumberInterval(String str) {
+        int len = str.length();
+        int idx = str.indexOf('-');
+
+        if (-1 == idx || (len - 1) <= idx) {
+            return false;
+        }
+        try {
+            return Long.parseLong(str.substring(0, idx), 16) >=0
+                && Integer.parseInt(str.substring(idx + 1), 16) >= 0;
+        } catch (NumberFormatException e) {
+            return false;
+        }
+    }
+
+}
--- a/src/share/classes/jdk/dio/AsyncErrorHandler.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/AsyncErrorHandler.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,16 +22,16 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 /**
  * The {@code AsyncErrorHandler} interface defines methods for getting notified of errors of
  * asynchronous I/O operations.
- * <p />
+ * <p>
  * Note though that contrarily to how classes implementing sub-interfaces of
- * {@link DeviceEventListener} handle events handling of I/O errors reported through this
+ * {@link DeviceEventListener} handle events, handling of I/O errors reported through this
  * interface is not subject to the same time-sensitivity constrains.
+ * </p>
  *
  * @param <P>
  *            the device type that generates the error.
--- a/src/share/classes/jdk/dio/BufferAccess.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/BufferAccess.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,68 +22,172 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 import java.io.*;
 import java.nio.*;
 
 /**
- * The {@code BufferAccess} interface provides methods for getting access to the device
- * (or the driver thereof) I/O buffers, if any.
+ * The {@code BufferAccess} interface provides methods for getting access to the
+ * device (or the driver thereof) I/O buffers, if any. A device driver may through
+ * this interface provide access to direct buffers that are suitable for efficient
+ * direct I/O operations such as using Direct Memory Access (DMA). This interface
+ * additionally provides a method that wraps an application-provided direct buffer
+ * into a buffer suitable for efficient direct I/O operations.
+ * <p>
+ * The following sample code illustrates how the internal device's buffer might be used
+ * to perform efficient I/O operations (assuming the feature is supported):</p>
+ * <blockquote>
+ * <pre>
+ * <i>// Iterativelly creates a series of samples according to some requirement...</i>
+ * private boolean createSamples(IntBuffer buffer) { ... }
  *
- * @param <B>
- *            the I/O buffer type.
+ * <i>// Generates the sampled output signal; this code is more efficient if all the
+ * // samples to generate fit within the device's output buffer.</i>
+ * try (DACChannel dac = DeviceManager.open(channelID)) {
+ *   IntBuffer buffer = dac.getOutputBuffer();
+ *   while (createSamples(buffer)) { <i>// Directly creates the samples in the driver's internal buffer</i>
+ *     dac.generate(buffer);
+ *     buffer.clear();
+ *   }
+ * } catch (IOException ex) {
+ *   <i>// ...</i>
+ * }
+ * </pre>
+ * </blockquote>
+ * <p>
+ * The following sample code illustrates how an application may use a (pre-allocated) direct buffer to
+ * to perform efficient I/O operations (assuming the feature is supported):</p>
+ * <blockquote>
+ * <pre>
+ *   ByteBuffer someBuffer = ... <i>// Some already allocated buffer</i>
+ *   try (DACChannel dac = DeviceManager.open(channelID)) {
+ *     someBuffer.clear(); <i>// Clear the buffer to make sure its full capacity can be used</i>
+ *     IntBuffer buffer = dac.prepareBuffer(someBuffer, 128);
+ *     if (buffer == null) { <i>// The provided buffer is not direct and/or is not suitable for efficient transfer</i>
+ *       buffer = someBuffer.asIntBuffer(); <i>// The device will default to less efficient transfer mode</i>
+ *     }
+ *     while (createSamples(buffer)) {
+ *       dac.generate(buffer);
+ *       buffer.clear();
+ *     }
+ *   } catch (IOException ex) {
+ *     <i>// ...</i>
+ *   }
+ * }
+ * </pre>
+ * </blockquote>
+ * <p>
+ * Buffers are not safe for use by multiple concurrent threads so care should be
+ * taken to not access the device I/O buffers until any on-going operation has
+ * completed. Interfering with an on-going I/O operation by accessing and
+ * modifying a device I/O buffer concurrently may yield unpredictable results.
+ * </p>
+ *
+ * @param <B> the I/O buffer type.
  * @since 1.0
  */
 @apimarker.API("device-io_1.1")
 public interface BufferAccess<B extends Buffer> {
 
-    /**
-     * Gets the <em>direct</em> input buffer of this device <i>(optional operation)</i>.
-     * <p />
-     * The input buffer will get allocated on a per-application basis to avoid conflicts;
-     * but only one such buffer will be allocated per application. The capacity of the buffer
-     * will be determined based on the property of the underlying device.
-     * <p />
-     * When the returned {@code Buffer} instance is invalidated because the device is either
-     * closed or in exclusive use by some other application then an attempt to access the
-     * {@code Buffer} instance will not change the buffer's content and will cause a
-     * {@code ClosedDeviceException} or some other unspecified exception to be thrown either at
-     * the time of the access or at some later time.
-     *
-     * @return the direct input buffer of this device.
-     * @throws UnsupportedOperationException
-     *             if this device (or driver thereof) does not have or does not allow direct access
-     *             to its input buffer.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     * @throws IOException
-     *             if an I/O error occurred such as the device is not readable.
-     */
-    B getInputBuffer() throws ClosedDeviceException, IOException;
+  /**
+   * Gets the <em>direct</em> input buffer of this device <i>(optional
+   * operation)</i>.
+   * <p>
+   * The input buffer will get allocated on a per-application basis to avoid
+   * conflicts; but only one such buffer will be allocated per application. The
+   * capacity of the buffer will be determined based on the property of the
+   * underlying device.
+   * </p><p>
+   * When the returned {@code Buffer} instance is invalidated because the device
+   * is either closed or in exclusive use by some other application then an
+   * attempt to access the {@code Buffer} instance will not change the buffer's
+   * content and will cause a {@code ClosedDeviceException} or some other
+   * unspecified exception to be thrown either at the time of the access or at
+   * some later time.
+   * </p>
+   *
+   * @return the direct input buffer of this device.
+   * @throws UnsupportedOperationException if this device (or driver thereof)
+   * does not have or does not allow direct access to its input buffer.
+   * @throws ClosedDeviceException if the device has been closed.
+   * @throws IOException if an I/O error occurred such as the device is not
+   * readable.
+   */
+  B getInputBuffer() throws ClosedDeviceException, IOException;
 
-    /**
-     * Gets the <em>direct</em> output buffer of this device <i>(optional operation)</i>.
-     * <p />
-     * The output buffer will get allocated on a per-application basis to avoid conflicts;
-     * but only one such buffer will be allocated per application. The capacity of the buffer
-     * will be determined based on the property of the underlying device.
-     * <p />
-     * When the returned {@code Buffer} instance is invalidated because the device is either
-     * closed or in exclusive use by some other application then an attempt to access the
-     * {@code Buffer} instance will not change the buffer's content and will cause a
-     * {@code ClosedDeviceException} or some other unspecified exception to be thrown either at
-     * the time of the access or at some later time.
-     *
-     * @return the direct output buffer of this device.
-     * @throws UnsupportedOperationException
-     *             if this device (or driver thereof) does not have or does not allow direct access
-     *             to its output buffer.
-     * @throws ClosedDeviceException
-     *             if the device has been closed.
-     * @throws IOException
-     *             if an I/O error occurred such as the device is not writable.
-     */
-    B getOutputBuffer() throws ClosedDeviceException, IOException;
+  /**
+   * Gets the <em>direct</em> output buffer of this device <i>(optional
+   * operation)</i>.
+   * <p>
+   * The output buffer will get allocated on a per-application basis to avoid
+   * conflicts; but only one such buffer will be allocated per application. The
+   * capacity of the buffer will be determined based on the property of the
+   * underlying device.
+   * </p><p>
+   * When the returned {@code Buffer} instance is invalidated because the device
+   * is either closed or in exclusive use by some other application then an
+   * attempt to access the {@code Buffer} instance will not change the buffer's
+   * content and will cause a {@code ClosedDeviceException} or some other
+   * unspecified exception to be thrown either at the time of the access or at
+   * some later time.
+   * </p>
+   *
+   * @return the direct output buffer of this device.
+   * @throws UnsupportedOperationException if this device (or driver thereof)
+   * does not have or does not allow direct access to its output buffer.
+   * @throws ClosedDeviceException if the device has been closed.
+   * @throws IOException if an I/O error occurred such as the device is not
+   * writable.
+   */
+  B getOutputBuffer() throws ClosedDeviceException, IOException;
+
+  /**
+   * Creates a view of the provided {@code ByteBuffer} suitable for efficient
+   * direct I/O transfers of the specified size and of the type required by this
+   * device. If the provided buffer is a direct buffer then the alignment of its current
+   * position, and its limit are checked; if eligible for direct I/O operation, a
+   * new buffer - of the required type - whose content is a shared subsequence of the provided
+   * buffer's content is created as follows:
+   * <ul>
+   * <li>
+   * The content of the new buffer will start at the provided buffer's current
+   * position - adjusted (incremented) for alignment, if necessary.
+   * </li>
+   * <li>
+   * The new buffer's position will be zero, its capacity and its limit will be
+   * be set to the most optimal value lesser or equal to the requested size that
+   * can fit in the number of bytes remaining in the provided buffer - after
+   * adjustment for alignment; its mark will be undefined.
+   * </li>
+   * </ul>
+   * Changes to the provided buffer's content will be visible in the new buffer,
+   * and vice versa; the two buffers' position, limit, and mark values will be
+   * independent. <br>
+   * This device's driver will make a best effort to perform native (e.g. DMA)
+   * I/O operations directly upon the new buffer. If the remaining elements in
+   * the new buffer is less than the requested size then the application will
+   * have to submit the whole I/O operation in several rounds. If the new buffer
+   * is not at its full capacity when submitted for transfer - such as upon the very
+   * last round - then this device's driver may not be able to use efficient
+   * transfer and may resort to a less efficient mode of transfer.
+   * <p>
+   * If the provided buffer is not direct or is not eligible for direct I/O (or
+   * if direct I/O is not supported) then {@code null} is returned. The
+   * provided buffer may still be used for the intended I/O operation but in
+   * this case, the device's driver may resort to less efficient procedures
+   * to perform the I/O operation.
+   * </p>
+   *
+   * @param buffer the buffer to prepare for efficient I/O transfer.
+   * @param size the size of the intended data to transfer.
+   * @return a new buffer suitable for efficient I/O operations mapped onto the
+   * provided buffer, if one can be created; {@code null} otherwise.
+   * @throws IllegalArgumentException if {@code size} is negative.
+   * @throws ClosedDeviceException if the device has been closed.
+   * @throws IOException if some other I/O error occurs.
+   *
+   * @since 1.1
+   */
+  B prepareBuffer(ByteBuffer buffer, int size) throws IOException, ClosedDeviceException;
 }
--- a/src/share/classes/jdk/dio/ClosedDeviceException.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/ClosedDeviceException.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 import java.nio.channels.ClosedChannelException;
--- a/src/share/classes/jdk/dio/Device.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/Device.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,23 +22,52 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 import java.io.IOException;
 import java.nio.channels.Channel;
+import java.nio.ByteOrder;
 
 /**
  * The {@code Device} interface represents devices in the system. This interface
- * provides generic methods for handling devices. <br />
+ * provides generic methods for handling devices. <br>
  * All <i>devices</i> must implement the {@code Device} interface.
- * <p />
+ * <p>
  * When a device is open in shared mode then access synchronization may be performed by
  * invoking {@link #tryLock tryLock} and {@link #unlock unlock}. Device locks are held on a per
  * {@code Device} instance basis. When the same device is open twice in shared access
  * mode by the same application, locking one of the {@code Device} instances will prevent the
  * other form being accessed/used.
- *
+ * </p>
+ * <h3><a name="byte_order">Device Byte Order</a></h3>
+ * <p>
+ * Devices that perform multi-byte value I/O operations have a "native" byte order
+ * (see {@link #getByteOrder getByteOrder}).
+ * Passing to such a device a buffer with a byte order different from its native
+ * byte order may result in byte re-ordering (byte order conversion). These byte
+ * re-ordering may have an impact on performance, memory consumption and I/O throughput.
+ * On resource-constrained platforms a device driver may throw an {@link UnsupportedByteOrderException} when a
+ * byte re-ordering may induce a detrimental loss of quality or performance.
+ * </p>
+ * <h3><a name="locking">Platform Dependencies of the Locking Facility</a></h3>
+ * <p>
+ * The {@link #tryLock tryLock} and {@link #unlock unlock} methods are primarily
+ * intended to prevents other concurrently-running Java applications and threads
+ * from accessing a device locked for exclusive access, provided the device is
+ * accessed through this API. The {@code tryLock} and {@code unlock} methods may
+ * not necessarily map directly to any native locking facility of the underlying
+ * operating system. Thus a lock held on a device may not necessarily be
+ * visible to all programs that have access to the device, regardless of the
+ * language in which those programs are written. Whether or not a lock acquire
+ * through this API actually prevents another program from accessing a locked
+ * device is implementation-dependent as well as system-dependent and therefore
+ * unspecified. A compliant implementation of this specification MUST nevertheless ensure
+ * that a lock held on a device accessed through this API is visible to other
+ * threads running in the same instance of the Java virtual machine (JVM) as
+ * well to other Java applications concurrently running in different instances
+ * of that same JVM.
+ * </p>
+  *
  * @param <P>
  *            the device type the descriptor is defined for.
  * @since 1.0
@@ -60,13 +89,14 @@
     int MIXED_ENDIAN = 2;
 
     /**
-     * Attempts to lock for (platform-wide) exclusive access the underlying device
+     * Attempts to lock for exclusive access the underlying device
      * resource. This method will block until the designated device resource becomes
      * available for exclusive access by this {@code Device} instance or the specified amount of
      * real time has elapsed. A {@code timeout} of {@code 0} means to wait forever.
-     * <p />
+     * <p>
      * This method returns silently if the underlying device resource is open in
      * exclusive access mode or is already acquired for exclusive access (locked).
+     * </p>
      *
      * @param timeout
      *            the timeout in milliseconds.
@@ -86,11 +116,12 @@
      * making it available to other applications. Upon closing the underlying device
      * resource MUST be set to the state (power state and configuration) it was in prior to opening
      * it.
-     * <p />
+     * <p>
      * Once closed, subsequent operations on that very same {@code Device} instance will result
      * in a {@link ClosedDeviceException} being thrown.
-     * <p />
+     * </p><p>
      * This method has no effects if the device has already been closed.
+     * </p>
      *
      * @throws IOException
      *             if an I/O error occurs.
@@ -107,11 +138,12 @@
     boolean isOpen();
 
     /**
-     * Releases from (platform-wide) exclusive access the underlying device resource.
-     * <p />
+     * Releases from exclusive access the underlying device resource.
+     * <p>
      * This method returns silently if the underlying device resource is either open in
      * exclusive access mode or is not currently acquired for exclusive access (locked) or has
      * already been closed.
+     * </p>
      *
      * @throws IOException
      *             if any other I/O error occurred.
@@ -129,4 +161,23 @@
      *         information of this device.
      */
     <U extends P> DeviceDescriptor<U> getDescriptor();
+
+    /**
+     * Retrieves this device's byte order.
+     * <p>
+     * The byte order is used when performing multi-byte value I/O operations.
+     * </p>
+     *
+     * @return this buffer's byte order.
+     *
+     * @throws IOException
+     *             if some other I/O error occurs.
+     * @throws UnavailableDeviceException
+     *             if this device is not currently available - such as it is locked by another application.
+     * @throws ClosedDeviceException
+     *             if the device has been closed.
+     *
+     * @since 1.1
+     */
+    ByteOrder getByteOrder() throws IOException, UnavailableDeviceException, ClosedDeviceException;
 }
--- a/src/share/classes/jdk/dio/DeviceAlreadyExistsException.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/DeviceAlreadyExistsException.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 /**
@@ -48,7 +47,7 @@
      * {@link Throwable#getMessage() getMessage} method.
      *
      * @param message
-     *            the detailed reason of the exception.
+     *            the detailed reason of the exception (may be {@code null}).
      */
     public DeviceAlreadyExistsException(String message) {
         super(message);
--- a/src/share/classes/jdk/dio/DeviceConfig.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/DeviceConfig.java	Fri Sep 09 13:20:20 2016 +0300
@@ -24,77 +24,210 @@
  */
 
 package jdk.dio;
+import java.io.IOException;
+import java.io.OutputStream;
 
 /**
- * The {@code DeviceConfig} class is a tagging interface for all device configuration
- * classes.
- * <p />
- * A device configuration contains the following elements:
+ * The {@code DeviceConfig} class is the base interface for all device
+ * configuration classes.
+ * <p>
+ * A device's configuration consists of the following elements:
+ * </p>
+ * <blockquote>
  * <dl>
  * <dt><b>Hardware Addressing Information</b></dt>
- * <dd>Information required to address the device. Examples are an I2C bus number and an
- * I2C slave device address or a GPIO controller number and pin index.</dd>
+ * <dd>Information required to address the device. Examples are an I2C bus
+ * number and an I2C slave device address or a GPIO controller number and pin
+ * index.</dd>
  * <dt><b>Static Configuration Parameters</b></dt>
- * <dd>Configuration parameters that must be set before the device is opened and which
- * may not be changed afterwards. Examples are an SPI slave device clock mode or word length.</dd>
+ * <dd>Configuration parameters that must be set upon opening the device and
+ * which may not be changed afterwards. Examples are an SPI slave device clock
+ * mode or word length.</dd>
  * <dt><b>Dynamic Configuration Parameters</b></dt>
- * <dd>Configuration parameters for which a default value may be set before the device is
- * opened and which may still be changed while the device is open. Dynamic configuration
- * parameters can be changed after the device is open through methods of
- * {@link Device} sub-interfaces. Examples are a UART baud rate or the current direction of a
- * bidirectional GPIO pin.</dd>
+ * <dd>Configuration parameters for which an initial value is set upon opening the
+ * device and that an application may change while the device is still open.
+ * Dynamic configuration parameters can be changed after the device is open
+ * through methods of {@link Device} sub-interfaces. Examples are a UART baud
+ * rate or the current direction of a bidirectional GPIO pin.
+ * The initial values
+ * of dynamic configuration parameters are initial <em>default</em> values from
+ * the point of view of the application accessing the device. Runtime changes
+ * to the values of dynamic configuration parameters are not reflected in the
+ * {@code DeviceConfig} object of that device, which retains its initial values.
+ * </dd>
  * </dl>
- * {@code DeviceConfig} instances should be immutable. <br />
- * A compliant implementation of this specification MUST ensure that information encapsulated in a
- * {@code DeviceConfig} instance cannot be altered while it is handling it and SHOULD either
- * create its own private copy of the instance or of the information it contains.
- * <p />
- * Some hardware addressing parameter, and static and dynamic configuration parameters may be set to
- * {@link #DEFAULT}. Whether such default settings are supported is platform- as well as device
- * driver-dependent.
- * <p />
- * An instance of {@code DeviceConfig} can be passed to the
- * {@link DeviceManager#open(DeviceConfig)} or
- * {@link DeviceManager#open(Class, DeviceConfig)} method to open the designated device
- * device with the specified configuration. A {@link InvalidDeviceConfigException} is thrown
- * when attempting to open a device with an invalid or unsupported configuration.
+ * </blockquote>
+ * The {@link DeviceManager#open(DeviceConfig) open(DeviceConfig, ...)} and
+ * {@link DeviceManager#open(Class, DeviceConfig) open(Class, DeviceConfig, ...)}
+ * methods of the {@link DeviceManager} can be used to open a device and obtain
+ * a {@code Device} instance to access it. The device to open is designated by
+ * the hardware addressing information encapsulated in the provided {@code DeviceConfig} object;
+ * it is then configured according to the static and runtime configuration parameters
+ * encapsulated in the same provided {@code DeviceConfig} object. If the device
+ * designated by the provided hardware addressing information cannot be found a
+ * {@link DeviceNotFoundException} is thrown. If a static or runtime configuration
+ * parameter or a combination thereof is not valid or not supported a
+ * {@link InvalidDeviceConfigException}.
+ * <h3><a name="immutability">Immutability of {@code DeviceConfig} Objects</a></h3>
+ * {@code DeviceConfig} objects should be immutable. If a
+ * {@code DeviceConfig}-implementing class is not immutable it should implement
+ * the {@link java.lang.Cloneable} interface. A compliant implementation of this
+ * specification MUST do its best to ensure that information encapsulated in a
+ * {@code DeviceConfig} instance cannot be altered while it is handling it and
+ * SHOULD, when necessary (that is when an instance is not considered
+ * immutable), create its own private copy either of the instance (such as by
+ * cloning it) or of the information it contains. If a
+ * {@code DeviceConfig}-implementing class does not implement the
+ * {@code Cloneable} interface then it SHALL - for that purpose - be considered
+ * immutable.<br>
+ * As per the above requirements, a compliant implementation of this specification
+ * may return the same (immutable) {@code DeviceConfig} instance over several calls;
+ * an application must therefore not synchronize on {@code DeviceConfig} objects.
+ * <h3><a name="persistency">Persistency of {@code DeviceConfig} Objects</a></h3>
+ * A compliant implementation of this specification MUST support the persistence
+ * of the device configuration registry across platform reboots; it MUST guarantee
+ * in particular that a device configuration registered by an application remains
+ * registered after the application has terminated and across platform reboots
+ * until it is explictly unregistered by an application (possibly the same)
+ * that has been granted the necessary permissions.<br>
+ * To allow for persistency of the device configuration registry, {@code DeviceConfig}
+ * objects must support saving their states to an {@code OutputStream}
+ * and restoring their states from an {@code InputStream}. The
+ * {@code DeviceManager} saves the state of an {@code DeviceConfig} object by invoking
+ * its {@link #serialize(java.io.OutputStream) serialize} method. The
+ * {@code DeviceManager} restores the state of an {@code DeviceConfig} object by invoking
+ * the {@link jdk.dio.spi.DeviceProvider#deserialize(java.io.InputStream) deserialize}
+ * on its associated {@link jdk.dio.spi.DeviceProvider DeviceProvider}.<br>
+ * On the Java Platform Standard Edition, these methods may delegate to the Object Serialization
+ * framework.
+ * In order to facilitate the implementation of compound or layered device abstractions,
+ * on the Java Platform Micro Edition, which does not support Object Serialization,
+ * {@code DeviceConfig}-implementing classes should provide methods for creating new instances
+ * initialized from an {@code InputStream}; see example below:
+ * <blockquote>
+ *   <pre>
+ * public class RealTimeClockConfig implements DeviceConfig&lt;RealTimeClock&gt;, HardwareAddressing {
  *
- * @param <P>
- *            the device type the configuration is defined for.
+ *   private MMIODeviceConfig mmioConfig;
+ *
+ *   public RealTimeClockConfig(MMIODeviceConfig mmioConfig) {
+ *     this.mmioConfig = mmioConfig;
+ *   }
+ *
+ *   <em>public static RealTimeClockConfig deserialize(InputStream in) throws IOException {
+ *     return new RealTimeClockConfig(MMIODeviceConfig.deserialize(in));
+ *   }</em>
+ *
+ *   ...
+ *
+ *   public MMIODeviceConfig getMmioConfig() {
+ *     return mmioConfig;
+ *   }
+ *
+ *   &#64;Override
+ *   public int serialize(OutputStream out) throws IOException {
+ *     return mmioConfig.serialize(out);
+ *   }
+ * }
+ *   </pre>
+ * </blockquote>
+ * <h3><a name="default_unassigned">Unassigned, Default or Unused Parameter Values</a></h3>
+ * Some hardware addressing, static or dynamic configuration parameters may be
+ * set to {@link #UNASSIGNED UNASSIGNED} (or {@code null}) when opening or registering a
+ * device configuration. Device drivers may substitute hardware addressing parameters
+ * and static and dynamic configuration parameters
+ * set to {@link #UNASSIGNED UNASSIGNED} (or {@code null}) with actual default values;
+ * whether such default settings are supported is platform- as well as device driver-dependent;
+ * if a required parameter is set to {@link #UNASSIGNED UNASSIGNED} (or {@code null}) the device driver
+ * MUST reject the configuration and throw an {@link InvalidDeviceConfigException}.
+ * When querying the configuration of an open device using the
+ * {@link DeviceDescriptor#getConfiguration DeviceDescriptor.getConfiguration}
+ * method the actual settings are returned; parameters that are neither supported
+ * nor required by the underlying hardware or driver are still set to {@link #UNASSIGNED UNASSIGNED}
+ * (or {@code null}); whether or not this is the case when listing registered
+ * device configuration using the {@link DeviceManager#list DeviceManager.list}
+ * methods depends on whether the device could be probed upon registration
+ * of the configuration (see <a href="{@docRoot}/jdk/dio/DeviceManager.html#probing">Device Probing</a>).
+ *
+ * @param <P> the device type the configuration is defined for.
  * @see DeviceManager#open(DeviceConfig)
+ * @see DeviceManager#open(DeviceConfig, int)
  * @see DeviceManager#open(Class, DeviceConfig)
+ * @see DeviceManager#open(Class, DeviceConfig, int)
+ * @see DeviceManager#list
+ * @see DeviceDescriptor#getConfiguration
  * @see InvalidDeviceConfigException
  * @since 1.0
  */
 @apimarker.API("device-io_1.1")
 public interface DeviceConfig<P extends Device<? super P>> {
 
-    /**
-     * Used to indicate that the default value of a configuration parameter should be used.
-     */
-    int DEFAULT = -1;
+  /**
+   * Used to indicate that the default value of a hardware addressing or
+   * configuration parameter is requested upon opening or registering a device
+   * configuration or to indicate that a configuration parameter is unassigned
+   * (such as when it is not supported).
+   * @deprecated As of 1.1 replaced by {@link #UNASSIGNED UNASSIGNED}.
+   */
+    @Deprecated
+  int DEFAULT = -1;
+  /**
+   * Used to indicate that the default value of a hardware addressing or
+   * configuration parameter is requested upon opening or registering a device
+   * configuration or to indicate that a configuration parameter is unused
+   * (such as when it is neither supported nor required by the underlying hardware or driver).
+   */
+  int UNASSIGNED = -1;
+
+  /**
+   * The {@code HardwareAddressing} interface defines an abstraction of an
+   * hardware addressing information common on different platforms.
+   * <p>
+   * When a device's {@code HardwareAddressing} contains both a specific controller number
+   * (see {@link #getControllerNumber getControllerNumber}) and a specific controller name (see {@link #getControllerName getControllerName})
+   * a compliant implementation of this specification MUST only use the controller number
+   * for addressing the device and for permission checks.
+   * </p>
+   *
+   * @since 1.0
+   */
+  @apimarker.API("device-io_1.1")
+  public interface HardwareAddressing {
 
     /**
-     * The {@code HardwareAddressing} interface defines an abstraction of an hardware addressing
-     * information common on different platforms.
+     * Gets the controller number.
      *
-     * @since 1.0
+     * @return the controller number (a positive or zero integer) or
+     * {@link #UNASSIGNED UNASSIGNED} if no specific value is requested or no actual value is
+     * assigned (see
+     * <a href="{@docRoot}/jdk/dio/DeviceConfig.html#default_unassigned">Unassigned, Default or Unused Parameter Values</a>).
      */
-    @apimarker.API("device-io_1.1")
-    public interface HardwareAddressing {
+    int getControllerNumber();
 
-        /**
-         * Gets the controller number.
-         *
-         * @return the controller number (a positive or zero integer) or {@link #DEFAULT}.
-         */
-        int getControllerNumber();
+    /**
+     * Gets the controller name (such as a <em>device file</em> name on UNIX
+     * systems).
+     *
+     * @return the controller name or {@code null} if no specific value is
+     * requested or no actual value is assigned (see
+     * <a href="{@docRoot}/jdk/dio/DeviceConfig.html#default_unassigned">Unassigned, Default or Unused Parameter Values</a>).
+     */
+    String getControllerName();
+  }
 
-        /**
-         * Gets the controller name (such as a <em>device file</em> name on UNIX systems).
-         *
-         * @return the controller name or {@code null}.
-         */
-        String getControllerName();
-    }
+  /**
+   * Serializes the state of this {@code DeviceConfig} object to the specified
+   * {@code OutputStream}. This method may be invoked by the
+   * {@link jdk.dio.DeviceManager DeviceManager} to save the state of a
+   * {@code DeviceConfig} object to a persistent store in order to support
+   * persistence of device configuration registration.
+   *
+   * @param out the stream to write to.
+   * @return the number of bytes written to the stream.
+   * @throws IOException if an I/O error occurs.
+   *
+   * @see jdk.dio.spi.DeviceProvider#deserialize(java.io.InputStream)
+   * @since 1.1
+   */
+  int serialize(OutputStream out) throws IOException;
 }
--- a/src/share/classes/jdk/dio/DeviceDescriptor.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/DeviceDescriptor.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 /**
@@ -77,7 +76,10 @@
     Class<P> getInterface();
 
     /**
-     * Returns the registered configuration of the device.
+     * Returns the actual configuration of the device. The actual settings are returned;
+     * {@link DeviceConfig#UNASSIGNED} (or {@code null}) may still be returned for a
+     * hardware addressing, static or dynamic configuration parameter
+     * to indicate that it is unassigned (such as when it is not supported).
      *
      * @param <C>
      *            the device configuration type.
--- a/src/share/classes/jdk/dio/DeviceEvent.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/DeviceEvent.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,15 +22,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 /**
  * The {@code DeviceEvent} class encapsulates events fired by or on behalf of a
  * device. An event may correspond to an hardware interrupt or to some software signal.
- * <p />
+ * <p>
  * When an event burst occurs - that is more events occurred than can be handled - events may be
  * coalesced. Coalescing of events is platform and device-dependent.
+ * </p>
  *
  * @param <P>
  *            the device type the event is defined for.
@@ -50,11 +50,12 @@
      */
     protected long lastTimeStamp;
     /**
-     * The additional microseconds to the timestamp for when the last coalesced event occurred. If
+     * The additional microseconds (in the range {@code [0 - 999]}) to the timestamp for when the last coalesced event occurred. If
      * events were not coalesced then this is the same as that of the first event.
-     * <p />
+     * <p>
      * The actual last timestamp in microseconds is equal to: <i>(lastTimeStamp * 1000) +
      * lastTimeStampMicros</i>.
+     * </p>
      */
     protected int lastTimeStampMicros;
     /**
@@ -67,11 +68,12 @@
      */
     protected long timeStamp;
     /**
-     * The additional microseconds to the timestamp for when this event (first) occurred. If events
+     * The additional microseconds (in the range {@code [0 - 999]}) to the timestamp for when this event (first) occurred. If events
      * were coalesced then this is that of the first event.
-     * <p />
+     * <p>
      * The actual timestamp in microseconds is equal to: <i>(timeStamp * 1000) +
      * timeStampMicros</i>.
+     * </p>
      */
     protected int timeStampMicros;
 
@@ -80,7 +82,7 @@
      * may represent.
      *
      * @return the number of underlying coalesced hardware interrupts software signals this event
-     *         may represent.
+     *         may represent; {@code 1} if no coalescing occurred.
      */
     public final int getCount() {
         return count;
@@ -100,7 +102,7 @@
      * Returns the additional microseconds to the timestamp for when the last coalesced event
      * occurred. If events were not coalesced then this is the same as that of the first event.
      *
-     * @return the additional microseconds to the timestamp for when the last coalesced event
+     * @return the additional microseconds (in the range {@code [0 - 999]}) to the timestamp for when the last coalesced event
      *         occurred.
      */
     public final int getLastTimeStampMicros() {
@@ -131,7 +133,7 @@
      * Returns the additional microseconds to the timestamp for when this event (first) occurred. If
      * events were coalesced then the time is that of the first event.
      *
-     * @return the additional microseconds to the timestamp for when this event (first) occurred.
+     * @return the additional microseconds (in the range {@code [0 - 999]}) to the timestamp for when this event (first) occurred.
      */
     public final int getTimeStampMicros() {
         return timeStampMicros;
--- a/src/share/classes/jdk/dio/DeviceEventListener.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/DeviceEventListener.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,22 +22,26 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 /**
  * The {@code DeviceEventListener} interface is a tagging interface that all event listeners
  * must implement. Event listeners provide methods for notifying applications of the occurrence of
  * events (hardware interrupts or software signals) on devices.
- * <p />
- * An event listener should implement the following requirements:
+ * <p>
+ * An event listener should implement the following requirements:</p>
  * <ul>
  * <li>it should be implemented to be as fast as possible; for example it should not call any
  * operations that may block, nor pause the current thread.</li>
  * <li>it should not throw any unchecked exception.</li>
  * </ul>
+ * <p>
  * A compliant implementation of this specification MUST catch unchecked exceptions that may be
  * thrown by a listener.
+ * </p><p>
+ * A compliant implementation of this specification MUST serialize the notifications
+ * to the same {@code DeviceEventListener} instance.
+ * </p>
  *
  * @since 1.0
  */
--- a/src/share/classes/jdk/dio/DeviceException.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/DeviceException.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 import java.io.IOException;
@@ -49,7 +48,7 @@
      * {@link Throwable#getMessage() getMessage} method.
      *
      * @param message
-     *            the detailed reason of the exception.
+     *            the detailed reason of the exception (may be {@code null}).
      */
     public DeviceException(String message) {
         super(message);
--- a/src/share/classes/jdk/dio/DeviceManager.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/DeviceManager.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 import java.io.IOException;
@@ -38,64 +37,66 @@
 import com.oracle.dio.registry.RegistrationEventHandler;
 import com.oracle.dio.registry.RegistrationEventSender;
 import com.oracle.dio.registry.Registry;
+import com.oracle.dio.utils.Constants;
+import com.oracle.dio.utils.ExceptionMessage;
+import com.oracle.dio.utils.Logging;
+import com.oracle.dio.utils.PrivilegeController;
+import com.oracle.dio.utils.PrivilegedAction;
 
 import jdk.dio.spi.DeviceProvider;
+
 import romizer.Local;
 
-import com.oracle.dio.utils.Constants;
-import com.oracle.dio.utils.PrivilegeController;
-import com.oracle.dio.utils.PrivilegedAction;
-import com.oracle.dio.utils.ExceptionMessage;
-
 /**
  * The {@code DeviceManager} class provides methods for opening and registering
- * devices that can then be handled as {@link Device} instances. A {@code Device} instance
+ * devices that can then be handled as {@link Device} instances. A device
  * of a particular type can be opened using its platform-specific numeric ID or name as well as
  * its properties or using an ad-hoc configuration (in which case, its hardware addressing
  * information must be explicitly provided).
- * <p />
- * A {@code Device} instance may be identified by a numeric ID. This ID is unrelated to the
+ * <p>
+ * A device may be identified by a numeric ID. This ID is unrelated to the
  * hardware number (hardware addressing information) that may be used to identify a device such as a
  * GPIO pin number or an I2C slave device address. A device ID typically corresponds to a
  * registered configuration for a device. The numeric ID of a device must be
  * greater than or equal to {@code 0} and must be unique. Yet the same device may be
  * directly and indirectly mapped through several IDs; each ID may correspond to a different
  * configuration, representation or abstraction for the same underlying device hardware
- * resource. <br />
- * A {@code Device} instance opened with an ad-hoc configuration - that is: not
+ * resource.<br>
+ * A device opened with an ad-hoc configuration - that is: not
  * through one of its registered configurations - is not assigned a numeric ID nor a name. Its
  * numeric ID and name are both undefined and set respectively to
  * {@link DeviceDescriptor#UNDEFINED_ID UNDEFINED_ID} and {@code null}.
- * <p />
+ * </p><p>
  * Devices may be opened in either <a href="{@docRoot}/overview-summary.html#access-model">
  * <em>exclusive</em> or <em>shared</em> mode</a>. By default,
  * devices are opened in exclusive mode. Whether a device can be opened in
  * shared mode depends on the underlying device hardware as well as on the underlying
  * device driver. It also depends on whether the provided {@code Device} implementation is a
  * <em>dedicated</em>, <em>virtualized</em> or <em>shared</em> abstraction of the underlying
- * device resource. <br />
+ * device resource. <br>
  * When a device is open with an ad-hoc configuration in shared mode then the
  * {@code Device} implementation (or driver) may throw a
  * {@link InvalidDeviceConfigException} if the device is already open and the
- * requested adhoc configuration is incompatible with the current configuration of the device
- * device. <br />
+ * requested adhoc configuration is incompatible with the current configuration of the
+ * device. <br>
  * When a device is open in shared mode then some explicit means of access
  * synchronization may have to be used such as by invoking {@link Device#tryLock Device.tryLock} and
  * {@link Device#unlock Device.unlock}. Device locks are held on a per {@code Device} instance basis.
  * When the same device is open twice in shared access mode by the same application,
  * locking one of the {@code Device} instances will prevent the other from being accessed/used.
- * <p />
- * Opening a {@code Device} instance of a specific type with a registered configuration is
- * subject to permission checks (see {@link DeviceMgmtPermission#OPEN}). <br />
- * Opening a {@code Device} instance of a specific type with an ad-hoc configuration is subject
+ * </p><p>
+ * Opening a device of a specific type with a registered configuration is
+ * subject to permission checks (see {@link DeviceMgmtPermission#OPEN}).<br>
+ * Opening a device of a specific type with an ad-hoc configuration is subject
  * to permission checks specific for that type (for example see
  * {@link jdk.dio.gpio.GPIOPinPermission GPIOPinPermission.OPEN}). This permission check
  * should be implemented by the {@link jdk.dio.spi.DeviceProvider#open
- * DeviceProvider.open} method. <br />
+ * DeviceProvider.open} method. <br>
  * Registration and unregistration of devices are subject to permission checks (see
  * {@link DeviceMgmtPermission#REGISTER} and {@link DeviceMgmtPermission#UNREGISTER}).
- * <br />
+ * <br>
  * For more details see <a href="{@docRoot}/overview-summary.html#security-model">Security Model</a>.
+ * </p>
  * <h3><a name="probing">Device Probing</a></h3>
  * For some peripheral hardware such as I2C bus or SPI bus, opening (or registering) a device
  * such as a slave device on a bus does not necessarily entail immediately
@@ -105,11 +106,11 @@
  * for device determines that the device does not exist or is not addressable
  * or, that it does not support the requested configuration a
  * {@code DeviceNotFoundException} or respectively an
- * {@code InvalidDeviceConfigException} is thrown. If the underlying platform or
- * driver does not implement any probing facility then a {@code Device} instance
- * is returned; I/O operations on the device will later fail - typically with an
- * {@code IOException} - if the device does not exist or is not addressable or,
- * if it does not support the requested configuration.
+ * {@code InvalidDeviceConfigException} is thrown. When the underlying platform or
+ * driver does not implement any probing facility a {@code Device} instance
+ * is returned, but I/O operations on the device will later fail - typically with an
+ * {@code IOException} - if the device does not exist, is not addressable, or
+ * does not support the requested configuration.
  *
  * @see UnavailableDeviceException
  * @see DeviceMgmtPermission
@@ -122,14 +123,16 @@
 public class DeviceManager {
     /**
      * Exclusive access mode.
-     * <p />
+     * <p>
      * This bit flag can be bitwise-combined (OR) with other access mode bit flags.
+     * </p>
      */
     public static final int EXCLUSIVE = 1;
     /**
      * Shared access mode.
-     * <p />
+     * <p>
      * This bit flag can be bitwise-combined (OR) with other access mode bit flags.
+     * </p>
      */
     public static final int SHARED = 2;
 
@@ -178,30 +181,28 @@
     }
 
     /**
-     * Opens a {@code Device} instance of the specified type with the specified hardware
-     * addressing information and configuration. The specified device type and specified
-     * configuration type must be compatible. An instance of the first <em>available</em>
-     * matching {@code Device} is returned. If a matching {@code Device} is already open
-     * (therefore <em>not available</em>) the next matching {@code Device} is considered.
-     * <p />
-     * Opening a {@code Device} instance with hardware addressing information and configuration
+     * Opens a device, returning a {@code Device} instance of the specified type to access it.
+     * The device to open is designated by the provided hardware addressing information and is
+     * initially set-up according to the specified configuration. The specified device type and specified
+     * configuration type must be compatible.
+     * <p>
+     * Opening a device from its hardware addressing information and with an ad-hoc configuration
      * may be subject to <a href="#probing">device probing limitations </a>.
-     * <p />
+     * </p><p>
      * The device is opened in exclusive access mode.
-     * <p />
+     * </p><p>
      * The returned {@code Device} instance's ID and name are undefined.
-     * <p />
      * A new instance is returned upon each call.
+     * </p>
      *
      * @param <P>
      *            the type of the device to open.
      * @param intf
-     *            the interface (sub-interface of {@code Device}) of the device being looked
-     *            up.
+     *            the interface (sub-interface of {@code Device}) of the device to open.
      * @param config
      *            the device configuration (which includes hardware addressing information as
      *            well as configuration parameters).
-     * @return a {@code Device} instance for the specified configuration.
+     * @return a new {@code Device} instance to access the designated device.
      * @throws UnsupportedDeviceTypeException
      *             if the designated device type is not supported.
      * @throws InvalidDeviceConfigException
@@ -230,35 +231,33 @@
     }
 
     /**
-     * Opens a {@code Device} instance of the specified type with the specified hardware
-     * addressing information and configuration. The specified device type and specified
-     * configuration type must be compatible. An instance of the first <em>available</em> matching {@code Device}
-     * is returned. If a matching {@code Device} is already open in a mode that is not
-     * compatible with the requested mode the next matching {@code Device} is considered.
-     * <p />
-     * Opening a {@code Device} instance with hardware addressing information and configuration
+     * Opens a device, returning a {@code Device} instance of the specified type to access it.
+     * The device to open is designated by the provided hardware addressing information and is
+     * initially set-up according to the specified configuration. The specified device type and specified
+     * configuration type must be compatible.
+     * <p>
+     * Opening a device from its hardware addressing information and with an ad-hoc configuration
      * may be subject to <a href="#probing">device probing limitations </a>.
-     * <p />
+     * </p><p>
      * The device is opened in the designated access mode. A device may be
      * opened in shared mode if supported by the underlying driver and hardware and if it is not
      * already opened in exclusive mode. A device may be opened in exclusive mode if
      * supported by the underlying driver and hardware and if it is not already opened.
-     * <p />
+     * </p><p>
      * The returned {@code Device} instance's ID and name are undefined.
-     * <p />
      * A new instance is returned upon each call.
+     * </p>
      *
      * @param <P>
      *            the type of the device to open.
      * @param intf
-     *            the interface (sub-interface of {@code Device}) of the device being looked
-     *            up.
+     *            the interface (sub-interface of {@code Device}) of the device to open.
      * @param config
      *            the device configuration (which includes hardware addressing information as
      *            well as configuration parameters).
      * @param mode
      *            the access mode, one of: {@link #EXCLUSIVE} or {@link #SHARED}.
-     * @return a {@code Device} instance for the specified configuration.
+     * @return a new {@code Device} instance to access the designated device.
      * @throws UnsupportedDeviceTypeException
      *             if the designated device type is not supported.
      * @throws InvalidDeviceConfigException
@@ -285,7 +284,7 @@
      *             is not applicable to the device type specified by {@code intf}.
      */
     public static <P extends Device<? super P>> P open(Class<P> intf, DeviceConfig<? super P> config, int mode)
-    throws IOException, InvalidDeviceConfigException, UnsupportedDeviceTypeException,
+            throws IOException, InvalidDeviceConfigException, UnsupportedDeviceTypeException,
             DeviceNotFoundException, UnavailableDeviceException, UnsupportedAccessModeException {
 
         if (null == intf) {
@@ -306,13 +305,12 @@
             );
         }
         checkMode(mode);
-
+        PeripheralDescriptorImpl<P> descr = new PeripheralDescriptorImpl(UNSPECIFIED_ID, null, config, intf, null);
         if (null != intf) {
-            PeripheralDescriptorImpl<DeviceConfig<P>, P> descr = new PeripheralDescriptorImpl(UNSPECIFIED_ID, null, config, intf, null);
             try {
                 return ((PeripheralFactory<P>)getFactory(intf)).create(descr, mode);
             } catch (DeviceNotFoundException | UnsupportedDeviceTypeException e) {
-                P res = (P)loadFromDriver(config, mode);
+                P res = (P)loadFromDriver(descr, mode);
                 if (null == res) {
                     throw e;
                 }
@@ -321,7 +319,7 @@
         } else {
             // special case: getDefaultType returns null that means config is not for embedded drivers
             // try to load from installed drivers
-            P res = (P)loadFromDriver(config, mode);
+            P res = (P)loadFromDriver(descr, mode);
             if (null == res) {
                 throw new UnsupportedDeviceTypeException(config.toString());
             }
@@ -330,17 +328,21 @@
     }
 
     /**
-     * Looks up and opens a {@code Device} instance for the provided numeric ID.
-     * <p />
+     * Looks up then opens the device designated by the provided numeric ID,
+     * returning a {@code Device} instance to access it.
+     * The device configuration registered for the provided ID is first looked up;
+     * the device designated by the retrieved hardware addressing information is open and is
+     * initially set-up according to the registered configuration.
+     * <p>
      * The device is opened in exclusive access mode.
-     * <p />
      * A new instance is returned upon each call.
+     * </p>
      *
      * @param <P>
      *            the type of the device to open.
      * @param id
      *            the numeric device id.
-     * @return a {@code Device} instance for the given numeric ID.
+     * @return a new {@code Device} instance to access the designated device.
      * @throws DeviceNotFoundException
      *             if the designated device is not found.
      * @throws UnavailableDeviceException
@@ -366,11 +368,16 @@
     }
 
     /**
-     * Looks up and opens a {@code Device} instance for the provided numeric ID and type.
-     * <p />
+     * Looks up then opens the device designated by the provided numeric ID and type,
+     * returning a {@code Device} instance of the specified type to access it.
+     * The device configuration registered for the provided ID is first looked up;
+     * the device designated by the retrieved hardware addressing information is open and is
+     * initially set-up according to the registered configuration. The specified device type and retrieved
+     * configuration type must be compatible.
+     * <p>
      * The device is opened in exclusive access mode.
-     * <p />
      * A new instance is returned upon each call.
+     * </p>
      *
      * @param <P>
      *            the type of the device to open.
@@ -379,7 +386,7 @@
      * @param intf
      *            the interface (sub-interface of {@code Device}) of the device being looked
      *            up.
-     * @return a {@code Device} instance for the given numeric ID.
+     * @return a new {@code Device} instance to access the designated device.
      * @throws DeviceNotFoundException
      *             if the designated device is not found.
      * @throws UnsupportedDeviceTypeException
@@ -409,14 +416,20 @@
     }
 
     /**
-     * Looks up and opens a {@code Device} instance for the provided numeric ID and type.
-     * <p />
+     * Looks up then opens the device designated by the provided numeric ID and type,
+     * returning a {@code Device} instance of the specified type to access it.
+     * The device configuration registered for the provided ID is first looked up;
+     * the device designated by the retrieved hardware addressing information is open and is
+     * initially set-up according to the registered configuration. The specified device type and retrieved
+     * configuration type must be compatible.
+     * <p>
      * The device is opened in the designated access mode. A device may be
      * opened in shared mode if supported by the underlying driver and hardware and if it is not
      * already opened in exclusive mode. A device may be opened in exclusive mode if
      * supported by the underlying driver and hardware and if it is not already opened.
-     * <p />
+     * </p><p>
      * A new instance is returned upon each call.
+     * </p>
      *
      * @param <P>
      *            the type of the device to open.
@@ -427,7 +440,7 @@
      *            up.
      * @param mode
      *            the access mode, one of: {@link #EXCLUSIVE} or {@link #SHARED}.
-     * @return a {@code Device} instance for the given numeric ID.
+     * @return a new {@code Device} instance to access the designated device.
      * @throws UnsupportedDeviceTypeException
      *             if the designated device type is not supported.
      * @throws DeviceNotFoundException
@@ -450,14 +463,20 @@
     public static <P extends Device<? super P>> P open(int id, Class<P> intf, int mode) throws IOException,
         UnsupportedDeviceTypeException, DeviceNotFoundException, UnavailableDeviceException,
         UnsupportedAccessModeException {
-        checkID(id);
+        Registry.checkID(id);
+
+        do {
+            AccessController.checkPermission(new DeviceMgmtPermission("*:" + id, DeviceMgmtPermission.OPEN));
+        } while (false);
+
+
         checkMode(mode);
         if (null == intf) {
             throw new NullPointerException(
                 ExceptionMessage.format(ExceptionMessage.DEVICE_NULL_INTF)
             );
         }
-        DeviceDescriptor<P> descr = Registry.getInstance().get(id);
+        PeripheralDescriptorImpl<P> descr = (PeripheralDescriptorImpl<P>)Registry.getInstance().get(id);
         if (null == descr) {
             throw new DeviceNotFoundException(
                 ExceptionMessage.format(ExceptionMessage.DEVICE_NOT_FOUND, String.valueOf(id))
@@ -470,11 +489,6 @@
             );
         }
 
-        do {
-            String name = (null == descr.getName()) ? ":" + id : descr.getName() + ":" + id;
-            AccessController.checkPermission(new DeviceMgmtPermission(name, DeviceMgmtPermission.OPEN));
-        } while (false);
-
         try {
             final PeripheralFactory<P> f = getFactory(descr.getInterface());
             final DeviceDescriptor<P> fdescr = descr;
@@ -487,8 +501,7 @@
         } catch (InvalidDeviceConfigException e) {
             throw new DeviceNotFoundException(e.getMessage());
         } catch (DeviceNotFoundException | UnsupportedDeviceTypeException e) {
-            DeviceConfig<? super P> config = descr.getConfiguration();
-            P res = (P)loadFromDriver(config, mode);
+            P res = (P)loadFromDriver(descr, mode);
             if (null == res) {
                 throw e;
             }
@@ -497,14 +510,20 @@
     }
 
     /**
-     * Looks up and opens a {@code Device} instance for the provided numeric ID.
-     * <p />
+     * Looks up then opens the device designated by the provided numeric ID,
+     * returning a {@code Device} instance to access it.
+     * The device configuration registered for the provided ID is first looked up;
+     * the device designated by the retrieved hardware addressing information is open and is
+     * initially set-up according to the registered configuration.
+     * <p>
      * The device is opened in the designated access mode. A device may be
      * opened in shared mode if supported by the underlying driver and hardware and if it is not
      * already opened in exclusive mode. A device may be opened in exclusive mode if
      * supported by the underlying driver and hardware and if it is not already opened.
-     * <p />
+     * </p><p>
+     * The device is opened in exclusive access mode.
      * A new instance is returned upon each call.
+     * </p>
      *
      * @param <P>
      *            the type of the device to open.
@@ -512,7 +531,7 @@
      *            the numeric device id.
      * @param mode
      *            the access mode, one of: {@link #EXCLUSIVE} or {@link #SHARED}.
-     * @return a {@code Device} instance for the given numeric ID.
+     * @return a new {@code Device} instance to access the designated device.
      * @throws DeviceNotFoundException
      *             if the designated device is not found.
      * @throws UnavailableDeviceException
@@ -540,27 +559,26 @@
     }
 
     /**
-     * Opens a {@code Device} instance with the specified hardware addressing information and
-     * configuration. The type of the device is inferred from the configuration type. An
-     * instance of the first <em>available</em> matching {@code Device}. If a matching
-     * {@code Device} is already open (therefore <em>not available</em>) the next matching
-     * {@code Device} is considered.
-     * <p />
-     * Opening a {@code Device} instance with hardware addressing information and configuration
+     * Opens a device, returning a {@code Device} instance of the specified type to access it.
+     * The device to open is designated by the provided hardware addressing information and is
+     * initially set-up according to the specified configuration.
+     * The type of the device is inferred from the configuration type.
+     * <p>
+     * Opening a device from its hardware addressing information and with an ad-hoc configuration
      * may be subject to <a href="#probing">device probing limitations </a>.
-     * <p />
+     * </p><p>
      * The device is opened in exclusive access mode.
-     * <p />
+     * </p><p>
      * The returned {@code Device} instance's ID and name are undefined.
-     * <p />
      * A new instance is returned upon each call.
+     * </p>
      *
      * @param <P>
      *            the type of the device to open.
      * @param config
      *            the device configuration (which includes hardware addressing information as
      *            well as configuration parameters).
-     * @return a {@code Device} instance for the specified configuration.
+     * @return a new {@code Device} instance to access the designated device.
      * @throws UnsupportedDeviceTypeException
      *             if the designated device type is not supported.
      * @throws InvalidDeviceConfigException
@@ -586,23 +604,22 @@
     }
 
     /**
-     * Opens a {@code Device} instance with the specified hardware addressing information and
-     * configuration. The type of the device is inferred from the configuration type. An
-     * instance of the first <em>available</em> matching {@code Device} is returned. If a
-     * matching {@code Device} is already open in a mode that is not compatible with the
-     * requested mode the next matching {@code Device} is considered.
-     * <p />
-     * Opening a {@code Device} instance with hardware addressing information and configuration
-     * may be subject to <a href="#probing">device probing limitations </a>.
-     * <p />
+     * Opens a device, returning a {@code Device} instance of the specified type to access it.
+     * The device to open is designated by the provided hardware addressing information and is
+     * initially set-up according to the specified configuration.
+     * The type of the device is inferred from the configuration type.
+     * <p>
+     * Opening a device from its hardware addressing information and with an ad-hoc configuration
+     * may be subject to <a href="#probing">device probing limitations</a>.
+     * </p><p>
      * The device is opened in the designated access mode. A device may be
      * opened in shared mode if supported by the underlying driver and hardware and if it is not
      * already opened in exclusive mode. A device may be opened in exclusive mode if
      * supported by the underlying driver and hardware and if it is not already opened.
-     * <p />
+     * </p><p>
      * The returned {@code Device} instance's ID and name are undefined.
-     * <p />
      * A new instance is returned upon each call.
+     * </p>
      *
      * @param <P>
      *            the type of the device to open.
@@ -611,7 +628,7 @@
      *            well as configuration parameters).
      * @param mode
      *            the access mode, one of: {@link #EXCLUSIVE} or {@link #SHARED}.
-     * @return a {@code Device} instance for the specified configuration.
+     * @return a new {@code Device} instance to access the designated device.
      * @throws UnsupportedDeviceTypeException
      *             if the designated device type is not supported.
      * @throws InvalidDeviceConfigException
@@ -641,20 +658,27 @@
     }
 
     /**
-     * Looks up and opens a {@code Device} instance for the specified name, type and/or
-     * properties. An instance of the first <em>available</em> matching {@code Device} is
-     * returned. If a matching {@code Device} is already open in a mode that is not compatible
-     * with the requested mode the next matching {@code Device} is considered.
-     * <p />
+     * Looks up then opens a device designated by the provided name, type and properties,
+     * returning a {@code Device} instance of the specified type to access it.
+     * A registered device configuration matching the provided name, type and properties is first looked up;
+     * if the device designated by the retrieved hardware addressing information is <em>available</em>
+     * it is open and initially set-up according to the matching configuration;
+     * if the device is already open in a mode that is not compatible
+     * with the requested mode the next matching registered device configuration is considered.
+     * <br>
+     * A provided {@code null} name matches all registered device names; an empty
+     * string name can only be matched by an empty string name or a by a {@code null} name.
+     * <p>
      * The device is opened in the designated access mode. A device may be
      * opened in shared mode if supported by the underlying driver and hardware and if it is not
      * already opened in exclusive mode. A device may be opened in exclusive mode if
      * supported by the underlying driver and hardware and if it is not already opened.
-     * <p />
+     * </p><p>
      * A new instance is returned upon each call.
-     * <p />
+     * </p><p>
      * Property-based lookup only uses exact (case-insensitive) matching and does not perform any
      * semantic interpretation.
+     * </p>
      *
      * @param <P>
      *            the type of the device to open.
@@ -667,7 +691,7 @@
      *            the access mode, one of: {@link #EXCLUSIVE} or {@link #SHARED}.
      * @param properties
      *            the list of required properties; may be {@code null}.
-     * @return a {@code Device} instance for the given name and required properties.
+     * @return a new {@code Device} instance to access the designated device.
      * @throws UnsupportedDeviceTypeException
      *             if the designated device type is not supported.
      * @throws DeviceNotFoundException
@@ -695,29 +719,33 @@
                 ExceptionMessage.format(ExceptionMessage.DEVICE_NULL_NAME_AND_PROPERTIES)
             );
         }
+
+        do {
+            AccessController.checkPermission(new DeviceMgmtPermission(((null == name)? "" : name) + ":*", DeviceMgmtPermission.OPEN));
+        } while (false);
+
+
         if (null == intf) {
             throw new NullPointerException(
                 ExceptionMessage.format(ExceptionMessage.DEVICE_NULL_INTF)
             );
         }
         checkMode(mode);
-        Iterator<DeviceDescriptor<P>> iter = Registry.getInstance().get(name, intf, properties);
-        // indicates if given device type is supprted
-        boolean supported = false;
+
+        // try to guess if this device type is valid
+        try {
+            getFactory(intf);
+        } catch (UnsupportedDeviceTypeException e) {
+            // nothing found yet
+            checkWithProviders(intf);
+        }
+
+        Iterator<PeripheralDescriptorImpl<P>> iter = Registry.getInstance().get(name, intf, properties);
         while (iter.hasNext()) {
-            DeviceDescriptor<P> descr = iter.next();
+            PeripheralDescriptorImpl<P> descr = iter.next();
             try {
-                do {
-                    String perm =  (null == descr.getName()) ? "" : descr.getName();
-                    perm = (UNSPECIFIED_ID == descr.getID()) ? perm : perm + ":" + descr.getID();
-                    AccessController.checkPermission(new DeviceMgmtPermission(name, DeviceMgmtPermission.OPEN));
-                } while (false);
-
                 final PeripheralFactory<P> f =  getFactory(descr.getInterface());
 
-                // we found at least one driver
-                supported = true;
-
                 final DeviceDescriptor<P> fdescr = descr;
                 final int fmode = mode;
                 return PrivilegeController.doPrivileged(new PrivilegedAction<P>() {
@@ -734,50 +762,37 @@
                 }
                 throw e2;
             } catch (DeviceNotFoundException | UnsupportedDeviceTypeException e) {
-                DeviceConfig<? super P> config = descr.getConfiguration();
-                P res = (P)loadFromDriver(config, mode);
+                P res = (P)loadFromDriver(descr, mode);
                 if (null == res) {
                     throw e;
                 }
+                return res;
             }
         }
 
-        if (!supported) {
-            // if there is no configuration for given type/name
-            // try to guess if this device type is valid
-            try {
-                getFactory(intf);
-                supported = true;
-            } catch (UnsupportedDeviceTypeException e) {
-                // nothing found yet
-            }
-        }
-
-        // special case if config is null
-        if (null != properties) {
-            return loadFromDriver(supported, intf, mode, properties);
-        }
-
-        if (supported) {
-            // type is valid, but no valid config is found
-            throw new DeviceNotFoundException(name);
-        } else {
-            throw new UnsupportedDeviceTypeException(intf.toString());
-        }
+        // type is valid, but no valid config is found
+        throw new DeviceNotFoundException(name);
     }
 
     /**
-     * Looks up and opens a {@code Device} instance for the specified name, type and/or
-     * properties. An instance of the first <em>available</em> matching {@code Device} is
-     * returned. If a matching {@code Device} is already open (therefore <em>not available</em>)
-     * the next matching {@code Device} is considered.
-     * <p />
+     * Looks up then opens a device designated by the provided name, type and properties,
+     * returning a {@code Device} instance of the specified type to access it.
+     * A registered device configuration matching the provided name, type and properties is first looked up;
+     * if the device designated by the retrieved hardware addressing information is <em>available</em>
+     * it is open and initially set-up according to the matching configuration;
+     * if the device is already open (therefore <em>not available</em>)
+     * the next matching registered device configuration is considered.
+     * <br>
+     * A provided {@code null} name matches all registered device names; an empty
+     * string name can only be matched by an empty string name or a by a {@code null} name.
+     * <p>
      * The device is opened in exclusive access mode.
-     * <p />
+     * </p><p>
      * A new instance is returned upon each call.
-     * <p />
+     * </p><p>
      * Property-based lookup only uses exact (case-insensitive) matching and does not perform any
      * semantic interpretation.
+     * </p>
      *
      * @param <P>
      *            the type of the device to open.
@@ -788,7 +803,7 @@
      *            up.
      * @param properties
      *            the list of required properties; may be {@code null}.
-     * @return a {@code Device} instance for the given name and required properties.
+     * @return a new {@code Device} instance to access the designated device.
      * @throws UnsupportedDeviceTypeException
      *             if the designated device type is not supported.
      * @throws DeviceNotFoundException
@@ -818,42 +833,45 @@
     }
 
     /**
-     * Registers under the specified ID (and optionally name and properties) a new device
+     * Registers under the specified ID and name (as well as optional properties) a new device
      * supporting the provided configuration. Upon successful registration all
      * {@link RegistrationListener} instances registered for the type of the registered device
      * are notified.
-     * <p />
-     * An implementation of the {@code DeviceManager} must guarantee that an application
+     * <p>
+     * An implementation of the {@code DeviceManager} MUST guarantee that an application
      * registering a device is the first one to get notified (in the event it has registered a
      * {@code RegistrationListener} for that type of devices).
-     * <p />
+     * </p><p>
      * The designated device may be probed to check if the provided configuration is valid
      * (see <a href="#probing">device probing limitations </a>).
-     * <p />
+     * </p><p>
      * Prior to registering a new device of a certain type the
      * {@link DeviceMgmtPermission} is checked with the action
-     * {@link DeviceMgmtPermission#REGISTER DeviceMgmtPermission.REGISTER}. <br />
+     * {@link DeviceMgmtPermission#REGISTER DeviceMgmtPermission.REGISTER}. <br>
      * For example, if a device of type {@link jdk.dio.gpio.GPIOPin
      * GPIOPin} is to be registered the {@code DeviceMgmtPermission} is checked with a target
      * name composed of the requested device name and ID and with the action
-     * {@code DeviceMgmtPermission#REGISTER DeviceMgmtPermission.REGISTER}.
-     * <p />
+     * {@link DeviceMgmtPermission#REGISTER DeviceMgmtPermission.REGISTER}.
+     * </p><p>
      * The following is an example of how this method may be used to register a new UART with Modem
-     * control lines: <blockquote>
-     *
+     * control lines:</p><blockquote>
      * <pre>
-     * DeviceManager.register(10, // the device ID
-     *         ModemUART.class, // the device type/interface
-     *         new UARTConfig(0, 2400, UARTConfig.DATABITS_8, UARTConfig.PARITY_EVEN, UARTConfig.STOPBITS_1,
-     *                 UARTConfig.FLOWCONTROL_NONE), // the device configuration
-     *         &quot;MODEM&quot;, // the device name
-     *         &quot;com.foobar.modem.xxx=true&quot;, &quot;com.foobar.modem.yyy=true&quot; // the device capabilities
+     * DeviceManager.register(10, <i>// the device ID</i>
+     *         ModemUART.class, <i>// the device type/interface</i>
+     *         new UARTConfig.Builder()
+     *             .setControllerNumber(0)
+     *             .setChannelNumber(0)
+     *             .setBaudRate(2400)
+     *             .setDataBits(UARTConfig.DATABITS_8)
+     *             .setParity(UARTConfig.PARITY_EVEN)
+     *             .setStopBits(UARTConfig.STOPBITS_1)
+     *             .setFlowControlMode(UARTConfig.FLOWCONTROL_NONE)
+     *             .build(), <i>// the device configuration</i>
+     *         &quot;MODEM&quot;, <i>// the device name</i>
+     *         &quot;com.foobar.modem.xxx=true&quot;, &quot;com.foobar.modem.yyy=true&quot; <i>// the device capabilities</i>
      * );
      * </pre>
      * </blockquote>
-     * This method cannot be used to register a device of a
-     * custom type. If an attempt is made to register a custom implementation of
-     * {@link DeviceConfig} a {@code UnsupportedDeviceTypeException} will be thrown.
      *
      * @param <P>
      *            the type of the device to be registered.
@@ -866,7 +884,7 @@
      * @param config
      *            the device configuration.
      * @param name
-     *            the name of the device to be registered; may be {@code null}.
+     *            the name of the device to be registered.
      * @param properties
      *            the list of properties/capabilities of the device to be registered; may be
      *            {@code null}.
@@ -883,7 +901,7 @@
      * @throws IOException
      *             if any other I/O error occurred.
      * @throws NullPointerException
-     *             if {@code intf} or {@code config} is {@code null}.
+     *             if {@code name}, {@code intf} or {@code config} is {@code null}.
      * @throws IllegalArgumentException
      *             if {@code id} is less than {@code 0} and is not equal to {@link #UNSPECIFIED_ID}.
      * @throws UnsupportedOperationException
@@ -900,98 +918,36 @@
                                                                  String name, String... properties) throws IOException, UnsupportedDeviceTypeException, InvalidDeviceConfigException,
         DeviceNotFoundException, DeviceAlreadyExistsException {
 
-        if (id < UNSPECIFIED_ID) {
-            throw new IllegalArgumentException(
-                ExceptionMessage.format(ExceptionMessage.DEVICE_INVALID_ID)
-            );
+        // quick fix: need info about custom DeviceConfig factory (if any)
+        PeripheralDescriptorImpl<P> dscr = new PeripheralDescriptorImpl(id, name, config, intf, properties);
+        // this fills dscr with correct provider
+        try (Device d = loadFromDriver(dscr, EXCLUSIVE)) {
+        } catch (Exception e) {
+            // intentionally ignored
         }
 
-        int new_id = checkConfig(id, intf, config, name, properties);
+        int new_id = Registry.getInstance().register(dscr);
 
-        Registry.getInstance().register(new_id, intf, config, name, properties);
-
-        // send notification in non-priveleged mode
-        RegistrationEventSender.notifyRegistered(null, new PeripheralDescriptorImpl(new_id, name, config, intf, properties));
+        RegistrationEventSender.notifyRegistered(null, dscr);
 
         return new_id;
     }
 
-    private static <P extends Device<? super P>> int checkConfig(final int id, final Class<P> intf, final DeviceConfig<? super P> config,
-                                                                      final String name, final String... properties)
-    throws IOException, UnsupportedDeviceTypeException, InvalidDeviceConfigException, DeviceNotFoundException, DeviceAlreadyExistsException {
-
-        if (!Registry.canRegister) {
-            throw new UnsupportedOperationException();
-        }
-
-        int new_id = PrivilegeController.doPrivileged(new PrivilegedAction<Integer>() {
-                public Integer run() throws IOException {
-                    Random rnd = new Random();
-                    int new_id = id;
-
-                    do {
-                        if (id == UNSPECIFIED_ID) {
-                            //  verify generated ID
-                            new_id = rnd.nextInt();
-                            if (new_id < 1) {
-                                continue;
-                            }
-                        }
-                        try {
-                            Device p = open(new_id);
-                            p.close();
-                        } catch (DeviceNotFoundException pnfe1) {
-                            // this is the only right way to break "while" condition
-                            break;
-                        } catch (UnavailableDeviceException pnae1) {}
-                        if (id  != UNSPECIFIED_ID) {
-                            throw new DeviceAlreadyExistsException(
-                                ExceptionMessage.format(ExceptionMessage.DEVICE_NONUNIQUE_ID)
-                            );
-                        }
-                        continue;
-                    } while (true);
-
-                    do {
-                        try {
-                            Device p = open(name, intf, properties);
-                            p.close();
-                        } catch (DeviceNotFoundException | IllegalArgumentException e1) {
-                            // this is the only right way to continue.
-                            // catch IAE to avoid duplicate of name/properties verification
-                            break;
-                        } catch (UnavailableDeviceException pnae2) {}
-                        throw new DeviceAlreadyExistsException(
-                            ExceptionMessage.format(ExceptionMessage.DEVICE_ALREADY_EXISTING_CONFIG)
-                        );
-                    } while(false);
-
-                    try {
-                        Device p = open(intf, config);
-                        p.close();
-                    } catch (UnavailableDeviceException pnae3) {}
-
-                    return new_id;
-                }
-
-        }).intValue();
-
-        return new_id;
-    }
 
     /**
      * Unregisters the device associated with the specified ID. Upon successful
      * unregistration all {@link RegistrationListener} instances registered for the type of the
      * device that has been unregistered are notified.
-     * <p />
+     * <p>
      * Some devices are registered by the underlying platform and cannot be unregistered.
-     * <p />
+     * </p><p>
      * Unregistration of a device has no side effect on its currently open
      * {@code Device} instances. These {@code Device} instances especially retain the
      * device ID that was assigned to them at the time they were open.
-     * <p />
+     * </p><p>
      * This method returns silently if the provided ID does not correspond to a registered
      * device.
+     * </p>
      *
      * @param id
      *            the ID of the device to unregister.
@@ -1003,8 +959,6 @@
      *             {@link DeviceMgmtPermission#UNREGISTER}).
      */
     public static void unregister(int id) {
-        checkID(id);
-
         final Registry r = Registry.getInstance();
         DeviceDescriptor unreg_d = r.unregister(id);
         // send notify
@@ -1056,16 +1010,14 @@
         RegistrationEventHandler.removeListener(listener, intf);
     }
 
+    /**
+     * Prevents instantiation.
+     */
+    private DeviceManager() {}
+
+
     /* ------------------- Private API ---------------- */
 
-    private static void checkID(int ID) throws IllegalArgumentException {
-        if (ID < 0) {
-            throw new IllegalArgumentException(
-                ExceptionMessage.format(ExceptionMessage.DEVICE_NEGATIVE_ID)
-            );
-        }
-    }
-
     private static void checkMode(int mode) throws UnsupportedAccessModeException {
         if (SHARED != mode && EXCLUSIVE != mode) {
             throw new UnsupportedAccessModeException();
@@ -1096,7 +1048,7 @@
     @Local(DontRenameNonAbstractSubtypes = {"com.oracle.dio.impl.PeripheralFactory"})
     private static PeripheralFactory getFactory(Class clazz) throws UnsupportedDeviceTypeException {
         // get package name of com.oracle.dio.PACAKAGE_NAME.PERIPHERAL_IFACE
-        // following code is correct for precompiled peripheral driver that following DAAPI name convention.
+        // following code is correct for precompiled peripheral driver that follows DAAPI name convention.
         String fullName = clazz.getName();
 
         // check for name correctness from current spec point of view.
@@ -1121,103 +1073,82 @@
     }
 
     // is called in response to UDTE and DNFE
-    private static <P extends Device<? super P>> P loadFromDriver(DeviceConfig<? super P> config, int mode) throws
+    private static <P extends Device<? super P>> P loadFromDriver(PeripheralDescriptorImpl<P> descr, int mode) throws
         DeviceNotFoundException, UnavailableDeviceException, InvalidDeviceConfigException,
         UnsupportedAccessModeException, IOException {
         ServiceLoader<DeviceProvider> loader = ServiceLoader.load(DeviceProvider.class);
         Iterator<DeviceProvider>  iter = loader.iterator();
-
+        final DeviceConfig<P> config = descr.getConfiguration();
+        final Class<P> type = descr.getInterface();
         boolean found = false;
         try {
             if (!iter.hasNext()) {
                 return null;
             }
 
-            int rejected, total;
-            rejected = total = 0;
             while (iter.hasNext()) {
-                total++;
                 DeviceProvider provider = iter.next();
-                if (!provider.getConfigType().isAssignableFrom(config.getClass())) {
-                    rejected++;
+                try {
+                    if (provider.getConfigType().isAssignableFrom(config.getClass()) &&
+                        (null == type || provider.getType().equals(type))) {
+                        found = true;
+                        if (provider.matches(descr.getProperties())) {
+                            // properties was checked by Registry when descriptor was loaded up
+                            P dev = (P)provider.open(config,descr.getProperties(),mode);
+                            // hack for config registration: save info about factory that may restore config from serialized data
+                            descr.setDeviceProvider(provider);
+                            return dev;
+                        }
+                    }
+                } catch (UnavailableDeviceException | InvalidDeviceConfigException | UnsupportedAccessModeException | SecurityException e) {
+                    // driver was found but it rejects provided data or device is busy or application has no rights to use the driver.
+                    // the driver is suitable for config class deserialization as well
+                    descr.setDeviceProvider(provider);
+                    throw e;
+                } catch (Throwable  e3) {
+                    Logging.reportError("Provider " + provider + " throws " + e3);
+                    // try other driver.
+                    // spec quotation:
+                    // A compliant implementation of the DeviceManager specification MUST catch undeclared unchecked exceptions,
+                    // unexpected values (such as null) or mismatching value types that may be thrown
+                    // or respectively returned at any of these steps
+                    // and MUST report these conditions to the caller as a DeviceNotFoundException.
+                    found = true;
+                    continue;
                 }
             }
-
-            if (rejected == total) {
-                // caller will rethrow UDTE or DNFE
-                return null;
-            }
-
-            iter = loader.iterator();
-
-            while (iter.hasNext()) {
-                DeviceProvider provider = iter.next();
-
-                try {
-                    // properties was checked by Registry when descriptor was loaded up
-                    return (P)provider.open(config,null,mode);
-                } catch (UnavailableDeviceException e) {
-                    // throw UPE if sunsequent operation is not success
-                    found = true;
-                    continue;
-                } catch (DeviceNotFoundException e2) {
-                    // try other driver.
-                    // now there is no way to determine what driver accepts config with correct hardware information
-                    // therefore it is neccesarry to test all of them
-                    continue;
-                }
-        }
         } catch (ServiceConfigurationError  ex) {
-                             // service framework exception equals to empty iterator
-                             return null;
+             // service framework exception equals to empty iterator
+             return null;
         }
         if (found) {
-            throw new UnavailableDeviceException(
-                ExceptionMessage.format(ExceptionMessage.DEVICE_FOUND_BUT_PERIPHERAL_IS_BUSY)
-            );
-        } else {
             throw new DeviceNotFoundException(
                 ExceptionMessage.format(ExceptionMessage.DEVICE_DRIVERS_NOT_MATCH)
             );
         }
+        // no driver matches descritor, caller will throw UDTE or DNFE
+        return null;
     }
 
-    private static <P extends Device<? super P>> P loadFromDriver(boolean supported, Class<P> intf, int mode, String... props) throws
-        DeviceNotFoundException, UnavailableDeviceException, InvalidDeviceConfigException,
-        UnsupportedAccessModeException, IOException {
+
+    private static void checkWithProviders(Class intf) throws UnsupportedDeviceTypeException {
         Iterator<DeviceProvider>  iter = ServiceLoader.load(DeviceProvider.class).iterator();
         try {
             while (iter.hasNext()) {
                 DeviceProvider provider = iter.next();
-
-                if (!provider.getConfigType().isAssignableFrom(intf)) {
-                    continue;
-                }
-
-                // found driver that recognizes intf type
-                supported = true;
-
-                if (provider.matches(props)) {
-                    try {
-                        return (P)provider.open(null, props, mode);
-                    } catch (UnavailableDeviceException e) {
-                        if (!iter.hasNext()) {
-                            throw e;
-                        }
+                try {
+                    if (provider.getType().equals(intf)) {
+                        return;
                     }
+                } catch (Throwable e) {
+                    // any exception threats as type is not suuported by provider
                 }
             }
         } catch (ServiceConfigurationError ex) {
             // intentionally ignored
         }
-        if (supported) {
-            throw new DeviceNotFoundException(
-                ExceptionMessage.format(ExceptionMessage.DEVICE_NOT_FOUND, intf.toString())
-            );
-        } else {
-            throw new UnsupportedDeviceTypeException (
-                ExceptionMessage.format(ExceptionMessage.DEVICE_DRIVER_MISSING)
-            );
-        }
+        throw new UnsupportedDeviceTypeException (
+            ExceptionMessage.format(ExceptionMessage.DEVICE_DRIVER_MISSING)
+        );
     }
 }
--- a/src/share/classes/jdk/dio/DeviceMgmtPermission.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/DeviceMgmtPermission.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,27 +22,30 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 import java.security.Permission;
 import java.security.PermissionCollection;
-import com.oracle.dio.utils.ActionFactory;
+import java.util.Objects;
 import java.util.Vector;
+
+import com.oracle.dio.utils.Utils;
+import com.oracle.dio.utils.Utils;
 import com.oracle.dio.utils.ExceptionMessage;
-import com.oracle.dio.utils.ActionFactory;
 
 /**
  * The {@code DeviceMgmtPermission} class defines permissions for registering and unregistering devices as
  * well as opening devices using their registered configurations.
- * <p />
+ * <p>
  * Device management permissions have a target name and actions.
- * <p />
+ * </p><p>
  * The target name is a combination of a device name and of a device ID or range of device IDs.
- * It takes the following form:
+ * It takes the following form:</p>
  * <blockquote>
  * <code>{device-name-spec} [ ":"{device-id-spec} ]</code>
  * </blockquote>
+ * where <code>{device-name-spec}</code> and <code>{device-id-spec}</code> are defined as follows:
+ * <blockquote>
  * <dl>
  * <dt><code>{device-name-spec}</code></dt>
  * <dd>
@@ -51,7 +54,8 @@
  * <code>{device-name} | "*" | ""</code>
  * </blockquote>
  * The <code>{device-name}</code>string is a device name as may be returned by a call to {@link DeviceDescriptor#getName() DeviceDescriptor.getName}.
- * <br />
+ * Occurrences of the semicolon character ({@code ":"}) must be escaped with a backslash ({@code "\"}).
+ * <br>
  * A <code>{device-name-spec}</code> specification consisting of the asterisk ("*") matches all device names.
  * A <code>{device-name-spec}</code> specification consisting of the empty string ("") designates an undefined device name
  * that may only be matched by an empty string or an asterisk.
@@ -64,26 +68,32 @@
  * </blockquote>
  * The <code>{device-id}</code> string is a device ID as may be returned by a call to {@link DeviceDescriptor#getID() DeviceDescriptor.getID}.
  * The characters in the string must all be decimal digits.
- * <br />
+ * <br>
+ * A <code>{device-id-spec}</code> specification of the form "N-M" (where N and M are device IDs) designates
+ * a range of device IDs from N (inclusive) to M (inclusive), where M is greater or equal to N.
  * A <code>{device-id-spec}</code> specification of the form "N-" (where N is a device ID) signifies all device IDs
  * numbered N and above, while a specification of the form "-N" indicates all device IDs numbered N and below.
  * A single asterisk in the place of the <code>{device-id-spec}</code> field matches all device IDs.
- * <p />
+ * <br>
  * The target name {@code "*:*"} matches all device names and all device IDs as is the target name {@code "*"}.
  * </dd>
  * </dl>
+ * </blockquote>
+ * <p>
  * The actions to be granted are passed to the constructor in a string containing a list of one or more comma-separated
- * keywords. The possible keywords are {@code register} and {@code unregister}. Their
- * meaning is defined as follows:
+ * keywords. The supported actions are {@code open}, {@code register} and {@code unregister}. Their
+ * meaning is defined as follows:</p>
+ * <blockquote>
  * <dl>
  * <dt>{@code open}</dt>
  * <dd>open a device using its device ID or name (see {@link DeviceManager#open(int) DeviceManager.open(id, ...)}
  * and {@link DeviceManager#open(java.lang.String, java.lang.Class, java.lang.String[]) DeviceManager.open(name, ...)} methods)</dd>
  * <dt>{@code register}</dt>
- * <dd>register a new device</dd>
+ * <dd>register a new device (see {@link DeviceManager#register DeviceManager.register})</dd>
  * <dt>{@code unregister}</dt>
- * <dd>unregister a device</dd>
+ * <dd>unregister a device (see {@link DeviceManager#unregister DeviceManager.unregister})</dd>
  * </dl>
+ * </blockquote>
  *
  * @see DeviceManager#open DeviceManager.open
  * @see DeviceManager#register DeviceManager.register
@@ -111,8 +121,16 @@
     /** Comma-separated ordered action list */
     private String myActions;
 
+    private String thisName;
+    private int lowID   = -1;
+    private int highID = -1;
+
     /**
      * Constructs a new {@code DeviceMgmtPermission} instance with the specified target name and action list.
+     * The target name is normalized so that leading and trailing spaces are removed
+     * and each occurrence of <code>{device-id}</code> is represented in its canonical
+     * decimal representation form (no leading zeros).
+     *
      *
      * @param name
      *            the target name (as defined above).
@@ -122,27 +140,98 @@
      * @throws NullPointerException
      *             if {@code name} is {@code null}.
      * @throws IllegalArgumentException
-     *             if actions is {@code null}, empty or contains an action other than the
-     *             specified possible actions.
+     *             <ul>
+     *             <li>if {@code actions} is {@code null}, empty or contains an action other than the
+     *             specified possible actions,</li>
+     *             <li>if {@code name} is not properly formatted.</li>
+     *             </ul>
      */
     public DeviceMgmtPermission(String name, String actions) {
+        // null check
         super(name.toString());
         if (null == actions) {
             throw new IllegalArgumentException(
                 ExceptionMessage.format(ExceptionMessage.DEVICE_NULL_ACTIONS)
             );
         }
-        myActions = ActionFactory.verifyAndOrderActions(actions, REGISTER+","+UNREGISTER+","+OPEN);
+        checkTargetNameFormat(name);
+        myActions = Utils.verifyAndOrderActions(actions, REGISTER+","+UNREGISTER+","+OPEN);
+    }
+
+    private void checkTargetNameFormat(String name) {
+
+        Objects.requireNonNull(name,  ExceptionMessage.format(ExceptionMessage.DEVICE_NULL_NAME));
+
+        String id;
+        int idx = -1;
+        while (-1 != (idx = name.indexOf(':', idx + 1))) {
+            if (idx == 0 || '\\' != name.charAt(idx - 1) ) {
+                break;
+            }
+        }
+
+        if (-1 == idx) {
+            thisName = name;
+            id = "";
+        } else {
+            thisName = name.substring(0, idx);
+            id = name.substring(idx + 1);
+            if ("".equals(id)) {
+                throw new IllegalArgumentException(ExceptionMessage.format(ExceptionMessage.DEVICE_INVALID_PERMISSION));
+            }
+        }
+
+        if ("*".equals(id) || "".equals(id)) {
+            lowID   = 0;
+            highID = Integer.MAX_VALUE;
+        } else {
+            idx = -1;
+            boolean foundDash = false;
+            for (int i = 0; i < id.length(); i++) {
+                char c = id.charAt(i);
+                if (!Character.isDigit(c)) {
+                    if ('-' == c && !foundDash) {
+                        foundDash = true;
+                        break;
+                    }
+                }
+            }
+
+            lowID   = 0;
+            highID = Integer.MAX_VALUE;
+            try {
+                if (foundDash) {
+                    idx = id.indexOf('-');
+                    if (idx > 0) {
+                        lowID = Integer.parseInt(id.substring(0, idx));
+                    }
+                    if (idx < id.length() - 1) {
+                        highID = Integer.parseInt(id.substring(idx + 1));
+                    }
+                    if (lowID > highID) {
+                        throw new IllegalArgumentException(ExceptionMessage.format(ExceptionMessage.DEVICE_INVALID_PERMISSION));
+                    }
+                } else {
+                    lowID = Integer.parseInt(id);
+                    highID = Integer.parseInt(id);
+                }
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException(ExceptionMessage.format(ExceptionMessage.DEVICE_INVALID_PERMISSION));
+            }
+        }
+
+        return;
     }
 
     /**
      * Checks two {@code DeviceMgmtPermission} objects for equality.
+     * Checks that {@code obj}'s class is the same as this object's class and has the
+     * same name (as returned by {@link Permission#getName Permission.getName}) and same actions (sorted as per {@link #getActions getActions}) as this object.
      *
      * @param obj
-     *            the object to test for equality with this object.
-     *
-     * @return {@code true} if {@code obj} is a {@code DeviceMgmtPermission} and has the same target name and
-     *         actions as this {@code DeviceMgmtPermission} object.
+     *         the object to test for equality with this object.
+     * @return {@code true} if {@code obj}'s class is the same as this object's class and has the same target
+     *         name and actions as this object; {@code false} otherwise.
      */
     @Override
     public boolean equals(Object obj) {
@@ -161,7 +250,12 @@
     }
 
     /**
-     * Returns the hash code value for this object.
+     * Returns the hash code value for this object. The hash code is calculated
+     * from this permission's name (as returned by {@link Permission#getName Permission.getName}) and actions (sorted as per {@link #getActions getActions})
+     * in a way that ensures that {@code permission1.equals(permission2)} implies
+     * that {@code permission1.hashCode()==permission2.hashCode()} for any two permissions,
+     * {@code permission1} and {@code permission2}, as required by the general contract of {@link Object#hashCode Object.hashCode}
+     * and the contract of {@link Permission#hashCode Permission.hashCode}.
      *
      * @return a hash code value for this object.
      */
@@ -171,12 +265,12 @@
     }
 
     /**
-     * Checks if this {@code DeviceMgmtPermission} object "implies" the specified permission.
-     * <p />
-     * More specifically, this method returns {@code true} if:
+     * Checks if this object "implies" the specified permission.
+     * <p>
+     * More specifically, this method returns {@code true} if:</p>
      * <ul>
-     * <li>{@code permission} is an instance of {@code DeviceMgmtPermission}, and
-     * <li>{@code permission}'s actions are a proper subset of this action list, and</li>
+     * <li>{@code permission}'s class is the same as this object's class, and</li>
+     * <li>{@code permission}'s actions (as returned by {@link #getActions getActions}) are a proper subset of this object's action list, and</li>
      * <li>{@code permission}'s device name, ID or range thereof
      * is included in this device name or ID range, whichever is defined.
      * </ul>
@@ -184,47 +278,18 @@
      * @param permission
      *            the permission to check against.
      *
-     * @return {@code true} if the specified permission is not {@code null} and is implied by this object, {@code false}
-     *         otherwise.
+     * @return {@code true} if the specified permission is not {@code null} and is implied by this
+     *         object, {@code false} otherwise.
      */
     @Override
     public boolean implies(Permission permission) {
+
         if ((permission == null) || (permission.getClass() != getClass()))
             return false;
 
-        if (!ActionFactory.implies(myActions, permission.getActions())) return false;
+        if (!Utils.implies(myActions, permission.getActions())) return false;
 
-        int idx = 0;
-        String name = permission.getName();
-        while (-1 != (idx = name.indexOf(':', idx))) {
-            if (idx == 0 || '\\' != name.charAt(idx - 1) ) {
-                break;
-            }
-        }
-        String thatName;
-        String thatID = "";
-        if (-1 == idx) {
-            thatName = name;
-        } else {
-            thatName = name.substring(0, idx);
-            thatID = name.substring(idx + 1);
-        }
-
-        idx = 0;
-        name = getName();
-        while (-1 != (idx = name.indexOf(':', idx))) {
-            if (idx == 0 || '\\' != name.charAt(idx - 1) ) {
-                break;
-            }
-        }
-        String thisName;
-        String thisID = "";
-        if (-1 == idx) {
-            thisName = name;
-        } else {
-            thisName = name.substring(0, idx);
-            thisID = name.substring(idx + 1);
-        }
+        String thatName = ((DeviceMgmtPermission)permission).thisName;
 
         if (!"*".equals(thisName)) {
             // the empty string ("") designates an undefined peripheral name
@@ -235,71 +300,11 @@
             }
         }
 
-        if (!"*".equals(thisID) &&
-            !(thisID.length() == 0 && thatID.length() == 0)) {
-            boolean foundDash = false;
-            for (int i = 0; i < thisID.length(); i++) {
-                char c = thisID.charAt(i);
-                if (!Character.isDigit(c)) {
-                     if('-' == c && !foundDash) {
-                         foundDash = true;
-                         continue;
-                     }
-                } else {
-                    continue;
-                }
-                // invalid format
-                return false;
-            }
-            int thisLow = 0;
-            int thisHigh = Integer.MAX_VALUE;
-            if (foundDash) {
-                idx = thisID.indexOf('-');
-                if (idx > 0) {
-                    thisLow = Integer.parseInt(thisID.substring(0, idx));
-                }
-                if (idx < thisID.length() - 1) {
-                    thisHigh = Integer.parseInt(thisID.substring(idx + 1));
-                }
-            } else {
-                thisLow = thisHigh = Integer.parseInt(thisID);
-            }
+        int thatLowID   = ((DeviceMgmtPermission)permission).lowID;
+        int thatHightID = ((DeviceMgmtPermission)permission).highID;
 
-            foundDash = false;
-            for (int i = 0; i < thatID.length(); i++) {
-                char c = thatID.charAt(i);
-                if (!Character.isDigit(c)) {
-                     if('-' == c && !foundDash) {
-                         foundDash = true;
-                         continue;
-                     }
-                } else {
-                    continue;
-                }
-                // invalid format
-                return false;
-            }
-
-            int thatLow = 0;
-            int thatHigh = Integer.MAX_VALUE;
-            if (foundDash) {
-                idx = thatID.indexOf('-');
-                if (idx > 0) {
-                    thatLow = Integer.parseInt(thatID.substring(0, idx));
-                }
-                if (idx < thatID.length() - 1) {
-                    thatHigh = Integer.parseInt(thatID.substring(idx + 1));
-                }
-            } else {
-                thatLow = thatHigh = Integer.parseInt(thatID);
-            }
-
-            return (thatLow >= thisLow && thatLow <= thisHigh &&
-                thatHigh >= thisLow && thatHigh <= thisHigh);
-
-        }
-
-        return true;
+        return (thatLowID >= lowID && thatLowID <= highID &&
+                thatHightID >= lowID && thatHightID <= highID);
 
     }
 
@@ -307,15 +312,10 @@
      * Returns a new {@code PermissionCollection} for storing {@code DeviceMgmtPermission} objects.
      * <p>
      * {@code DeviceMgmtPermission} objects must be stored in a manner that allows them to be inserted into the
-     * collection in any order, but that also enables the {@code PermissionCollection} implies method to be implemented
+     * collection in any order, but that also enables the {@link PermissionCollection#implies PermissionCollection.implies} method to be implemented
      * in an efficient (and consistent) manner.
      *
-     * <p>
-     * If {@code null} is returned, then the caller of this method is free to store permissions of this type in any
-     * PermissionCollection they choose (one that uses a {@code Hashtable}, one that uses a {@code Vector}, etc).
-     *
-     * @return a new {@code PermissionCollection} suitable for storing {@code DeviceMgmtPermission} objects, or
-     *         {@code null} if one is not defined.
+     * @return a new {@code PermissionCollection} suitable for storing {@code DeviceMgmtPermission} objects.
      */
     @Override
     public PermissionCollection newPermissionCollection() {
--- a/src/share/classes/jdk/dio/DeviceNotFoundException.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/DeviceNotFoundException.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 /**
@@ -45,7 +44,7 @@
      * error message string {@code message} can later be retrieved by the {@link Throwable#getMessage() getMessage} method.
      *
      * @param message
-     *            the detailed reason of the exception.
+     *            the detailed reason of the exception (may be {@code null}).
      */
     public DeviceNotFoundException(String message) {
         super(message);
--- a/src/share/classes/jdk/dio/DevicePermission.java	Mon Aug 29 14:45:05 2016 +0300
+++ b/src/share/classes/jdk/dio/DevicePermission.java	Fri Sep 09 13:20:20 2016 +0300
@@ -22,28 +22,32 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.dio;
 
 import java.security.Permission;
 import java.security.PermissionCollection;
 import java.util.Enumeration;
 import java.util.Vector;
+
 import com.oracle.dio.utils.ExceptionMessage;
-import com.oracle.dio.utils.ActionFactory;
+import com.oracle.dio.utils.Utils;
 import romizer.Local;
 
 /**
  * The {@code DevicePermission} abstract class is the superclass of all device permissions.
- * <p />
+ * <p>
  * A {@code DevicePermission} permission has a target name and, optionally, a list of actions.
- * <p />
- * The target name contains hardware addressing information. It takes the following form:
+ * </p><p>
+ * The target name contains hardware addressing information. It takes the following form:</p>
  * <blockquote> <code>( {controller-spec} ) [ ":" {channel-spec}]</code> </blockquote>
+ * where <code>{controller-spec}</code> and <code>{channel-spec}</code> are defined as follows:
+ * <blockquote>
  * <dl>
  * <dt><code>{controller-spec}</code></dt>
  * <dd>The <code>{controller-spec}</code> takes the following form: <blockquote>
  * <code>{controller-name-spec} | {controller-number} | "*" | ""</code> </blockquote>
+ * where <code>{controller-name-spec}</code> and <code>{controller-number}</code> are defined as follows:
+ * <blockquote>
  * <dl>
  * <dt><code>{controller-name-spec}</code></dt>
  * <dd>The <code>{controller-name-spec}</code> string is the string representation of a controller name as
@@ -60,6 +64,7 @@
  * DeviceConfig.HardwareAddressing.getControllerNumber}. The characters in the string must all be
  * decimal digits.</dd>
  * </dl>
+ * </blockquote>
  * A <code>{controller-spec}</code> specification consisting of the asterisk ({@code "*"}) matches all
  * controller names or numbers. A <code>{controller-spec}</code> specification consisting of the empty
  * string ({@code ""}) designates an undefined controller name or number that may only be matched by an
@@ -67,21 +72,31 @@
  * <dt>{channel-spec}</dt>
  * <dd>The <code>{channel-spec}</code> takes the following form: <blockquote>
  * <code>{channel-desc} | "*" | ""</code> </blockquote>
+ * where <code>{channel-desc}</code> is defined as follows:
+ * <blockquote>
  * <dl>
  * <dt><code>{channel-desc}</code></dt>
  * <dd>The <code>{channel-desc}</code> string is device type-specific and must be defined by
  * subclasses.</dd>
  * </dl>
+ * </blockquote>
  * A <code>{channel-spec}</code> specification consisting of the asterisk ({@code "*"}) matches all
  * channels. A <code>{channel-spec}</code> specification consisting of the empty string ({@code ""})
- * designates an undefined channel that may only be matched by an empty string or an asterisk.</dd>
+ * designates an undefined channel that may only be matched by an empty string or an asterisk.
+ * <br>
+ * The {@code DevicePermission} abstract class treats the <code>{channel-desc}</code> string
+ * as an opaque string: a <code>{channel-spec}</code> string may therefore only be matched
+ * by the exact same <code>{channel-spec}</code> string or by the asterisk ({@code "*"}).
+ * </dd>
  * </dl>
+ * </blockquote>
  * Subclasses of {@code DevicePermission} may defined additional specific target name formats to
  * designate devices using their specific hardware addressing information.
- * <p />
+ * <p>
  * The actions to be granted are passed to the constructor in a string containing a list of one or
  * more comma-separated keywords. The supported common actions are {@code open} and
- * {@code powermanage}. Their meaning is defined as follows:
+ * {@code powermanage}. Their meaning is defined as follows:</p>
+ * <blockquote>
  * <dl>
  * <dt>{@code open}</dt>
  * <dd>open a device (see {@link DeviceManager#open DeviceManager.open})</dd>
@@ -89,6 +104,7 @@
  * <dd>manage the power saving mode of a device (see
  * {@link jdk.dio.power.PowerManaged})</dd>
  * </dl>
+ * </blockquote>
  * Additional actions to be granted may be defined by subclasses of
  * {@code DevicePermission}.
  *
@@ -98,7 +114,6 @@
  */
 @apimarker.API("device-io_1.1")
 public abstract class DevicePermission extends Permission {
-
     /**
      * The {@code open} action.
      */
@@ -110,64 +125,75 @@
     public static final String POWER_MANAGE = "powermanage";
 
     /**
-     * Coma-separated action list
-     *
+     * Coma-separated action list     *
      */
     private String myActions;
 
+    private String thisDevice;
+    private String thisChannel;
+
+
     /**
-     * Constructs a new {@code DevicePermission} with the specified
-     * target name and the implicit {@code open} action.
+     * Constructs a new {@code DevicePermission} with the specified target name and the implicit
+     * {@code open} action.
+     * The target name is normalized so that leading and trailing spaces are removed
+     * and each occurrence of <code>{controller-number}</code> is represented in its canonical
+     * decimal representation form (without leading zeros).
      *
-     * @param name
-     *            the target name (as defined above).
-     * @throws NullPointerException
-     *             if {@code name} is {@code null}.
+     * @param name the target name (as defined above).
+     * @throws NullPointerException     if {@code name} is {@code null}.
+     * @throws IllegalArgumentException if {@code name} is not properly formatted.
      * @see #getName getName
      */
     public DevicePermission(String name) {
-        super(checkName(name));
+        // null check
+        super(name.toString());
+        String[] ret = Utils.parseDevicePermissionName(name);
+        thisDevice = ret[0];
+        thisChannel = ret[1];
         myActions = OPEN;
     }
 
-    private static String checkName(String name) {
-        if(name == null){
-            throw new NullPointerException(
-                ExceptionMessage.format(ExceptionMessage.DEVICE_NULL_NAME)
-            );
-        }
-
-        return name;
-    }
-
     /**
      * Constructs a new {@code DevicePermission} instance with the specified target name and
      * action list.
+     * The target name is normalized so that leading and trailing spaces are removed
+     * and each occurrence of <code>{controller-number}</code> is represented in its canonical
+     * decimal representation form (without leading zeros).
      *
-     * @param name
-     *            the target name (as defined above).
-     * @param actions
-     *            comma-separated list of device operations: {@code open} or {@code powermanage}
-     *            (additional actions may be defined by subclasses).
-     * @throws NullPointerException
-     *             if {@code name} is {@code null}.
-     * @throws IllegalArgumentException
-     *             if actions is {@code null}, empty or contain