最近做了个平板与单片机的项目,由于使用的平板不支持串口,所以中间借助了usb-串口转换器(PL2303)。
这方面的资料可以说少之又少,几乎没有,我唯一能找到的就是usb-serial-for-android,一个国外的开源项目。
实现了一些主要的转换器的驱动,但是国内一般用得最多的还是PL2303。
我将usb-serial-for-android的驱动简化了下,成功的与串口调试工具通信了,能读,能写。给大家分享下。
下载:https://pan.baidu.com/s/1i4CT7pj
或者直接下载
驱动源码:
package com.example.android_usb;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
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.hardware.usb.UsbManager;
import android.util.Log;
import android.widget.Toast;
/**
* PL2303串口驱动
* @author pc
*
*/
public class ProlificSerialDriver {
private static final int USB_READ_TIMEOUT_MILLIS = 5000;
private static final int USB_WRITE_TIMEOUT_MILLIS = 3000;
private final Object mReadBufferLock = new Object();
private final Object mWriteBufferLock = new Object();
private byte[] buffer = new byte[4096];
private ByteArrayOutputStream bufferOS = new ByteArrayOutputStream();
private Context context;
private UsbEndpoint mReadEndpoint;
private UsbEndpoint mWriteEndpoint;
private UsbDeviceConnection connection;
private UsbDevice usbDevice;
public ProlificSerialDriver(Context context, UsbDevice usbDevice){
this.context = context;
this.usbDevice = usbDevice;
}
/**
* 安装
* @param baudRate
* @throws IOException
*/
public void setup(int baudRate) throws IOException{
open();
initPL2303Chip();
ctrlOut(baudRate);
}
private void open() throws IOException{
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
//申请权限
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent("com.prolific.pl2303hxdsimpletest.USB_PERMISSION"), 0);
usbManager.requestPermission(usbDevice, mPermissionIntent);
UsbInterface usbInterface = usbDevice.getInterface(0);
for (int i = 0; i < usbInterface.getEndpointCount(); ++i) {
UsbEndpoint currentEndpoint = usbInterface.getEndpoint(i);
switch (currentEndpoint.getAddress()) {
case 0x83:
mReadEndpoint = currentEndpoint;
break;
case 0x02:
mWriteEndpoint = currentEndpoint;
break;
}
}
connection = usbManager.openDevice(usbDevice);
connection.claimInterface(usbInterface, true);
}
private final void ctrlOut(int baudRate) throws IOException {
//设置传输控制
byte[] lineRequestData = new byte[7];
lineRequestData[0] = (byte) (baudRate & 0xff);
lineRequestData[1] = (byte) ((baudRate >> 8) & 0xff);
lineRequestData[2] = (byte) ((baudRate >> 16) & 0xff);
lineRequestData[3] = (byte) ((baudRate >> 24) & 0xff);
lineRequestData[4] = 0;
lineRequestData[5] = 0;
lineRequestData[6] = (byte) 8;
outControlTransfer(UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_CLASS | 0x01, 0x20, 0, 0, lineRequestData);
}
/**
* 初始化芯片
* @throws IOException
*/
private void initPL2303Chip() throws IOException{
int mDeviceType = getDeviceType();
vendorIn(0x8484, 0, 1);
vendorOut(0x0404, 0, null);
vendorIn(0x8484, 0, 1);
vendorIn(0x8383, 0, 1);
vendorIn(0x8484, 0, 1);
vendorOut(0x0404, 1, null);
vendorIn(0x8484, 0, 1);
vendorIn(0x8383, 0, 1);
vendorOut(0, 1, null);
vendorOut(1, 0, null);
vendorOut(2, (mDeviceType == 0) ? 0x44 : 0x24, null);
}
/**
* 获得设备类型
*/
private int getDeviceType(){
int mDeviceType = 0;
try {
if (usbDevice.getDeviceClass() == 0x02) {
mDeviceType = 1;
} else{
Method getRawDescriptorsMethod = connection.getClass().getMethod("getRawDescriptors");
byte[] rawDescriptors = (byte[]) getRawDescriptorsMethod.invoke(connection);
byte maxPacketSize0 = rawDescriptors[7];
if (maxPacketSize0 == 64) {
mDeviceType = 0;
} else if ((usbDevice.getDeviceClass() == 0x00) || (usbDevice.getDeviceClass() == 0xff)) {
mDeviceType = 2;
} else {
mDeviceType = 0;
}
}
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return mDeviceType;
}
/**
* 写
* @param buf
* @param wlength
* @return
*/
public int write(byte[] buf, int wlength) {
int offset = 0;
byte[] write_buf = new byte[4096];
synchronized (mWriteBufferLock) {
while (offset < wlength) {
int write_size = 4096;
if (offset + write_size > wlength) {
write_size = wlength - offset;
}
System.arraycopy(buf, offset, write_buf, 0, write_size);
int actual_length = this.connection.bulkTransfer(this.mWriteEndpoint, write_buf, write_size, USB_WRITE_TIMEOUT_MILLIS);
if (actual_length < 0) {
return -1;
}
offset += actual_length;
}
}
return offset;
}
/**
* 读取
* @param timeoutMillis
* @throws IOException
*/
public byte[] read() throws IOException {
synchronized (mReadBufferLock) {
try {
bufferOS.reset();
int number = 0;
while(number != -1){
number = connection.bulkTransfer(mReadEndpoint, buffer, buffer.length, USB_READ_TIMEOUT_MILLIS);
MainActivity.showMessage("number:"+number);
bufferOS.write(buffer, 0, number);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return bufferOS.toByteArray();
}
/**
* 关闭资源
*/
public void close(){
try {
if (connection == null) {
return ;
}
connection.releaseInterface(this.usbDevice.getInterface(0));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 输出的传输
* @throws IOException
*/
private final void outControlTransfer(int requestType, int request, int value, int index, byte[] data) throws IOException {
int length = (data == null) ? 0 : data.length;
int result = connection.controlTransfer(requestType, request, value, index, data, length, USB_WRITE_TIMEOUT_MILLIS);
if (result != length) {
throw new IOException(String.format("ControlTransfer with value 0x%x failed: %d", value, result));
}
}
/**
* 输入的传输
* @throws IOException
*/
private final byte[] inControlTransfer(int requestType, int request, int value, int index, int length) throws IOException {
byte[] buffer = new byte[length];
int result = connection.controlTransfer(requestType, request, value, index, buffer, length, USB_READ_TIMEOUT_MILLIS);
if (result != length) {
throw new IOException(String.format("ControlTransfer with value 0x%x failed: %d", value, result));
}
return buffer;
}
/**
* 写设备控制
*/
private final byte[] vendorIn(int value, int index, int length)throws IOException {
return inControlTransfer(UsbConstants.USB_DIR_IN | UsbConstants.USB_TYPE_VENDOR, 0x01, value, index, length);
}
/**
* 读设备控制
*/
private final void vendorOut(int value, int index, byte[] data)throws IOException {
outControlTransfer(UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR, 0x01, value, index, data);
}
}