您的位置:首页 > 移动开发 > Android开发

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

2017-11-16 18:35 375 查看
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方式一般需要看芯片手册来确定具体设置值替代上面的参数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐