mirror of
				https://github.com/mik3y/usb-serial-for-android
				synced 2025-10-31 02:17:23 +00:00 
			
		
		
		
	Initial CDC ACM support.
Tested on Arduino Uno.
This commit is contained in:
		
							parent
							
								
									f801b31997
								
							
						
					
					
						commit
						b4b6d147ea
					
				| @ -2,4 +2,6 @@ | ||||
| <resources> | ||||
|     <!-- 0x0403 / 0x6001: FTDI FT232R UART --> | ||||
|     <usb-device vendor-id="1027" product-id="24577" /> | ||||
|     <!-- 0x2341 / 0x0001: Arduino Uno --> | ||||
|     <usb-device vendor-id="9025" product-id="1" /> | ||||
| </resources> | ||||
|  | ||||
| @ -0,0 +1,159 @@ | ||||
| package com.hoho.android.usbserial.driver; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.util.Arrays; | ||||
| 
 | ||||
| import android.hardware.usb.UsbConstants; | ||||
| import android.hardware.usb.UsbDevice; | ||||
| import android.hardware.usb.UsbDeviceConnection; | ||||
| import android.hardware.usb.UsbEndpoint; | ||||
| import android.hardware.usb.UsbInterface; | ||||
| import android.util.Log; | ||||
| 
 | ||||
| /** | ||||
|  * USB CDC/ACM serial driver implementation. | ||||
|  * | ||||
|  * @author mike wakerly (opensource@hoho.com) | ||||
|  */ | ||||
| public class CdcAcmSerialDriver implements UsbSerialDriver { | ||||
|     private final String TAG = CdcAcmSerialDriver.class.getSimpleName(); | ||||
| 
 | ||||
|     private UsbDevice mDevice; | ||||
|     private UsbDeviceConnection mConnection; | ||||
|     private final byte[] mReadBuffer = new byte[4096]; | ||||
| 
 | ||||
|     private UsbInterface mControlInterface; | ||||
|     private UsbInterface mDataInterface; | ||||
| 
 | ||||
|     private UsbEndpoint mControlEndpoint; | ||||
|     private UsbEndpoint mReadEndpoint; | ||||
|     private UsbEndpoint mWriteEndpoint; | ||||
| 
 | ||||
|     /** | ||||
|      * @param usbDevice | ||||
|      * @param connection | ||||
|      */ | ||||
|     public CdcAcmSerialDriver(UsbDevice usbDevice, UsbDeviceConnection connection) { | ||||
|         mDevice = usbDevice; | ||||
|         mConnection = connection; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void open() throws IOException { | ||||
|         Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount()); | ||||
| 
 | ||||
|         Log.d(TAG, "Claiming control interface."); | ||||
|         mControlInterface = mDevice.getInterface(0); | ||||
|         Log.d(TAG, "Control iface=" + mControlInterface); | ||||
|         // class should be USB_CLASS_COMM | ||||
| 
 | ||||
|         if (!mConnection.claimInterface(mControlInterface, true)) { | ||||
|             throw new IOException("Could not claim control interface."); | ||||
|         } | ||||
|         mControlEndpoint = mControlInterface.getEndpoint(0); | ||||
|         Log.d(TAG, "Control endpoint direction: " + mControlEndpoint.getDirection()); | ||||
| 
 | ||||
|         Log.d(TAG, "Claiming data interface."); | ||||
|         mDataInterface = mDevice.getInterface(1); | ||||
|         Log.d(TAG, "data iface=" + mDataInterface); | ||||
|         // class should be USB_CLASS_CDC_DATA | ||||
| 
 | ||||
|         if (!mConnection.claimInterface(mDataInterface, true)) { | ||||
|             throw new IOException("Could not claim data interface."); | ||||
|         } | ||||
|         mReadEndpoint = mDataInterface.getEndpoint(1); | ||||
|         Log.d(TAG, "Read endpoint direction: " + mReadEndpoint.getDirection()); | ||||
|         mWriteEndpoint = mDataInterface.getEndpoint(0); | ||||
|         Log.d(TAG, "Write endpoint direction: " + mWriteEndpoint.getDirection()); | ||||
| 
 | ||||
|         Log.d(TAG, "Setting line coding"); | ||||
|         setBaudRate(115200); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void close() throws IOException { | ||||
|         mConnection.close(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int read(byte[] dest, int timeoutMillis) throws IOException { | ||||
|         int readAmt = Math.min(dest.length, mReadBuffer.length); | ||||
|         readAmt = Math.min(readAmt, mReadEndpoint.getMaxPacketSize()); | ||||
|         final int transferred = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt, | ||||
|                 timeoutMillis); | ||||
| 
 | ||||
|         if (transferred < 0) { | ||||
|             throw new IOException("Timeout reading timeoutMillis=" + timeoutMillis); | ||||
|         } | ||||
|         System.arraycopy(mReadBuffer, 0, dest, 0, transferred); | ||||
|         return transferred; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int write(byte[] src, int timeoutMillis) throws IOException { | ||||
|         int offset = 0; | ||||
|         final int chunksize = mWriteEndpoint.getMaxPacketSize(); | ||||
| 
 | ||||
|         while (offset < src.length) { | ||||
|             final byte[] writeBuffer; | ||||
|             final int writeLength; | ||||
| 
 | ||||
|             // bulkTransfer does not support offsets; make a copy if necessary. | ||||
|             writeLength = Math.min(src.length - offset, chunksize); | ||||
|             if (offset == 0) { | ||||
|                 writeBuffer = src; | ||||
|             } else { | ||||
|                 writeBuffer = Arrays.copyOfRange(src, offset, offset + writeLength); | ||||
|             } | ||||
| 
 | ||||
|             final int amt = mConnection.bulkTransfer(mWriteEndpoint, writeBuffer, writeLength, | ||||
|                     timeoutMillis); | ||||
|             if (amt <= 0) { | ||||
|                 throw new IOException("Error writing " + writeLength | ||||
|                         + " bytes at offset " + offset + " length=" + src.length); | ||||
|             } | ||||
|             Log.d(TAG, "Wrote amt=" + amt + " attempted=" + writeBuffer.length); | ||||
|             offset += amt; | ||||
|         } | ||||
|         return offset; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int setBaudRate(int baudRate) throws IOException { | ||||
|         setAcmLineCoding(baudRate, 0, 0, 8); | ||||
|         return baudRate; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public UsbDevice getDevice() { | ||||
|         return mDevice; | ||||
|     } | ||||
| 
 | ||||
|     public static boolean probe(UsbDevice usbDevice) { | ||||
|         return usbDevice.getVendorId() == 0x2341 && usbDevice.getProductId() == 0x001; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -49,6 +49,20 @@ public enum UsbSerialProber { | ||||
|             } | ||||
|             return new FtdiSerialDriver(usbDevice, connection); | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
|     CDC_ACM_SERIAL { | ||||
|         @Override | ||||
|         public UsbSerialDriver getDevice(UsbManager manager, UsbDevice usbDevice) { | ||||
|             if (!CdcAcmSerialDriver.probe(usbDevice)) { | ||||
|                 return null; | ||||
|             } | ||||
|             final UsbDeviceConnection connection = manager.openDevice(usbDevice); | ||||
|             if (connection == null) { | ||||
|                 return null; | ||||
|             } | ||||
|             return new CdcAcmSerialDriver(usbDevice, connection); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user