mirror of
				https://github.com/mik3y/usb-serial-for-android
				synced 2025-10-31 02:17:23 +00:00 
			
		
		
		
	iomanager with configurable buffer size
This commit is contained in:
		
							parent
							
								
									4f2d6c73a4
								
							
						
					
					
						commit
						f443d1f012
					
				| @ -45,6 +45,7 @@ import org.junit.runner.Description; | |||||||
| import org.junit.runner.RunWith; | import org.junit.runner.RunWith; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
|  | import java.nio.BufferOverflowException; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.EnumSet; | import java.util.EnumSet; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @ -56,6 +57,7 @@ import static org.junit.Assert.assertEquals; | |||||||
| import static org.junit.Assert.assertFalse; | import static org.junit.Assert.assertFalse; | ||||||
| import static org.junit.Assert.assertNotEquals; | import static org.junit.Assert.assertNotEquals; | ||||||
| import static org.junit.Assert.assertNotNull; | import static org.junit.Assert.assertNotNull; | ||||||
|  | import static org.junit.Assert.assertNull; | ||||||
| import static org.junit.Assert.assertThat; | import static org.junit.Assert.assertThat; | ||||||
| import static org.junit.Assert.assertTrue; | import static org.junit.Assert.assertTrue; | ||||||
| import static org.junit.Assert.fail; | import static org.junit.Assert.fail; | ||||||
| @ -1014,6 +1016,82 @@ public class DeviceTest { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Test | ||||||
|  |     public void IoManager() throws Exception { | ||||||
|  |         usb.ioManager = new SerialInputOutputManager(null); | ||||||
|  |         assertNull(usb.ioManager.getListener()); | ||||||
|  |         usb.ioManager.setListener(usb); | ||||||
|  |         assertEquals(usb, usb.ioManager.getListener()); | ||||||
|  |         usb.ioManager = new SerialInputOutputManager(usb.serialPort, usb); | ||||||
|  |         assertEquals(usb, usb.ioManager.getListener()); | ||||||
|  | 
 | ||||||
|  |         assertEquals(0, usb.ioManager.getReadTimeout()); | ||||||
|  |         usb.ioManager.setReadTimeout(10); | ||||||
|  |         assertEquals(10, usb.ioManager.getReadTimeout()); | ||||||
|  |         assertEquals(0, usb.ioManager.getWriteTimeout()); | ||||||
|  |         usb.ioManager.setWriteTimeout(11); | ||||||
|  |         assertEquals(11, usb.ioManager.getWriteTimeout()); | ||||||
|  | 
 | ||||||
|  |         assertEquals(4096, usb.ioManager.getReadBufferSize()); | ||||||
|  |         usb.ioManager.setReadBufferSize(12); | ||||||
|  |         assertEquals(12, usb.ioManager.getReadBufferSize()); | ||||||
|  |         assertEquals(4096, usb.ioManager.getWriteBufferSize()); | ||||||
|  |         usb.ioManager.setWriteBufferSize(13); | ||||||
|  |         assertEquals(13, usb.ioManager.getWriteBufferSize()); | ||||||
|  | 
 | ||||||
|  |         usb.open(); // creates new IoManager | ||||||
|  |         usb.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||||
|  |         telnet.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||||
|  |         usb.waitForIoManagerStarted(); | ||||||
|  |         try { | ||||||
|  |             usb.ioManager.setReadTimeout(20); | ||||||
|  |             fail("setReadTimeout IllegalStateException expected"); | ||||||
|  |         } catch (IllegalStateException ignored) {} | ||||||
|  |         assertEquals(0, usb.ioManager.getReadTimeout()); | ||||||
|  |         usb.ioManager.setWriteTimeout(21); | ||||||
|  |         assertEquals(21, usb.ioManager.getWriteTimeout()); | ||||||
|  |         usb.ioManager.setReadBufferSize(22); | ||||||
|  |         assertEquals(22, usb.ioManager.getReadBufferSize()); | ||||||
|  |         usb.ioManager.setWriteBufferSize(23); | ||||||
|  |         assertEquals(23, usb.ioManager.getWriteBufferSize()); | ||||||
|  | 
 | ||||||
|  |         // readbuffer resize | ||||||
|  |         telnet.write(new byte[1]); | ||||||
|  |         usb.ioManager.setReadBufferSize(64); | ||||||
|  |         Log.d(TAG, "setReadBufferSize(64)"); | ||||||
|  |         telnet.write(new byte[1]); // still uses old buffer as infinite waiting step() holds reference to buffer | ||||||
|  |         telnet.write(new byte[1]); // now uses 8 byte buffer | ||||||
|  |         usb.read(3); | ||||||
|  | 
 | ||||||
|  |         // writebuffer resize | ||||||
|  |         try { | ||||||
|  |             usb.ioManager.writeAsync(new byte[8192]); | ||||||
|  |             fail("expected BufferOverflowException"); | ||||||
|  |         } catch (BufferOverflowException ignored) {} | ||||||
|  | 
 | ||||||
|  |         usb.ioManager.setWriteBufferSize(16); | ||||||
|  |         usb.ioManager.writeAsync("1234567890AB".getBytes()); | ||||||
|  |         try { | ||||||
|  |             usb.ioManager.setWriteBufferSize(8); | ||||||
|  |             fail("expected BufferOverflowException"); | ||||||
|  |         } catch (BufferOverflowException ignored) {} | ||||||
|  |         usb.ioManager.setWriteBufferSize(24); // pending date copied to new buffer | ||||||
|  |         telnet.write("a".getBytes()); | ||||||
|  |         assertThat(usb.read(1), equalTo("a".getBytes())); | ||||||
|  |         assertThat(telnet.read(12), equalTo("1234567890AB".getBytes())); | ||||||
|  | 
 | ||||||
|  |         // small readbuffer | ||||||
|  |         usb.ioManager.setReadBufferSize(8); | ||||||
|  |         Log.d(TAG, "setReadBufferSize(8)"); | ||||||
|  |         telnet.write("b".getBytes()); | ||||||
|  |         assertThat(usb.read(1), equalTo("b".getBytes())); | ||||||
|  |         // now new buffer is used | ||||||
|  |         telnet.write("c".getBytes()); | ||||||
|  |         assertThat(usb.read(1), equalTo("c".getBytes())); | ||||||
|  |         telnet.write("d".getBytes()); | ||||||
|  |         assertThat(usb.read(1), equalTo("d".getBytes())); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Test |     @Test | ||||||
|     public void writeAsync() throws Exception { |     public void writeAsync() throws Exception { | ||||||
|         if (usb.serialDriver instanceof FtdiSerialDriver) |         if (usb.serialDriver instanceof FtdiSerialDriver) | ||||||
| @ -1021,19 +1099,6 @@ public class DeviceTest { | |||||||
| 
 | 
 | ||||||
|         byte[] data, buf = new byte[]{1}; |         byte[] data, buf = new byte[]{1}; | ||||||
| 
 | 
 | ||||||
|         usb.ioManager = new SerialInputOutputManager(null); |  | ||||||
|         assertEquals(null, usb.ioManager.getListener()); |  | ||||||
|         usb.ioManager.setListener(usb); |  | ||||||
|         assertEquals(usb, usb.ioManager.getListener()); |  | ||||||
|         usb.ioManager = new SerialInputOutputManager(usb.serialPort, usb); |  | ||||||
|         assertEquals(usb, usb.ioManager.getListener()); |  | ||||||
|         assertEquals(0, usb.ioManager.getReadTimeout()); |  | ||||||
|         usb.ioManager.setReadTimeout(100); |  | ||||||
|         assertEquals(100, usb.ioManager.getReadTimeout()); |  | ||||||
|         assertEquals(0, usb.ioManager.getWriteTimeout()); |  | ||||||
|         usb.ioManager.setWriteTimeout(200); |  | ||||||
|         assertEquals(200, usb.ioManager.getWriteTimeout()); |  | ||||||
| 
 |  | ||||||
|         // w/o timeout: write delayed until something is read |         // w/o timeout: write delayed until something is read | ||||||
|         usb.open(); |         usb.open(); | ||||||
|         usb.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); |         usb.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||||
| @ -1047,10 +1112,6 @@ public class DeviceTest { | |||||||
|         assertEquals(1, data.length); |         assertEquals(1, data.length); | ||||||
|         data = telnet.read(2); |         data = telnet.read(2); | ||||||
|         assertEquals(2, data.length); |         assertEquals(2, data.length); | ||||||
|         try { |  | ||||||
|             usb.ioManager.setReadTimeout(100); |  | ||||||
|             fail("IllegalStateException expected"); |  | ||||||
|         } catch (IllegalStateException ignored) {} |  | ||||||
|         usb.close(); |         usb.close(); | ||||||
| 
 | 
 | ||||||
|         // with timeout: write after timeout |         // with timeout: write after timeout | ||||||
|  | |||||||
| @ -175,6 +175,18 @@ public class UsbWrapper implements SerialInputOutputManager.Listener { | |||||||
|         readError = null; |         readError = null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public void waitForIoManagerStarted() throws IOException { | ||||||
|  |         for (int i = 0; i < 100; i++) { | ||||||
|  |             if (SerialInputOutputManager.State.STOPPED != ioManager.getState()) return; | ||||||
|  |             try { | ||||||
|  |                 Thread.sleep(1); | ||||||
|  |             } catch (InterruptedException e) { | ||||||
|  |                 e.printStackTrace(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         throw new IOException("IoManager not started"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // wait full time |     // wait full time | ||||||
|     public byte[] read() throws Exception { |     public byte[] read() throws Exception { | ||||||
|         return read(-1); |         return read(-1); | ||||||
|  | |||||||
| @ -30,8 +30,11 @@ public class SerialInputOutputManager implements Runnable { | |||||||
|     private int mReadTimeout = 0; |     private int mReadTimeout = 0; | ||||||
|     private int mWriteTimeout = 0; |     private int mWriteTimeout = 0; | ||||||
| 
 | 
 | ||||||
|     private final ByteBuffer mReadBuffer = ByteBuffer.allocate(BUFSIZ); |     private final Object mReadBufferLock = new Object(); | ||||||
|     private final ByteBuffer mWriteBuffer = ByteBuffer.allocate(BUFSIZ); // Synchronized by 'mWriteBuffer' |     private final Object mWriteBufferLock = new Object(); | ||||||
|  | 
 | ||||||
|  |     private ByteBuffer mReadBuffer = ByteBuffer.allocate(BUFSIZ); | ||||||
|  |     private ByteBuffer mWriteBuffer = ByteBuffer.allocate(BUFSIZ); | ||||||
| 
 | 
 | ||||||
|     public enum State { |     public enum State { | ||||||
|         STOPPED, |         STOPPED, | ||||||
| @ -72,10 +75,13 @@ public class SerialInputOutputManager implements Runnable { | |||||||
|         return mListener; |         return mListener; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * read/write timeout | ||||||
|  |      */ | ||||||
|     public void setReadTimeout(int timeout) { |     public void setReadTimeout(int timeout) { | ||||||
|         // when set if already running, read already blocks and the new value will not become effective now |         // when set if already running, read already blocks and the new value will not become effective now | ||||||
|         if(mReadTimeout == 0 && timeout != 0 && mState != State.STOPPED) |         if(mReadTimeout == 0 && timeout != 0 && mState != State.STOPPED) | ||||||
|             throw new IllegalStateException("Set readTimeout before SerialInputOutputManager is started"); |             throw new IllegalStateException("readTimeout only configurable before SerialInputOutputManager is started"); | ||||||
|         mReadTimeout = timeout; |         mReadTimeout = timeout; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -91,12 +97,42 @@ public class SerialInputOutputManager implements Runnable { | |||||||
|         return mWriteTimeout; |         return mWriteTimeout; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * read/write buffer size | ||||||
|  |      */ | ||||||
|  |     public void setReadBufferSize(int bufferSize) { | ||||||
|  |         if (getReadBufferSize() == bufferSize) | ||||||
|  |             return; | ||||||
|  |         synchronized (mReadBufferLock) { | ||||||
|  |             mReadBuffer = ByteBuffer.allocate(bufferSize); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getReadBufferSize() { | ||||||
|  |         return mReadBuffer.capacity(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setWriteBufferSize(int bufferSize) { | ||||||
|  |         if(getWriteBufferSize() == bufferSize) | ||||||
|  |             return; | ||||||
|  |         synchronized (mWriteBufferLock) { | ||||||
|  |             ByteBuffer newWriteBuffer = ByteBuffer.allocate(bufferSize); | ||||||
|  |             if(mWriteBuffer.position() > 0) | ||||||
|  |                 newWriteBuffer.put(mWriteBuffer.array(), 0, mWriteBuffer.position()); | ||||||
|  |             mWriteBuffer = newWriteBuffer; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getWriteBufferSize() { | ||||||
|  |         return mWriteBuffer.capacity(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /* |     /* | ||||||
|      * when writeAsync is used, it is recommended to use readTimeout != 0, |      * when writeAsync is used, it is recommended to use readTimeout != 0, | ||||||
|      * else the write will be delayed until read data is available |      * else the write will be delayed until read data is available | ||||||
|      */ |      */ | ||||||
|     public void writeAsync(byte[] data) { |     public void writeAsync(byte[] data) { | ||||||
|         synchronized (mWriteBuffer) { |         synchronized (mWriteBufferLock) { | ||||||
|             mWriteBuffer.put(data); |             mWriteBuffer.put(data); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -150,34 +186,37 @@ public class SerialInputOutputManager implements Runnable { | |||||||
| 
 | 
 | ||||||
|     private void step() throws IOException { |     private void step() throws IOException { | ||||||
|         // Handle incoming data. |         // Handle incoming data. | ||||||
|         int len = mSerialPort.read(mReadBuffer.array(), mReadTimeout); |         byte[] buffer = null; | ||||||
|  |         synchronized (mReadBufferLock) { | ||||||
|  |             buffer = mReadBuffer.array(); | ||||||
|  |         } | ||||||
|  |         int len = mSerialPort.read(buffer, mReadTimeout); | ||||||
|         if (len > 0) { |         if (len > 0) { | ||||||
|             if (DEBUG) Log.d(TAG, "Read data len=" + len); |             if (DEBUG) Log.d(TAG, "Read data len=" + len); | ||||||
|             final Listener listener = getListener(); |             final Listener listener = getListener(); | ||||||
|             if (listener != null) { |             if (listener != null) { | ||||||
|                 final byte[] data = new byte[len]; |                 final byte[] data = new byte[len]; | ||||||
|                 mReadBuffer.get(data, 0, len); |                 System.arraycopy(buffer, 0, data, 0, len); | ||||||
|                 listener.onNewData(data); |                 listener.onNewData(data); | ||||||
|             } |             } | ||||||
|             mReadBuffer.clear(); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Handle outgoing data. |         // Handle outgoing data. | ||||||
|         byte[] outBuff = null; |         buffer = null; | ||||||
|         synchronized (mWriteBuffer) { |         synchronized (mWriteBufferLock) { | ||||||
|             len = mWriteBuffer.position(); |             len = mWriteBuffer.position(); | ||||||
|             if (len > 0) { |             if (len > 0) { | ||||||
|                 outBuff = new byte[len]; |                 buffer = new byte[len]; | ||||||
|                 mWriteBuffer.rewind(); |                 mWriteBuffer.rewind(); | ||||||
|                 mWriteBuffer.get(outBuff, 0, len); |                 mWriteBuffer.get(buffer, 0, len); | ||||||
|                 mWriteBuffer.clear(); |                 mWriteBuffer.clear(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (outBuff != null) { |         if (buffer != null) { | ||||||
|             if (DEBUG) { |             if (DEBUG) { | ||||||
|                 Log.d(TAG, "Writing data len=" + len); |                 Log.d(TAG, "Writing data len=" + len); | ||||||
|             } |             } | ||||||
|             mSerialPort.write(outBuff, mWriteTimeout); |             mSerialPort.write(buffer, mWriteTimeout); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user