zoukankan      html  css  js  c++  java
  • Android USB Host与HID通讯

    前端时间捣鼓一个HID的硬件, 需要和android通信, 网上搜索了一圈,收获不小.

    比较好的文章是: 
         Android USB Host与HID通讯

         Android Service创建USB HOST通信

    其中代码之处有些地方需要注意的, 特此注明一下:

    /**
     * USB HOST 连接 HID
     * @author IVAN
     *
     */
    public class MainActivity extends Activity {
        private static final String TAG = "USB_HOST";
     
        private UsbManager myUsbManager;
        private UsbDevice myUsbDevice;
        private UsbInterface myInterface;
        private UsbDeviceConnection myDeviceConnection;
     
        private final int VendorID = 8457;    //这里要改成自己的硬件ID
        private final int ProductID = 30264;
     
        private TextView info;
     
        private UsbEndpoint epOut;
        private UsbEndpoint epIn;
     
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
     
            info = (TextView) findViewById(R.id.info);
     
            // 获取UsbManager
            myUsbManager = (UsbManager) getSystemService(USB_SERVICE);
     
            enumerateDevice();
     
            findInterface();
     
            openDevice();
     
            assignEndpoint();
     
        }
     
        /**
         * 分配端点,IN | OUT,即输入输出;此处我直接用1为OUT端点,0为IN,当然你也可以通过判断
         */

         //USB_ENDPOINT_XFER_BULK
         /*
         #define USB_ENDPOINT_XFER_CONTROL 0 --控制传输
         #define USB_ENDPOINT_XFER_ISOC 1 --等时传输
         #define USB_ENDPOINT_XFER_BULK 2 --块传输
         #define USB_ENDPOINT_XFER_INT 3 --中断传输
         * */

        private void assignEndpoint() {

              if (myInterface != null) { //这一句不加的话 很容易报错  导致很多人在各大论坛问:为什么报错呀 

                  //这里的代码替换了一下 按自己硬件属性判断吧

                 for (int i = 0; i < myInterface.getEndpointCount(); i++) { 

                    UsbEndpoint ep = myInterface.getEndpoint(i);

                    if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {
                    if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                       epOut = ep;

                     } else { 

                      epIn = ep;

                      }
                    }
                  }
               }

            Log.d(TAG, getString(R.string.text));
        }
     
        /**
         * 打开设备
         */
        private void openDevice() {
            if (myInterface != null) {
                UsbDeviceConnection conn = null;
                // 在open前判断是否有连接权限;对于连接权限可以静态分配,也可以动态分配权限,可以查阅相关资料
                if (myUsbManager.hasPermission(myUsbDevice)) {
                    conn = myUsbManager.openDevice(myUsbDevice);
                }
     
                if (conn == null) {
                    return;
                }
     
                if (conn.claimInterface(myInterface, true)) {
                    myDeviceConnection = conn; // 到此你的android设备已经连上HID设备
                    Log.d(TAG, "打开设备成功");
                } else {
                    conn.close();
                }
            }
        }
     
        /**
         * 找设备接口
         */
        private void findInterface() {
            if (myUsbDevice != null) {
                Log.d(TAG, "interfaceCounts : " + myUsbDevice.getInterfaceCount());
                for (int i = 0; i < myUsbDevice.getInterfaceCount(); i++) {
                    UsbInterface intf = myUsbDevice.getInterface(i);
                    // 根据手上的设备做一些判断,其实这些信息都可以在枚举到设备时打印出来
                    if (intf.getInterfaceClass() == 8
                            && intf.getInterfaceSubclass() == 6
                            && intf.getInterfaceProtocol() == 80) {
                        myInterface = intf;
                        Log.d(TAG, "找到我的设备接口");
                    }
                    break;
                }
            }
        }
     
        /**
         * 枚举设备
         */
        private void enumerateDevice() {
            if (myUsbManager == null)
                return;
     
            HashMap<String, UsbDevice> deviceList = myUsbManager.getDeviceList();
            if (!deviceList.isEmpty()) { // deviceList不为空
                StringBuffer sb = new StringBuffer();
                for (UsbDevice device : deviceList.values()) {
                    sb.append(device.toString());
                    sb.append("
    ");
                    info.setText(sb);
                    // 输出设备信息
                    Log.d(TAG, "DeviceInfo: " + device.getVendorId() + " , "
                            + device.getProductId());
     
                    // 枚举到设备
                    if (device.getVendorId() == VendorID
                            && device.getProductId() == ProductID) {
                        myUsbDevice = device;
                        Log.d(TAG, "枚举设备成功");
                    }
                }
            }
        }
     
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    }

    获取数据的代码:

     ncount = myDeviceConnection.bulkTransfer(epIn, buffer, buffer.length,  
                                100);

    这里注意数据读取的长度, 这个对某些硬件来说非常重要,  有的硬件小了或者大了立马死机重启, 要么就是一直返回-1

    这个数据的长度需要根据硬件属性来,

        有一种办法是通过int inMax = epIn.getMaxPacketSize()来获取;

        还有一种办法是通过windows下面的hid程序探测设备的数据长度;

    至于读不到硬件的问题 我觉得以下办法不会有帮助了, 要么是硬件不支持, android4.0以上 貌似都包含了以下的文件信息了

    将android.hardware.usb.host.xml文件放到/system/etc/permissions下;第二处是在同目录下的handheld_core_hardware.xml里面添加一句<feature name="android.hardware.usb.host">

  • 相关阅读:
    【python cookbook】【数据结构与算法】12.找出序列中出现次数最多的元素
    [转]ASP.NET MVC 5
    [转]ASP.NET MVC 5 学习教程:快速入门
    Using XSLT and Open XML to Create a Word 2007 Document
    如何在VS2010中更好的编写JavaScript代码
    [转]这五种方法前四种方法只支持IE浏览器,最后一个方法支持当前主流的浏览器(火狐,IE,Chrome,Opera,Safari)
    [转]C# 超高速高性能写日志 代码开源
    windows 2003 发布遇到问题---分析器错误消息: 未能加载类型“YWPT.MvcApplication”。
    将Oracle数据库转换为SQL Server
    SQLServer2008导出表数据为SQL脚本
  • 原文地址:https://www.cnblogs.com/doorsky/p/4388849.html
Copyright © 2011-2022 走看看