diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java index 6dabac1..912feac 100644 --- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java +++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java @@ -15,6 +15,9 @@ import java.util.Map; * USB CDC/ACM serial driver implementation. * * @author mike wakerly (opensource@hoho.com) + * @see Universal + * Serial Bus Class Definitions for Communication Devices, v1.1 */ public class CdcAcmSerialDriver extends UsbSerialDriver { @@ -27,6 +30,22 @@ public class CdcAcmSerialDriver extends UsbSerialDriver { private UsbEndpoint mReadEndpoint; private UsbEndpoint mWriteEndpoint; + private int mBaudRate; + private int mDataBits; + private int mStopBits; + private int mParity; + + private boolean mRts = false; + private boolean mDtr = false; + + private static final int USB_RECIP_INTERFACE = 0x01; + private static final int USB_RT_ACM = UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE; + + private static final int SET_LINE_CODING = 0x20; // USB CDC 1.1 section 6.2 + private static final int GET_LINE_CODING = 0x21; + private static final int SET_CONTROL_LINE_STATE = 0x22; + private static final int SEND_BREAK = 0x23; + public CdcAcmSerialDriver(UsbDevice device, UsbDeviceConnection connection) { super(device, connection); } @@ -59,31 +78,17 @@ public class CdcAcmSerialDriver extends UsbSerialDriver { mWriteEndpoint = mDataInterface.getEndpoint(0); Log.d(TAG, "Write endpoint direction: " + mWriteEndpoint.getDirection()); - Log.d(TAG, "Setting line coding"); - setBaudRate(115200); - + Log.d(TAG, "Setting line coding to 115200/8N1"); + mBaudRate = 115200; + mDataBits = DATABITS_8; + mParity = PARITY_NONE; + mStopBits = STOPBITS_1; + setParameters(mBaudRate, mDataBits, mStopBits, mParity); } - private static final int USB_RECIP_INTERFACE = 0x01; - private static final int USB_RT_ACM = UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE; - - private static final int SET_LINE_CODING = 0x20; // USB CDC 1.1 section 6.2 - private int sendAcmControlMessage(int request, int value, byte[] buf) { - return mConnection.controlTransfer(USB_RT_ACM, request, value, 0, buf, buf != null ? buf.length : 0, 5000); - } - - private int setAcmLineCoding(int bitRate, int stopBits, int parity, int dataBits) { - byte[] msg = { - (byte) ( bitRate & 0xff), - (byte) ((bitRate >> 8 ) & 0xff), - (byte) ((bitRate >> 16) & 0xff), - (byte) ((bitRate >> 24) & 0xff), - - (byte) stopBits, - (byte) parity, - (byte) dataBits}; - return sendAcmControlMessage(SET_LINE_CODING, 0, msg); + return mConnection.controlTransfer( + USB_RT_ACM, request, value, 0, buf, buf != null ? buf.length : 0, 5000); } @Override @@ -145,50 +150,90 @@ public class CdcAcmSerialDriver extends UsbSerialDriver { return offset; } + @Deprecated @Override public int setBaudRate(int baudRate) throws IOException { - setAcmLineCoding(baudRate, 0, 0, 8); - return baudRate; + mBaudRate = baudRate; + setParameters(mBaudRate, mDataBits, mStopBits, mParity); + return mBaudRate; + } + + @Override + public void setParameters(int baudRate, int dataBits, int stopBits, int parity) { + byte stopBitsByte; + switch (stopBits) { + case STOPBITS_1: stopBitsByte = 1; break; + case STOPBITS_1_5: stopBitsByte = 2; break; + case STOPBITS_2: stopBitsByte = 3; break; + default: throw new IllegalArgumentException("Bad value for stopBits: " + stopBits); + } + + byte parityBitesByte; + switch (parity) { + case PARITY_NONE: parityBitesByte = 0; break; + case PARITY_ODD: parityBitesByte = 1; break; + case PARITY_EVEN: parityBitesByte = 2; break; + case PARITY_MARK: parityBitesByte = 3; break; + case PARITY_SPACE: parityBitesByte = 4; break; + default: throw new IllegalArgumentException("Bad value for parity: " + parity); + } + + byte[] msg = { + (byte) ( baudRate & 0xff), + (byte) ((baudRate >> 8 ) & 0xff), + (byte) ((baudRate >> 16) & 0xff), + (byte) ((baudRate >> 24) & 0xff), + stopBitsByte, + parityBitesByte, + (byte) dataBits}; + sendAcmControlMessage(SET_LINE_CODING, 0, msg); } @Override public boolean getCD() throws IOException { - return false; + return false; // TODO } @Override public boolean getCTS() throws IOException { - return false; + return false; // TODO } @Override public boolean getDSR() throws IOException { - return false; + return false; // TODO } @Override public boolean getDTR() throws IOException { - return false; + return mDtr; } @Override - public boolean setDTR(boolean value) throws IOException { - return false; + public void setDTR(boolean value) throws IOException { + mDtr = value; + setDtrRts(); } @Override public boolean getRI() throws IOException { - return false; + return false; // TODO } @Override public boolean getRTS() throws IOException { - return false; + return mRts; } @Override - public boolean setRTS(boolean value) throws IOException { - return false; + public void setRTS(boolean value) throws IOException { + mRts = value; + setDtrRts(); + } + + private void setDtrRts() { + int value = (mRts ? 0x2 : 0) | (mDtr ? 0x1 : 0); + sendAcmControlMessage(SET_CONTROL_LINE_STATE, value, null); } public static Map getSupportedDevices() { diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/FtdiSerialDriver.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/FtdiSerialDriver.java index da22fd8..22f59e8 100644 --- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/FtdiSerialDriver.java +++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/FtdiSerialDriver.java @@ -90,6 +90,9 @@ import java.util.Map; public class FtdiSerialDriver extends UsbSerialDriver { private static final int DEFAULT_BAUD_RATE = 115200; + private static final int DEFAULT_DATA_BITS = DATABITS_8; + private static final int DEFAULT_PARITY = PARITY_NONE; + private static final int DEFAULT_STOP_BITS = STOPBITS_1; public static final int USB_TYPE_STANDARD = 0x00 << 5; public static final int USB_TYPE_CLASS = 0x00 << 5; @@ -161,6 +164,11 @@ public class FtdiSerialDriver extends UsbSerialDriver { private int mMaxPacketSize = 64; // TODO(mikey): detect + private int mBaudRate; + private int mDataBits; + private int mParity; + private int mStopBits; + /** * Due to http://b.android.com/28023 , we cannot use UsbRequest async reads * since it gives no indication of number of bytes read. Set this to @@ -204,7 +212,7 @@ public class FtdiSerialDriver extends UsbSerialDriver { } } reset(); - setBaudRate(DEFAULT_BAUD_RATE); + setParameters(DEFAULT_BAUD_RATE, DEFAULT_DATA_BITS, DEFAULT_STOP_BITS, DEFAULT_PARITY); opened = true; } finally { if (!opened) { @@ -307,13 +315,12 @@ public class FtdiSerialDriver extends UsbSerialDriver { } @Override + @Deprecated public int setBaudRate(int baudRate) throws IOException { long[] vals = convertBaudrate(baudRate); long actualBaudrate = vals[0]; long index = vals[1]; long value = vals[2]; - Log.i(TAG, "Requested baudrate=" + baudRate + ", actual=" + actualBaudrate); - int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_SET_BAUD_RATE_REQUEST, (int) value, (int) index, null, 0, USB_WRITE_TIMEOUT_MILLIS); @@ -323,6 +330,59 @@ public class FtdiSerialDriver extends UsbSerialDriver { return (int) actualBaudrate; } + @Override + public void setParameters(int baudRate, int dataBits, int stopBits, int parity) + throws IOException { + mBaudRate = setBaudRate(baudRate); + + int config = dataBits; + + switch (parity) { + case PARITY_NONE: + config |= (0x00 << 8); + break; + case PARITY_ODD: + config |= (0x01 << 8); + break; + case PARITY_EVEN: + config |= (0x02 << 8); + break; + case PARITY_MARK: + config |= (0x03 << 8); + break; + case PARITY_SPACE: + config |= (0x04 << 8); + break; + default: + throw new IllegalArgumentException("Unknown parity value: " + parity); + } + + switch (stopBits) { + case STOPBITS_1: + config |= (0x00 << 11); + break; + case STOPBITS_1_5: + config |= (0x01 << 11); + break; + case STOPBITS_2: + config |= (0x02 << 11); + break; + default: + throw new IllegalArgumentException("Unknown stopBits value: " + stopBits); + } + + int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, + SIO_SET_DATA_REQUEST, config, 0 /* index */, + null, 0, USB_WRITE_TIMEOUT_MILLIS); + if (result != 0) { + throw new IOException("Setting parameters failed: result=" + result); + } + + mParity = parity; + mStopBits = stopBits; + mDataBits = dataBits; + } + private long[] convertBaudrate(int baudrate) { // TODO(mikey): Braindead transcription of libfti method. Clean up, // using more idiomatic Java where possible. @@ -430,8 +490,7 @@ public class FtdiSerialDriver extends UsbSerialDriver { } @Override - public boolean setDTR(boolean value) throws IOException { - return false; + public void setDTR(boolean value) throws IOException { } @Override @@ -445,8 +504,7 @@ public class FtdiSerialDriver extends UsbSerialDriver { } @Override - public boolean setRTS(boolean value) throws IOException { - return false; + public void setRTS(boolean value) throws IOException { } public static Map getSupportedDevices() { diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java index 41970ce..e084ef2 100644 --- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java +++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java @@ -47,6 +47,30 @@ public abstract class UsbSerialDriver { /** Internal write buffer. Guarded by {@link #mWriteBufferLock}. */ protected byte[] mWriteBuffer; + public static final int DATABITS_5 = 5; + public static final int DATABITS_6 = 6; + public static final int DATABITS_7 = 7; + public static final int DATABITS_8 = 8; + + public static final int FLOWCONTROL_NONE = 0; + public static final int FLOWCONTROL_RTSCTS_IN = 1; + public static final int FLOWCONTROL_RTSCTS_OUT = 2; + public static final int FLOWCONTROL_XONXOFF_IN = 4; + public static final int FLOWCONTROL_XONXOFF_OUT = 8; + + public static final int PARITY_EVEN = 2; + public static final int PARITY_MARK = 3; + public static final int PARITY_NONE = 0; + public static final int PARITY_ODD = 1; + public static final int PARITY_SPACE = 4; + + /** 1 stop bit. */ + public static final int STOPBITS_1 = 1; + /** 1.5 stop bits. */ + public static final int STOPBITS_1_5 = 3; + /** 2 stop bits. */ + public static final int STOPBITS_2 = 2; + public UsbSerialDriver(UsbDevice device, UsbDeviceConnection connection) { mDevice = device; mConnection = connection; @@ -96,9 +120,27 @@ public abstract class UsbSerialDriver { * @param baudRate the desired baud rate, in bits per second * @return the actual rate set * @throws IOException on error setting the baud rate + * @deprecated Use {@link #setParameters(int, int, int, int)} instead of this method. */ + @Deprecated public abstract int setBaudRate(final int baudRate) throws IOException; + /** + * Sets various serial port parameters. + * + * @param baudRate baud rate as an integer, for example {@code 115200}. + * @param dataBits one of {@link #DATABITS_5}, {@link #DATABITS_6}, + * {@link #DATABITS_7}, or {@link #DATABITS_8}. + * @param stopBits one of {@link #STOPBITS_1}, {@link #STOPBITS_1_5}, or + * {@link #STOPBITS_2}. + * @param parity one of {@link #PARITY_NONE}, {@link #PARITY_ODD}, + * {@link #PARITY_EVEN}, {@link #PARITY_MARK}, or + * {@link #PARITY_SPACE}. + * @throws IOException on error setting the port parameters + */ + public abstract void setParameters( + int baudRate, int dataBits, int stopBits, int parity) throws IOException; + /** * Gets the CD (Carrier Detect) bit from the underlying UART. * @@ -138,7 +180,7 @@ public abstract class UsbSerialDriver { * @param value the value to set * @throws IOException if an error occurred during writing */ - public abstract boolean setDTR(boolean value) throws IOException; + public abstract void setDTR(boolean value) throws IOException; /** * Gets the RI (Ring Indicator) bit from the underlying UART. @@ -160,10 +202,10 @@ public abstract class UsbSerialDriver { * Sets the RTS (Request To Send) bit on the underlying UART, if * supported. * - * @param value thje value to set + * @param value the value to set * @throws IOException if an error occurred during writing */ - public abstract boolean setRTS(boolean value) throws IOException; + public abstract void setRTS(boolean value) throws IOException; /** * Returns the currently-bound USB device.