android apk使用framework中usb接口范例(应用RtkGps分析)

来源:互联网 发布:膛线无缝管淘宝有售吗 编辑:程序博客网 时间:2024/05/16 02:49
1、首先需要在AndroidManifest中要监听usb设备插入的activity或service等中加入
<intent-filter><action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /></intent-filter><meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"android:resource="@xml/usb_device_filter" />
其中usb_device_filter是一个自己编写的文件,里面描述的是希望接管的usb设备信息。如:
<?xml version="1.0" encoding="utf-8"?><resources><!-- Prolific --><usb-device vendor-id="1659"product-id="8963" /><!-- 0x067b 0x2303 PL2303 Serial--><usb-device vendor-id="1659"product-id="4660" /><!-- 0x067b 0x1234 DCU-11 Phone Cable--><usb-device vendor-id="21362"product-id="8963" /><!-- 0x5372 0x2303 Prolific2 PL2303--><!-- Generic comunnication device with Abstract Control Model subclass--><usb-device class="2"subclass="0"protocol="0" /></resources>
主要是vendor-id和product-id的值与usb设备一致。

2、首先在MainActivity中当mNavDrawerServerSwitch被checked时,start RtkNaviService,在onStartCommand中执行processStart,在processStart中执行UsbToRtklib.start(),在UsbToRtklib.start()执行UsbReceiver.start(),在UsbReceiver.start()中增加usb事件的检测:
f = new IntentFilter();
f.addAction(ACTION_USB_DEVICE_ATTACHED);
f.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);

f.addAction(ACTION_USB_PERMISSION);

mContext.registerReceiver(mUsbStateListener, f);

mServiceThread = new UsbServiceThread();
mServiceThread.start();
执行UsbServiceThread的run时,子线程UsbServiceThread卡在serialControllerSet.block();等待serialControllerSet.open()来唤醒这个子线程。

主线程之后执行

findSupportedDevice()  ---> probeDevice(),之后就new出UsbPl2303Controller,new UsbPl2303Controller 时就会拿到各种interface和endpoint的信息,可以用来传递数据用。

                    |

1)已连接usb设备:

主线程:

requestPermission()

                    |

ACTION_USB_PERMISSION

                    |

2)没有连接usb设备:

当连接usb设备后,就会执行:

mUsbStateListener下的

ACTION_USB_DEVICE_ATTACHED

                     |

onUsbDeviceAttached();

                    |

probeDevice()  ---> probeDevice(),之后就new出UsbPl2303Controller,requestPermission()

                    |

ACTION_USB_PERMISSION

                    |

3)

主线程:

onUsbPermissionGranted()

                   |

mServiceThread.setController(controller);   其中执行serialControllerSet.open() ,唤醒UsbServiceThread线程。


UsbServiceThread子线程:

mUsbController.attach();

这个执行打开usb设备:

mUsbConnection = mUsbManager.openDevice(mUsbDevice);
if (mUsbConnection == null) {
    throw new UsbControllerException("openDevice() failed");
}

将usb设备和本程序绑定(用本程序代替usb上层驱动来管理usb设备,如:当usb设备是U盘时,代替mass storge驱动来管理u盘,此时u盘会被卸载)

for (int i=0; i< mUsbInterfaces.length; ++i) {
    if (mUsbConnection.claimInterface(mUsbInterfaces[i], true) == false) {
        for (int j=0; j<i; ++j) {
            mUsbConnection.releaseInterface(mUsbInterfaces[j]);
        }
        mUsbConnection.close();
        throw new UsbControllerException("claimInterface() failed");
    }
}

对usb设备的reset和初始化(就是驱动usb设备,发送controlTransfer设置usb设备)

if (!pl2303Reset()) {
    detach();
    throw new UsbControllerException("pl2303Reset() failed");
}
if (!pl2303Init()) {
    detach();
    throw new UsbControllerException("pl2303Init() failed");
}

使用之前拿到的bulk endpoint得到InputStream和OutputStream,为之后数据传输做准备。

inputStream = new UsbSerialInputStream(mUsbConnection, mBulkInEndpoint);
outputStream = new UsbSerialOutputStream(mUsbConnection, mBulkOutEndpoint);


interrupt endpoint 只能用自己封装urb(也就是UsbRequest)的方式传送usb数据给usb device;

bulk endpoint 可以使用mUsbConnection.bulkTransfer传送数据给usb device;

control endpoint可以使用mUsbConnection.controlTransfer传送数据给usb device;(control endpoint一般是endpoint 0,是不直接暴露给用户使用的,必须用这个函数操作。


下面详解各种用法:

1、interrupt 方式数据传输:

protected static class UsbSerialInterruptListener extends Thread {
    
    private boolean cancelRequested = false;
    private UsbDeviceConnection mUsbConnection;
    private ByteBuffer buffer;
    private UsbRequest request;
            
    public UsbSerialInterruptListener(UsbDeviceConnection connection, UsbEndpoint endpoint) {
        this.mUsbConnection = connection;
        this.setName("PL2303InterruptListener");
        buffer =  ByteBuffer.allocate(endpoint.getMaxPacketSize());
        request = new UsbRequest();
        request.initialize(connection, endpoint);

    }

     @Override
     public void run() {
    mainloop: while(!cancelRequested()) {
        request.queue(buffer, buffer.capacity());
        if (mUsbConnection.requestWait() == request) {
            if (D) Log.v(TAG, "Interrupt received: " + buffer.toString() +
                    Arrays.toString(buffer.array()));
            synchronized(this) {
                try {
                    this.wait(100);
                } catch (InterruptedException e) {
                    break mainloop;
                }
                if (cancelRequested) break mainloop;
            }
         }else {
             Log.e(TAG, "requestWait failed, exiting");
             break mainloop;
         }
       }
        Log.d(TAG, "Pl2303InterruptListener thread stopped");
    }

    public synchronized void cancel() {
          cancelRequested = true;
          this.notify();
     }

     private synchronized boolean cancelRequested() {
           return this.cancelRequested;
     }

}


2、bulk的方式传输数据

bulk in:

protected class UsbSerialInputStream extends InputStream {
        
    private static final int DEFAULT_READ_TIMEOUT_MS = 30000;
    private int mTimeout = DEFAULT_READ_TIMEOUT_MS;
            
    private UsbDeviceConnection mUsbConnection;
    private UsbEndpoint mUsbEndpoint;
    private byte rcvPkt[] = null;
            
    public UsbSerialInputStream(UsbDeviceConnection connection,
            UsbEndpoint bulkInEndpoint,
            int writeTmoutMs
            ) {
        mUsbConnection = connection;
        mUsbEndpoint = bulkInEndpoint;
        mTimeout = writeTmoutMs;
        rcvPkt = new byte[mUsbEndpoint.getMaxPacketSize()];
    }

    public UsbSerialInputStream(UsbDeviceConnection connection,
            UsbEndpoint bulkInEndpoint) {
        this(connection, bulkInEndpoint, DEFAULT_READ_TIMEOUT_MS);
    }

    @Override
    public int read() throws IOException {
        synchronized(this) {
        int rcvd = read(rcvPkt, 0, 1);
        if (rcvd == 0) throw new IOException("timeout");
        return rcvPkt[0] & 0xff;
        }
    }

  @Override
  public int read(byte[] buffer, int offset, int count) throws IOException {
    int rcvd;

    synchronized(this) {
        if (offset == 0) {
            rcvd = mUsbConnection.bulkTransfer(mUsbEndpoint, buffer,
                    count, mTimeout);
            if (rcvd < 0) throw new IOException("bulkTransfer() error");
            //if (D) Log.d(TAG, "Received " + rcvd + " bytes aligned");
            return rcvd;
        }else {
            rcvd = mUsbConnection.bulkTransfer(mUsbEndpoint,
                    rcvPkt,
                    Math.min(count, rcvPkt.length),
                    mTimeout);
            if (rcvd < 0) throw new IOException("bulkTransfer() error");
            else if (rcvd > 0) {
                System.arraycopy(rcvPkt, 0, buffer, offset, rcvd);
            }
            if (D) Log.d(TAG, "Received " + rcvd + " bytes");
                return rcvd;
        }
     }
  }
}


bulk out:

protected class UsbSerialOutputStream extends OutputStream {

    private static final int DEFAULT_WRITE_TIMEOUT_MS = 2000;
    private int mTimeout = DEFAULT_WRITE_TIMEOUT_MS;

    private UsbDeviceConnection mUsbConnection;
    private UsbEndpoint mUsbEndpoint;
    private byte sndPkt[] = null;

    public UsbSerialOutputStream(UsbDeviceConnection connection,
            UsbEndpoint bulkOutEndpoint,
            int writeTmoutMs
            ) {
        mUsbConnection = connection;
        mUsbEndpoint = bulkOutEndpoint;
        mTimeout = writeTmoutMs;
        sndPkt = new byte[mUsbEndpoint.getMaxPacketSize()];
    }

    public UsbSerialOutputStream(UsbDeviceConnection connection,
            UsbEndpoint bulkOutEndpoint) {
        this(connection, bulkOutEndpoint, DEFAULT_WRITE_TIMEOUT_MS);
    }

    @Override
    public void write(int arg0) throws IOException {
        write(new byte[] { (byte) arg0 } );
    }
     @Override
     public void write(byte[] buffer, int offset, int count) throws IOException {
         synchronized(this) {
             while(count>0) {
                 /* XXX: timeout */
                 int length = count > sndPkt.length ? sndPkt.length : count;
                 System.arraycopy(buffer, offset, sndPkt, 0, length);
                 int snd = mUsbConnection.bulkTransfer(mUsbEndpoint, sndPkt, length, mTimeout);
                 if (snd<0) throw new IOException("bulkTransfer() failed");
                 count -= snd;
                 offset += snd;
             }
         }
     }
 }


3、control方式传输:

mUsbConnection.controlTransfer(
 UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR,
 0x01 /* set request */,
 0x0000,
 0x0000,
 null,
 0,
 PL2303_INIT_TIMEOUT_MS) >= 0;

control方式一般需要看芯片手册来确定具体设置值替代上面的参数。


原创粉丝点击