changeset 119:dada06425261

8077268: OSGI permission file for IoT project Summary: Permission file is added, Makefile is modified to include it into bundle Reviewed-by: alkonsta
author snazarki
date Wed, 08 Apr 2015 18:40:00 +0400
parents 636b32ba06f9
children 203499b65f94
files Makefile src/se/classes/com/oracle/dio/impl/EventQueue.java src/se/classes/com/oracle/dio/uart/impl/UARTEventHandler.java src/se/classes/com/oracle/dio/utils/Logging.java src/se/permissions.perm-osgi 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/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/uart/serial.c src/share/linux/native/com/oracle/dio/uart/uart.c
diffstat 19 files changed, 403 insertions(+), 257 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Wed Mar 18 14:55:33 2015 +0300
+++ b/Makefile	Wed Apr 08 18:40:00 2015 +0400
@@ -246,10 +246,12 @@
 	rm -rf $(OSGI_DIST_DIR)/*
 	mkdir -p $(OSGI_DIST_DIR)
 	mkdir -p $(OSGI_BUILD_DIR)/lib
+	mkdir -p $(OSGI_BUILD_DIR)/OSGI-INF
 	sed -e  "s/BUILD_NUMBER/$(B)$(BUILD_NUMBER)/g;s/OSGI_ARCH/$(OSGI_ARCH)/g;s/DIO_VERSION/$(DIO_VERSION)/g" src/se/manifest.mf-osgi > $(OSGI_BUILD_DIR)/manifest.mf
+	cp src/se/permissions.perm-osgi $(OSGI_BUILD_DIR)/OSGI-INF/permissions.perm
 	cp $(JAR_OUT_DIR)/$(LIB_NAME).jar $(OSGI_JAR)
 	cp $(SO_OUT_DIR)/lib$(LIB_NAME).so $(OSGI_BUILD_DIR)/lib
-	$(JAR) ufm $(OSGI_JAR) $(OSGI_BUILD_DIR)/manifest.mf -C $(OSGI_BUILD_DIR) lib/lib$(LIB_NAME).so
+	$(JAR) ufm $(OSGI_JAR) $(OSGI_BUILD_DIR)/manifest.mf -C $(OSGI_BUILD_DIR) lib/lib$(LIB_NAME).so -C $(OSGI_BUILD_DIR) OSGI-INF/permissions.perm
 
 clean:
 	@echo "clean: removing $(BUILD_DIR)"
--- a/src/se/classes/com/oracle/dio/impl/EventQueue.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/se/classes/com/oracle/dio/impl/EventQueue.java	Wed Apr 08 18:40:00 2015 +0400
@@ -43,6 +43,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);
     }
@@ -108,24 +112,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
         }
     }
 
@@ -167,13 +170,8 @@
         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();
+                    EventHandler h = (EventHandler)listeners.get(i+1);
+                    h.handleEvent(evt);
                 }
             }
         }
--- a/src/se/classes/com/oracle/dio/uart/impl/UARTEventHandler.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/se/classes/com/oracle/dio/uart/impl/UARTEventHandler.java	Wed Apr 08 18:40:00 2015 +0400
@@ -158,9 +158,6 @@
                                                 Class<UARTEvent> eventClass);
 
     public boolean isDispatchThread() {
-        /*
-         * because of nature of dispatch for se where an event processed in separate thread
-         */
-        return false;
+        return queue.getEventDispatchThread().equals(Thread.currentThread());
     }
 }
--- a/src/se/classes/com/oracle/dio/utils/Logging.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/se/classes/com/oracle/dio/utils/Logging.java	Wed Apr 08 18:40:00 2015 +0400
@@ -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);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/se/permissions.perm-osgi	Wed Apr 08 18:40:00 2015 +0400
@@ -0,0 +1,32 @@
+( org.osgi.framework.PackagePermission "jdk.dio" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.adc" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.atcmd" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.counter" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.dac" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.generic" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.gpio" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.i2cbus" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.modem" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.power" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.pwm" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.spi" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.spibus" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.uart" "exportonly")
+( org.osgi.framework.PackagePermission "jdk.dio.watchdog" "exportonly")
+( java.util.PropertyPermission "jdk.dio.registry" "read")
+( java.lang.RuntimePermission "loadLibrary.dio")
+( java.util.PropertyPermission "user.dir" "read")
+( jdk.dio.DevicePermission "*:*" "open,powermanage")
+( jdk.dio.DeviceMgmtPermission "*:*" "open,register,unregister")
+( jdk.dio.adc.ADCPermission "*:*" "open,powermanage")
+( jdk.dio.atcmd.ATPermission "*:*" "open,powermanage,data")
+( jdk.dio.counter.CounterPermission "*:*" "open,powermanage")
+( jdk.dio.dac.DACPermission "*:*" "open,powermanage")
+( jdk.dio.generic.GenericPermission "*:*" "open,powermanage")
+( jdk.dio.gpio.GPIOPinPermission "*:*" "open,powermanage,setdirection")
+( jdk.dio.gpio.GPIOPortPermission "*:*" "open,powermanage,setdirection")
+( jdk.dio.i2cbus.I2CPermission "*:*" "open,powermanage")
+( jdk.dio.pwm.PWMPermission "*:*" "open,powermanage") 
+( jdk.dio.spibus.SPIPermission "*:*" "open,powermanage")
+( jdk.dio.uart.UARTPermission "*:*" "open,powermanage")
+( jdk.dio.watchdog.WatchdogTimerPermission "*:*" "open,powermanage")
--- a/src/share/classes/com/oracle/dio/impl/AbstractPeripheral.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/com/oracle/dio/impl/AbstractPeripheral.java	Wed Apr 08 18:40:00 2015 +0400
@@ -35,6 +35,7 @@
 import com.oracle.dio.utils.Constants;
 import com.oracle.dio.utils.ExceptionMessage;
 import java.nio.Buffer;
+import java.nio.ByteOrder;
 
 /* It is recommended to synchronize subclass native operation on {@code handle} lock.
    @see {@link #unlock()} for the reason
@@ -200,4 +201,8 @@
      * Release peripheral for shared access
      */
     protected  void unlock0() { handle.unlock(); }
+
+    public ByteOrder getByteOrder() throws IOException, UnavailableDeviceException, ClosedDeviceException {
+        return ByteOrder.LITTLE_ENDIAN;
+    }
 }
--- a/src/share/classes/com/oracle/dio/spibus/impl/SPICompositeMessageImpl.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/com/oracle/dio/spibus/impl/SPICompositeMessageImpl.java	Wed Apr 08 18:40:00 2015 +0400
@@ -59,12 +59,15 @@
         }
     }
 
-    private void checkStatus() {
+    private void checkStatus() throws ClosedDeviceException {
         if (isAlreadyTransferedOnce) {
             throw new IllegalStateException(
                 ExceptionMessage.format(ExceptionMessage.I2CBUS_ALREADY_TRANSFERRED_MESSAGE)
             );
         }
+        if (!device.isOpen()) {
+            throw new ClosedDeviceException();
+        }
     }
 
     private void check(Message message) throws ClosedDeviceException {
@@ -77,10 +80,6 @@
             );
         }
 
-        if (!device.isOpen()) {
-            throw new ClosedDeviceException();
-        }
-
         for (int i = 0; i < messageList.size(); i++) {
             ByteBuffer tx = messageList.get(i).tx;
             ByteBuffer rx = messageList.get(i).rx;
@@ -140,7 +139,7 @@
     }
 
     @Override
-    public synchronized SPICompositeMessage appendDelay(int delay) {
+    public synchronized SPICompositeMessage appendDelay(int delay) throws ClosedDeviceException {
 
         checkStatus();
 
--- a/src/share/classes/com/oracle/dio/uart/impl/UARTImpl.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/com/oracle/dio/uart/impl/UARTImpl.java	Wed Apr 08 18:40:00 2015 +0400
@@ -51,6 +51,7 @@
     private boolean isWriting;
 
     private Object synchReadLock = new Object();
+    private Object synchWriteLock = new Object();
 
     private ByteBuffer writeBuffers[] = new ByteBuffer[2];
     private int writeBuffersPositions[] = new int[2];
@@ -68,7 +69,6 @@
 
     private int receiveTriggerLevel;
     private int inputTimeout = Integer.MAX_VALUE;//timeout is disabled
-    private Timer receiveTimer;
 
 
     UARTImpl(DeviceDescriptor<UART> dscr, int mode)
@@ -112,47 +112,26 @@
         initPowerManagement();
     }
 
-    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> {
+            @Override
+            public void inputRoundCompleted(RoundCompletionEvent<UART, ByteBuffer> event) {
+                synchronized(synchReadLock){
+                    synchReadLock.notifyAll();
                 }
+            }
 
-                @Override
-                public void failed(Throwable ex, UART arg1) {
-                    synchronized(synchReadLock){
-                        synchReadLock.notifyAll();
-                    }
+            @Override
+            public void failed(Throwable ex, UART arg1) {
+                synchronized(synchReadLock){
+                    synchReadLock.notifyAll();
                 }
-            };
+            }
     }
 
-    private void startReceiveTimer(){
-
-        if(receiveTimer != null){
-            receiveTimer.cancel();
-        }
-        receiveTimer = new Timer();
-        receiveTimer.schedule(new TimerTask(){
-                                            @Override
-                                            public void run() {
-                                            try{
-                                                UARTEventHandler.getInstance().sendTimeoutEvent(getHandle().getNativeHandle());
-                                            }catch(Exception e){
-                                                //do nothing
-                                            }
-                                        }
-                                   },inputTimeout);
+    private InputRoundListener getLocalInputRoundListener(){
+        return new InternalRoundListener();
     }
 
-    private void stopReceiveTimer(){
-        if(receiveTimer != null){
-            receiveTimer.cancel();
-        }
-    }
 
     private boolean isAlphaNumerical(char ch) {
         if ((('a' <= ch && ch <= 'z') ||
@@ -209,20 +188,13 @@
         AccessController.checkPermission(new UARTPermission(getSecurityName(), DevicePermission.POWER_MANAGE));
     }
 
-    protected synchronized void processEvent(int event, int bytesProcessed){
+    protected void processEvent(int event, int bytesProcessed){
         UARTEventListener listener = eventListeners.get(event);
         if (listener != null){
             try{
-                if(event == UARTEvent.INPUT_DATA_AVAILABLE){
-                    stopReceiveTimer();
-                }
                 UARTEvent uartEvent = new UARTEvent(this, event);
                 listener.eventDispatched(uartEvent);
-                if(event == UARTEvent.INPUT_DATA_AVAILABLE){
-                    startReceiveTimer();
-                }
-            }
-            catch(Exception e){
+            } catch(Throwable e){
                 //do nothing
             }
         }
@@ -445,9 +417,6 @@
         }else{
              eventListeners.put(eventId, listener);
              subscribe(eventId);
-             if(eventId == UARTEvent.INPUT_DATA_AVAILABLE && inputTimeout < Integer.MAX_VALUE){
-                startReceiveTimer();
-             }
         }
     }
 
@@ -503,9 +472,8 @@
      * 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{
+    public void startWriting(ByteBuffer src, OutputRoundListener<UART, ByteBuffer> listener) throws IOException, UnavailableDeviceException, ClosedDeviceException{
         checkPowerState();
-        checkWrite();
 
         if(src == null || listener == null){
             throw new NullPointerException(
@@ -513,20 +481,14 @@
             );
         }
 
-        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){
@@ -535,23 +497,41 @@
             );
         }
 
-        writeBuffers[1] = src2;
-        writeBuffersPositions[1] = src2.position();
-        startWriting(src1, listener);
+        writeAsync(src1, src2, listener);
+    }
+
+    private void writeAsync(ByteBuffer src1, ByteBuffer src2, OutputRoundListener<UART, ByteBuffer> listener) throws IOException,
+        UnavailableDeviceException, ClosedDeviceException {
+        synchronized(synchWriteLock) {
+            checkWrite();
+            writeBuffers[0] = src1;
+            writeBuffersPositions[0] = src1.position();
+            writeBuffers[1] = src2;
+            if (null != src2) {
+                writeBuffersPositions[1] = src2.position();
+            }
+            writeBufferIdx = 0;
+            outRoundListener = listener;
+            subscribe(UARTEvent.OUTPUT_BUFFER_EMPTY);
+            writeAsynch0(src1);
+            isWriting = true;
+        }
     }
 
     /**
      * 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){
+                outRoundListener = null;
+                unsubscribe(UARTEvent.OUTPUT_BUFFER_EMPTY);
+                writeBuffers[0] = writeBuffers[1] = null;
+                stopWriting0();
+                isWriting = false;
+            }
         }
     }
 
@@ -560,33 +540,22 @@
      * buffer.
      */
     @Override
-    public synchronized void startReading(ByteBuffer src, InputRoundListener<UART, ByteBuffer> listener) throws IOException, UnavailableDeviceException, ClosedDeviceException{
+    public 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);
+        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{
 
         if(src1 == null || src2 == null || listener == null){
@@ -594,23 +563,51 @@
                 ExceptionMessage.format(ExceptionMessage.UART_NULL_SRC1_OR_SRC2_OR_LISTENER)
             );
         }
-        readBuffers[1] = src2;
-        readBuffersPositions[1] = src2.position();
-        startReading(src1, listener);
+        readAsync(src1, src2, listener);
+    }
+
+    private void readAsync(ByteBuffer src1, ByteBuffer src2, InputRoundListener<UART, ByteBuffer> listener)  throws IOException,
+            UnavailableDeviceException, ClosedDeviceException {
+        synchronized(synchReadLock){
+            checkRead();
+            inRoundListener = listener;
+            readBuffers[0] = src1;
+            readBuffersPositions[0] = src1.position();
+            readBuffers[1] = src2;
+            if (null != src2) {
+                readBuffersPositions[1] = src2.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);
+        }
+    }
+
+
+    /* stop operation of required type only, e.g. public stopReading() doesn't affect read() */
+    private void stopReading(boolean syncVer) throws IOException, UnavailableDeviceException, ClosedDeviceException {
+        synchronized(synchReadLock) {
+            if (null != inRoundListener && syncVer == (inRoundListener instanceof InternalRoundListener) ) {
+                inRoundListener = null;
+                unsubscribe(UARTEvent.INPUT_DATA_AVAILABLE);
+                readBuffers[0] = readBuffers[1] = null;
+                // redundant function, remove later
+                stopReading0();
+            }
+        }
     }
 
     /**
      * Stops (cancels) the currently active reading session.
       */
     @Override
-    public synchronized void stopReading() throws IOException, UnavailableDeviceException, ClosedDeviceException{
+    public void stopReading() throws IOException, UnavailableDeviceException, ClosedDeviceException{
         checkOpen();
-        if (inRoundListener != null){
-            inRoundListener = null;
-            unsubscribe(UARTEvent.INPUT_DATA_AVAILABLE);
-            readBuffers[0] = readBuffers[1] = null;
-            stopReading0();
-        }
+        stopReading(false);
     }
 
     /**
@@ -651,22 +648,20 @@
             UnavailableDeviceException, ClosedDeviceException{
         int ret;
 
-        synchronized(this){
-            checkRead();
+        if (dst == null){
+            throw new NullPointerException(
+                ExceptionMessage.format(ExceptionMessage.UART_NULL_DST)
+            );
         }
 
-        synchronized(handle){
+        if(!dst.hasRemaining()){
+            ret = 0;
+        }else{
+            ret = dst.position();
+            synchronized(synchReadLock){
 
-            if (dst == null){
-                throw new NullPointerException(
-                    ExceptionMessage.format(ExceptionMessage.UART_NULL_DST)
-                );
-            }
+                checkRead();
 
-            if(!dst.hasRemaining()){
-                ret = 0;
-            }else{
-                ret = dst.position();
                 /*read all data available*/
                 int readRes = read0(dst);
                 shiftBufferPosition(dst, ret + readRes);
@@ -678,7 +673,6 @@
                          * else read with timeout
                          */
                         startReading(dst, getLocalInputRoundListener());
-                        synchronized(synchReadLock){
                             try{
                                 if(inputTimeout == Integer.MAX_VALUE){
                                     //timeout disabled, wait forever or till the buffer is fullfilled
@@ -688,15 +682,16 @@
                                 }
                             }catch(InterruptedException iE){
                                 throw new IOException();
+                            } finally {
+                                stopReading(true);
                             }
-                        } // synch
-                        stopReading();
                     }
                 } // if !event thread
-            } // if has Remaining
+            } // synch
             ret = dst.position() - ret;
-        } // synch handle
-        return ret==0?-1:ret;
+        } // if has Remaining
+
+        return ret;
     }
 
     /**
@@ -711,42 +706,40 @@
             );
         }
 
-        synchronized (this) {
-            checkPowerState();
+        checkPowerState();
+
+        int ret = 0;
+
+        synchronized(synchWriteLock) {
             checkWrite();
+            isWriting = true;
         }
 
-        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();
             super.close();
         }
+        // unblock read()
+        synchronized(synchReadLock) {
+            synchReadLock.notifyAll();
+        }
     }
 
     @Override
--- a/src/share/classes/com/oracle/dio/utils/ActionFactory.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/com/oracle/dio/utils/ActionFactory.java	Wed Apr 08 18:40:00 2015 +0400
@@ -83,14 +83,28 @@
      * @return true for valid
      */
     private static boolean isValidAction(String actions, String normalizedList) {
-        StringTokenizer tokez = new StringTokenizer(actions, ",");
+        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;
             }
         }
-        return true;
+        // detects last empty token as well
+        return !lastTokenIsComma;
     }
 
     /**
--- a/src/share/classes/jdk/dio/Device.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/jdk/dio/Device.java	Wed Apr 08 18:40:00 2015 +0400
@@ -27,6 +27,7 @@
 
 import java.io.IOException;
 import java.nio.channels.Channel;
+import java.nio.ByteOrder;
 
 /**
  * The {@code Device} interface represents devices in the system. This interface
@@ -39,6 +40,15 @@
  * mode by the same application, locking one of the {@code Device} instances will prevent the
  * other form being accessed/used.
  *
+ * <h3><a name="byte_order">Device Byte Order</a></h3>
+ * 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.
+ *
  * @param <P>
  *            the device type the descriptor is defined for.
  * @since 1.0
@@ -129,4 +139,24 @@
      *         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. The byte
+     * order of a device that only performs single-byte value I/O operations
+     * is always {@link java.nio.ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+     *
+     * @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/DeviceManager.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/jdk/dio/DeviceManager.java	Wed Apr 08 18:40:00 2015 +0400
@@ -754,7 +754,7 @@
         }
 
         // special case if config is null
-        if (null != properties) {
+        if (0 != properties.length) {
             return loadFromDriver(supported, intf, mode, properties);
         }
 
--- a/src/share/classes/jdk/dio/adc/ADCChannel.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/jdk/dio/adc/ADCChannel.java	Wed Apr 08 18:40:00 2015 +0400
@@ -30,6 +30,7 @@
 import jdk.dio.DeviceManager;
 import jdk.dio.ClosedDeviceException;
 import jdk.dio.UnavailableDeviceException;
+import jdk.dio.UnsupportedByteOrderException;
 import java.io.IOException;
 import java.nio.*;
 import romizer.WeakDontRenameClass;
@@ -344,21 +345,23 @@
      *            input values have been read.
      * @throws NullPointerException
      *             If {@code dst} or {@code listener} is {@code null}.
-     * @throws IOException
-     *             if some other I/O error occurs.
+     * @throws IllegalStateException
+     *             if another synchronous or asynchronous acquisition is already active.
      * @throws UnavailableDeviceException
      *             if this device is not currently available - such as it is locked by another
      *             application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the provided buffer is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
      * @throws ClosedDeviceException
      *             if the device has been closed.
-     * @throws IllegalStateException
-     *             if another synchronous or asynchronous acquisition is already active.
+     * @throws IOException
+     *             if some other I/O error occurs.
      * @throws UnsupportedOperationException
      *             if an asynchronous monitoring is already active and acquisition and monitoring
      *             cannot be performed concurrently.
      */
     void startAcquisition(IntBuffer dst, AcquisitionRoundListener listener) throws IOException,
-            UnavailableDeviceException, ClosedDeviceException;
+            UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Starts asynchronous analog input acquisition on this channel and reads a series of raw
@@ -407,24 +410,26 @@
      *            input values have been read.
      * @throws NullPointerException
      *             If {@code dst1}, {@code dst2} or {@code listener} 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.
      * @throws IllegalStateException
      *             if another synchronous or asynchronous acquisition is already active.
      * @throws IllegalArgumentException
      *             if any of the buffers {@code dst1} and {@code dst2} has a zero-capacity or
      *             if they are the same or overlap.
+     * @throws UnavailableDeviceException
+     *             if this device is not currently available - such as it is locked by another
+     *             application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the any of the provided buffers is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
+     * @throws ClosedDeviceException
+     *             if the device has been closed.
+     * @throws IOException
+     *             if some other I/O error occurs.
      * @throws UnsupportedOperationException
      *             if an asynchronous monitoring is already active and acquisition and monitoring
      *             cannot be performed concurrently.
      */
     void startAcquisition(IntBuffer dst1, IntBuffer dst2, AcquisitionRoundListener listener) throws IOException,
-            UnavailableDeviceException, ClosedDeviceException;
+            UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Starts monitoring this channel analog input and asynchronously notifies the provided
--- a/src/share/classes/jdk/dio/dac/DACChannel.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/jdk/dio/dac/DACChannel.java	Wed Apr 08 18:40:00 2015 +0400
@@ -25,11 +25,8 @@
 
 package jdk.dio.dac;
 
-import jdk.dio.BufferAccess;
-import jdk.dio.Device;
-import jdk.dio.DeviceManager;
-import jdk.dio.ClosedDeviceException;
-import jdk.dio.UnavailableDeviceException;
+import jdk.dio.*;
+
 import java.io.IOException;
 import java.nio.IntBuffer;
 import romizer.WeakDontRenameClass;
@@ -275,19 +272,21 @@
      *
      * @param src
      *            the buffer from which the integer raw values can be retrieved.
-     * @throws IOException
-     *             if some other I/O error occurs.
      * @throws NullPointerException
      *             If {@code src} is {@code null}.
+     * @throws IllegalStateException
+     *             if an asynchronous output generation is already active.
      * @throws UnavailableDeviceException
      *             if this device is not currently available - such as it is locked by another
      *             application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the provided buffer is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
      * @throws ClosedDeviceException
      *             if the device has been closed.
-     * @throws IllegalStateException
-     *             if an asynchronous output generation is already active.
+     * @throws IOException
+     *             if some other I/O error occurs.
      */
-    void generate(IntBuffer src) throws IOException, UnavailableDeviceException, ClosedDeviceException;
+    void generate(IntBuffer src) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Starts asynchronous analog output generation on this channel from a series of raw output
@@ -309,10 +308,18 @@
      * buffer's position will be equal to <i>{@code p + n}</i>; its limit will not have changed. <br />
      * The buffer's position upon stopping this asynchronous operation by a call to
      * {@link #stopGeneration stopGeneration} is not predictable unless called from within the
-     * listener..
+     * listener. <br />
+     * If the provided {@code src} buffer is a direct buffer fulfilling the direct
+     * I/O requirements of this device (see {@link #prepareBuffer(java.nio.Buffer, int) prepareBuffer}) then the listener will only
+     * be invoked after all the <i>r</i> raw output values remaining in the provided
+     * {@code src} buffer have been consumed by the driver/hardware. If this channel
+     * uses an output buffer and is therefore working in buffering mode the listener will only be
+     * invoked after all the <i>r</i> raw output values have been copied to the
+     * output buffer; otherwise the listener will only be invoked after all the
+     * <i>r</i> raw output values have been consumed by the driver/hardware.
      * <p />
      * The raw output values (samples) will be converted according to the current output sampling
-     * interval as returned by {@link #getSamplingInterval getSamplingInterval}.
+     * interval as returned by {@link #getSamplingRate getSamplingRate}.
      * <p />
      * Upon notification of the provided {@code GenerationRoundListener}
      * the reference to the provided {@code src} buffer can be retrieved from the
@@ -341,24 +348,26 @@
      * significant bits beyond the {@code n} bits of the DAC device resolution have been truncated.
      *
      * @param src
-     *            the buffer from which the integer raw sampled input values are to be retrieved.
+     *            the buffer from which the integer raw sampled output values are to be retrieved.
      * @param listener
      *            the {@link GenerationRoundListener} instance to be notified when all the output
      *            values have been converted.
      * @throws NullPointerException
      *             If {@code src} or {@code listener} is {@code null}.
-     * @throws IOException
-     *             if some other I/O error occurs.
+     * @throws IllegalStateException
+     *             if another synchronous or asynchronous output generation is already active.
      * @throws UnavailableDeviceException
      *             if this device is not currently available - such as it is locked by another
      *             application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the provided buffer is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
      * @throws ClosedDeviceException
      *             if the device has been closed.
-     * @throws IllegalStateException
-     *             if another synchronous or asynchronous output generation is already active.
+     * @throws IOException
+     *             if some other I/O error occurs.
      */
     void startGeneration(IntBuffer src, GenerationRoundListener listener) throws IOException,
-            UnavailableDeviceException, ClosedDeviceException;
+            UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Starts asynchronous analog output generation on this channel from a series of raw output
@@ -374,7 +383,15 @@
      * will only be suspended if the previous event has not yet been handled. Also,
      * the position of the current working buffer upon stopping this asynchronous operation by a call to
      * {@link #stopGeneration stopGeneration} is not predictable even if called from within the
-     * listener.
+     * listener. <br />
+     * If both buffers are direct buffer fulfilling the direct I/O requirements of
+     * this device (see {@link #prepareBuffer(java.nio.Buffer, int) prepareBuffer} ) then the
+     * listener will only be invoked after all the raw output values remaining in
+     * the current working buffer are consumed by the driver/hardware; otherwise if this
+     * channel uses an output buffer and is therefore working in buffering mode
+     * the listener will only
+     * be invoked after all the raw output values remaining in the current working
+     * buffer have been copied to the output buffer.
      * <p />
      * Upon notification of the provided {@code GenerationRoundListener}
      * the reference to the  current working buffer (initially {@code src1}) can be retrieved from the
@@ -403,31 +420,33 @@
      * significant bits beyond the {@code n} bits of the DAC device resolution have been truncated.
      *
      * @param src1
-     *            the first buffer from which the integer raw sampled input values are to be
+     *            the first buffer from which the integer raw sampled output values are to be
      *            retrieved.
      * @param src2
-     *            the second buffer from which the integer raw sampled input values are to be
+     *            the second buffer from which the integer raw sampled output values are to be
      *            retrieved.
      * @param listener
      *            the {@link GenerationRoundListener} instance to be notified when all the output
      *            values have been converted.
      * @throws NullPointerException
      *             If {@code src1}, {@code src2} or {@code listener} 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.
      * @throws IllegalStateException
      *             if another synchronous or asynchronous output generation is already active.
      * @throws IllegalArgumentException
      *             if any of the buffers {@code src1} and {@code src2} has a zero-capacity or
      *             if they are the same or overlap.
+     * @throws UnavailableDeviceException
+     *             if this device is not currently available - such as it is locked by another
+     *             application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the any of the provided buffers is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
+     * @throws ClosedDeviceException
+     *             if the device has been closed.
+     * @throws IOException
+     *             if some other I/O error occurs.
      */
     void startGeneration(IntBuffer src1, IntBuffer src2, GenerationRoundListener listener) throws IOException,
-            UnavailableDeviceException, ClosedDeviceException;
+            UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Stops the asynchronous analog output generation on this channel as started by a call to one
--- a/src/share/classes/jdk/dio/generic/GenericBufferIODevice.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/jdk/dio/generic/GenericBufferIODevice.java	Wed Apr 08 18:40:00 2015 +0400
@@ -28,6 +28,7 @@
 import jdk.dio.BufferAccess;
 import jdk.dio.ClosedDeviceException;
 import jdk.dio.UnavailableDeviceException;
+import jdk.dio.UnsupportedByteOrderException;
 import java.io.*;
 import java.nio.*;
 import java.nio.channels.ByteChannel;
@@ -64,13 +65,15 @@
      * @throws UnavailableDeviceException
      *             if this device is not currently available - such as it is locked by another
      *             application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the provided buffer is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
      * @throws ClosedDeviceException
      *             if the device has been closed.
      * @throws IOException
      *             if an I/O error occurred such as the device is not readable.
      */
     @Override
-    int read(ByteBuffer dst) throws IOException, UnavailableDeviceException, ClosedDeviceException;
+    int read(ByteBuffer dst) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Reads a sequence of bytes from this device into the given buffer, skipping the first
@@ -93,12 +96,14 @@
      * @throws UnavailableDeviceException
      *             if this device is not currently available - such as it is locked by another
      *             application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the provided buffer is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
      * @throws ClosedDeviceException
      *             if the device has been closed.
      * @throws IOException
      *             if an I/O error occurred such as the device is not readable.
      */
-    int read(int skip, ByteBuffer dst) throws IOException, UnavailableDeviceException, ClosedDeviceException;
+    int read(int skip, ByteBuffer dst) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Writes a sequence of bytes to this device from the given buffer.
@@ -116,11 +121,13 @@
      * @throws UnavailableDeviceException
      *             if this device is not currently available - such as it is locked by another
      *             application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the provided buffer is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
      * @throws ClosedDeviceException
      *             if the device has been closed.
      * @throws IOException
      *             if an I/O error occurred such as the device is not writable.
      */
     @Override
-    int write(ByteBuffer src) throws IOException, UnavailableDeviceException, ClosedDeviceException;
+    int write(ByteBuffer src) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 }
--- a/src/share/classes/jdk/dio/power/PowerManaged.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/jdk/dio/power/PowerManaged.java	Wed Apr 08 18:40:00 2015 +0400
@@ -353,6 +353,7 @@
      *
      * @since 1.0
      */
+    @apimarker.API("device-io_1.1")
     public interface Group {
 
         /**
--- a/src/share/classes/jdk/dio/pwm/PWMChannel.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/jdk/dio/pwm/PWMChannel.java	Wed Apr 08 18:40:00 2015 +0400
@@ -30,6 +30,7 @@
 import jdk.dio.Device;
 import jdk.dio.DeviceManager;
 import jdk.dio.UnavailableDeviceException;
+import jdk.dio.UnsupportedByteOrderException;
 import java.io.IOException;
 import java.nio.IntBuffer;
 import romizer.WeakDontRenameClass;
@@ -202,7 +203,7 @@
      * <p />
      * The operation will return only after generating all of the <i>r</i> requested pulses.
      * <p />
-     * The pulses will be generated according to the current pulse period as returned by {@link #getPulsePeriod getPulsePeriod}.
+     * The pulses will be generated according to the current pulse rate as returned by {@link #getPulseRate getPulseRate}.
      * <p />
      * This method may be invoked at any time. If another thread has already initiated a synchronous pulse generation
      * upon this channel, however, then an invocation of this method will block until the first operation is complete.
@@ -222,18 +223,20 @@
      *
      * @param src
      *            the buffer from which the pulse width integer values can be retrieved.
+     * @throws NullPointerException
+     *             If {@code src} is {@code null}.
+     * @throws IllegalStateException
+     *             if an asynchronous pulse generation is already active.
+     * @throws UnavailableDeviceException
+     *             if this device is not currently available - such as it is locked by another application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the provided buffer is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
+     * @throws ClosedDeviceException
+     *             if the device has been closed.
      * @throws IOException
      *             if some other I/O error occurs.
-     * @throws NullPointerException
-     *             If {@code src} 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.
-     * @throws IllegalStateException
-     *             if an asynchronous pulse generation is already active.
      */
-    void generate(IntBuffer src) throws IOException, UnavailableDeviceException, ClosedDeviceException;
+    void generate(IntBuffer src) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Starts an asynchronous pulse train generation session - continuously generating pulses of the specified width
@@ -332,8 +335,8 @@
      * The buffer's position upon stopping this asynchronous operation by a call to {@link #stopGeneration stopGeneration}
      * is not predictable unless called from within the listener.
      * <p />
-     * The pulses will be generated according to the current pulse period as returned by {@link #getPulsePeriod getPulsePeriod}. The
-     * pulse period can be changed by the provided {@link GenerationRoundListener} instance upon notification of each
+     * The pulses will be generated according to the current pulse rate as returned by {@link #getPulseRate getPulseRate}. The
+     * pulse rate can be changed by the provided {@link GenerationRoundListener} instance upon notification of each
      * pulse train subsequence.
      * <p />
      * Upon notification of the provided {@code GenerationRoundListener}
@@ -372,17 +375,19 @@
      *            the width values remaining in the buffer.
      * @throws NullPointerException
      *             If {@code src} or {@code listener} is {@code null}.
+     * @throws IllegalStateException
+     *             if another synchronous or asynchronous output generation is already active.
+     * @throws UnavailableDeviceException
+     *             if this device is not currently available - such as it is locked by another application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the provided buffers is not supported.
+     * @throws ClosedDeviceException
+     *             if the device has been closed.
      * @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.
-     * @throws IllegalStateException
-     *             if another synchronous or asynchronous output generation is already active.
      */
     void startGeneration(IntBuffer src, GenerationRoundListener listener) throws IOException,
-            UnavailableDeviceException, ClosedDeviceException;
+            UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Starts asynchronous pulse train generation in successive rounds.
@@ -435,20 +440,22 @@
      *            the width values remaining in the working buffer.
      * @throws NullPointerException
      *             If {@code src1}, {@code src2} or {@code listener} 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.
      * @throws IllegalStateException
      *             if another synchronous or asynchronous output generation is already active.
      * @throws IllegalArgumentException
      *             if any of the buffers {@code src1} and {@code src2} has a zero-capacity or
      *             if they are the same or overlap.
+     * @throws UnavailableDeviceException
+     *             if this device is not currently available - such as it is locked by another application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the any of the provided buffers is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
+     * @throws ClosedDeviceException
+     *             if the device has been closed.
+     * @throws IOException
+     *             if some other I/O error occurs.
      */
     void startGeneration(IntBuffer src1, IntBuffer src2, GenerationRoundListener listener) throws IOException,
-            UnavailableDeviceException, ClosedDeviceException;
+            UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Stops (cancels) the currently active pulse generation session as started by a call to one
--- a/src/share/classes/jdk/dio/spibus/SPIDevice.java	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/classes/jdk/dio/spibus/SPIDevice.java	Wed Apr 08 18:40:00 2015 +0400
@@ -30,6 +30,7 @@
 import jdk.dio.DeviceManager;
 import jdk.dio.ClosedDeviceException;
 import jdk.dio.UnavailableDeviceException;
+import jdk.dio.UnsupportedByteOrderException;
 import java.io.IOException;
 import java.nio.*;
 import java.nio.channels.ByteChannel;
@@ -58,18 +59,28 @@
  * data received from the SPI slave device will be ignored/discarded. When reading only, dummy data will be sent to the
  * slave.
  * <p/>
- * A data exchange consists of words of a certain length which may vary from SPI slave device to SPI slave device. <br />
- * Words in the sending and receiving byte buffers are not packed (bit-wise) and must be byte-aligned. The most
- * significant bits of a word are stored at the lower index (that is first). If a word's length is not a multiple of 8
+ * A data exchange consists of words of a certain length which may vary from SPI
+ * slave device to SPI slave device. <br />
+ * Words in the sending and receiving byte buffers are not packed (bit-wise) and
+ * must be byte-aligned; bytes are copied out or in, respectively, from/to these
+ * buffers according to their byte orders (see
+ * {@link ByteBuffer#order() ByteBuffer.order}) and the bits are shifted out or
+ * in, respectively, according to the bit ordering configured for the device
+ * (see
+ * {@link SPIDeviceConfig#getBitOrdering() SPIDeviceConfig.getBitOrdering}).
+ * If a word's length is not a multiple of 8
  * (the byte length in bits) then the most significant bits will be undefined when receiving or unused when sending. If
  * the designated portion of a sending or receiving byte buffer cannot contain a (positive) integral number of words
  * then an {@link InvalidWordLengthException} will be thrown. For example, if the word length is 16bits and the
  * designated portion of buffer is only 1-byte long or is 3-byte long an {@link InvalidWordLengthException} will be
  * thrown. <br />
  * Assuming a word length <em>w</em>, the length <em>l</em> of the designated portion of the sending or receiving byte
- * buffer must be such that: <br />
- * <em>((l % (((w - 1) / 8) + 1)) == 0)</em>
- * <p />
+ * buffer must be such that:
+ * <blockquote>
+ * <pre>
+ * {@code ((l % (((w - 1) / 8) + 1)) == 0)}
+ * </pre>
+ * </blockquote>
  * Since the SPI master device controls the serial transmission clock read and write operations are never blocked nor delayed by
  * unresponsive slave devices. Not though that a read or write operation may be blocked if another read or write operation
  * is concurrently being performed on the same {@code SPIDevice} instance.
@@ -180,13 +191,15 @@
      *             if the number of bytes to receive belies word length.
      * @throws UnavailableDeviceException
      *             if this device is not currently available - such as it is locked by another application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the provided buffer is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
      * @throws ClosedDeviceException
      *             if the device has been closed.
      * @throws IOException
      *             if some other I/O error occurs.
      */
     @Override
-    int read(ByteBuffer dst) throws IOException, UnavailableDeviceException, ClosedDeviceException;
+    int read(ByteBuffer dst) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Reads a sequence of bytes from this device into the given buffer, skipping the first {@code skip} bytes read.
@@ -211,12 +224,14 @@
      *             if the total number of bytes to receive belies word length.
      * @throws UnavailableDeviceException
      *             if this device is not currently available - such as it is locked by another application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the provided buffer is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
      * @throws ClosedDeviceException
      *             if the device has been closed.
      * @throws IOException
      *             if some other I/O error occurs.
      */
-    int read(int skip, ByteBuffer dst) throws IOException, UnavailableDeviceException, ClosedDeviceException;
+    int read(int skip, ByteBuffer dst) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Writes a sequence of bytes to this slave device from the given buffer.
@@ -246,13 +261,15 @@
      *             if {@code src} is {@code null}.
      * @throws UnavailableDeviceException
      *             if this device is not currently available - such as it is locked by another application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the provided buffer is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
      * @throws ClosedDeviceException
      *             if the device has been closed.
      * @throws IOException
      *             if some other I/O error occurs.
      */
     @Override
-    int write(ByteBuffer src) throws IOException, UnavailableDeviceException, ClosedDeviceException;
+    int write(ByteBuffer src) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Writes one data word of up to 32 bits to this slave device.
@@ -296,12 +313,14 @@
      *             if the number of bytes to receive or send belies word length.
      * @throws UnavailableDeviceException
      *             if this device is not currently available - such as it is locked by another application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the any of the provided buffers is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
      * @throws ClosedDeviceException
      *             if the device has been closed.
      * @throws IOException
      *             if some other I/O error occurs.
      */
-    int writeAndRead(ByteBuffer src, ByteBuffer dst) throws IOException, UnavailableDeviceException, ClosedDeviceException;
+    int writeAndRead(ByteBuffer src, ByteBuffer dst) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Exchanges (transmits and receives) data with this slave device skipping the specified number of bytes received.
@@ -328,12 +347,14 @@
      *             if the total number of bytes to receive or send belies word length.
      * @throws UnavailableDeviceException
      *             if this device is not currently available - such as it is locked by another application.
+     * @throws UnsupportedByteOrderException
+     *             if the byte ordering of the any of the provided buffers is not supported (see <a href="{@docRoot}/jdk/dio/Device.html#byte_order">Device Byte Order</a>).
      * @throws ClosedDeviceException
      *             if the device has been closed.
      * @throws IOException
      *             if some other I/O error occurs.
      */
-    int writeAndRead(ByteBuffer src, int skip, ByteBuffer dst) throws IOException, UnavailableDeviceException, ClosedDeviceException;
+    int writeAndRead(ByteBuffer src, int skip, ByteBuffer dst) throws IOException, UnavailableDeviceException, UnsupportedByteOrderException, ClosedDeviceException;
 
     /**
      * Exchanges (transmits and receives) one data word of up to 32 bits with this slave device.
--- a/src/share/linux/native/com/oracle/dio/uart/serial.c	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/linux/native/com/oracle/dio/uart/serial.c	Wed Apr 08 18:40:00 2015 +0400
@@ -25,6 +25,7 @@
 
 #include "serial.h"
 #include "list_helper.h"
+#include "privilege_manager.h"
 
 typedef void *(thread_func)(void*);
 
@@ -730,10 +731,15 @@
     if(get_config_by_name(p->dev_name) != NULL){
         return JAVACALL_BUSY;
     }
-    //opening one of the /dev/ttyUSB devices, no pin busy check
-    if (-1 == (p->fd = open(p->dev_name, O_RDWR | O_NOCTTY | O_NONBLOCK))) {
-        JAVACALL_REPORT_ERROR2(JC_SERIAL, "Can't open %s file errno %d",
-                p->dev_name, errno);
+
+    // restore root privileges temporary
+    restore_privileges();
+    p->fd = open(p->dev_name, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    drop_privileges();
+
+    if (-1 == p->fd) {
+        JAVACALL_REPORT_ERROR2(JC_SERIAL, "Can't open %s file. %s",
+                p->dev_name, strerror(errno));
         return JAVACALL_FAIL;
     }
     /*flock set an advisory lock*/
@@ -744,15 +750,16 @@
     lock.l_pid    = getpid();
 
     if(-1 == fcntl(p->fd, F_SETLK, &lock)){
+        //save errno for printouts, next "close" call may modify it
         error_n = errno;
         close(p->fd);
         p->fd = -1;
 
         if (error_n == EACCES || error_n == EAGAIN) {
-            JAVACALL_REPORT_ERROR1(JC_DIO, "[UART] Can't lock device. errno %d", errno);
+            JAVACALL_REPORT_ERROR1(JC_DIO, "[UART] Can't lock device. %s", strerror(error_n));
             return JAVACALL_BUSY;
         }else{
-            JAVACALL_REPORT_ERROR1(JC_DIO, "[UART] Can't lock device. errno %d", errno);
+            JAVACALL_REPORT_ERROR1(JC_DIO, "[UART] Can't lock device. %s", strerror(error_n));
             return JAVACALL_FAIL;
         }
     }
--- a/src/share/linux/native/com/oracle/dio/uart/uart.c	Wed Mar 18 14:55:33 2015 +0300
+++ b/src/share/linux/native/com/oracle/dio/uart/uart.c	Wed Apr 08 18:40:00 2015 +0400
@@ -120,24 +120,27 @@
         void **pContext) {
 
     int bytesAvailable;
+    javacall_dio_result res;
 
     pthread_mutex_lock( &((serial_handle)handle)->lock );
 
     if (JAVACALL_FAIL == jc_serial_read_common((serial_handle)handle, buffer, size, bytesRead, &bytesAvailable)){
         JAVACALL_REPORT_INFO(JC_SERIAL, "javacall_serial_read_start: cannot read from the internal buffer");
-        return JAVACALL_DIO_FAIL;
+        res = JAVACALL_DIO_FAIL;
+    }else{
+
+        ((uart_handle)handle)->notifiedEvents &= ~SERIAL_IN_AVAILABLE;
+        if(bytesAvailable > 0){
+        ((serial_handle)handle)->new_data_avail_cb((serial_handle)handle, bytesAvailable, JAVACALL_DIO_OK);
+        }
+        /*  read from the internal buffer complete, buffer may overrun again
+        */
+        ((uart_handle)handle)->notifiedEvents &= ~SERIAL_IN_OVERRUN;
+        res = JAVACALL_DIO_OK;
     }
-
-    ((uart_handle)handle)->notifiedEvents &= ~SERIAL_IN_AVAILABLE;
-    if(bytesAvailable > 0){
-        ((serial_handle)handle)->new_data_avail_cb((serial_handle)handle, bytesAvailable, JAVACALL_DIO_OK);
-    }
-    /*  read from the internal buffer complete, buffer may overrun again
-    */
-    ((uart_handle)handle)->notifiedEvents &= ~SERIAL_IN_OVERRUN;
     pthread_mutex_unlock( &((serial_handle)handle)->lock );
 
-    return JAVACALL_DIO_OK;
+    return res;
 }