USB host 通信

公司主打支付产品,产品是和Android平板连接起来的。Android平板怎么和产品通信呢?串口或者USB口。串口通信比较简单,下篇再讲,此篇主要讲的是usb host通信。

一:寻找UsbDevice并授权

两种方法寻找usb device,1是通过Intent Filter来寻找,2是通过枚举所有的设备来寻找

1.在manifest文件中添加如下代码:

[java]  view plain  copy
  1. <activity ...>  
  2.     ...  
  3.     <intent-filter>  
  4.         <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />  
  5.     </intent-filter>  
  6.     <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" />  
  7. </activity>  

然后再res文件夹下创建一个device_filter.xml文件如下 :

[java]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.    <usb-device vendor-id="1411" product-id="22336"  />  
  4. </resources>  
然后在包含此 Intent Filter的 activity中通过如下方法就可以得到已经授权的USBDevice了

[html]  view plain  copy
  1. Intent intent = getIntent();  
  2. UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);  
当用户在已经打开此应用的平板中插入产品模块的时候,此activity会自动打开并弹出对话框,“是否授权usb读写权限”,当用户点击“是”时,此应用就会得到应用授权的UsbDevice。

2.通过枚举所有的设备来寻找

[html]  view plain  copy
  1. mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);  
  2. getUsbDevice(mUsbManager);  
  3. ......  
  4. private void getUsbDevice(UsbManager mUsbManager)   
  5.     {  
  6.         HashMap<String, UsbDevice> devicesList = mUsbManager.getDeviceList();  
  7.         Iterator<UsbDevice> deviceIterator = devicesList.values().iterator();  
  8.           
  9.         while(deviceIterator.hasNext())   
  10.         {  
  11.             UsbDevice usb = deviceIterator.next();  
  12.             if(usb.getProductId()==0x5740 && usb.getVendorId()==0x0583)   
  13.             {  
  14.                 usbDevice = usb;  
  15.             }  
  16.         }  
  17.     }  
但是通过此方法寻找出来的usbDevice并没有得到授权,所以需要在此之上进行授权,怎么授权,如下:

[java]  view plain  copy
  1. mUsbReceiver = new UsbReceiver();  
  2. IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);  
  3. filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);  
  4. filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);  
  5. registerReceiver(mUsbReceiver, filter);  
  6. mPermissionIntent = PendingIntent.getBroadcast(this0new Intent(ACTION_USB_PERMISSION), 0);  
  7. mUsbManager.requestPermission(usbDevice, mPermissionIntent);  
mUsbManager调用方法  requestPermission()  将弹出对话框,以询问用户是授权应用。广播接收类如下:

[java]  view plain  copy
  1. private class UsbReceiver extends BroadcastReceiver  
  2.     {  
  3.   
  4.         @Override  
  5.         public void onReceive(Context context, Intent intent)  
  6.         {  
  7.             // TODO Auto-generated method stub  
  8.             String action = intent.getAction();  
  9.             if (ACTION_USB_PERMISSION.equals(action))   
  10.             {                 
  11.                 synchronized (this)   
  12.                 {   
  13.                     usbDevice = (UsbDevice) intent  
  14.                             .getParcelableExtra(UsbManager.EXTRA_DEVICE);  
  15.                     boolean usbPremission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);  
  16.                     if((usbPremission) && (usbDevice != null))  
  17.                     {  
  18.                         findEndPoint();  
  19.                         openDevice(localUsbInterface);  
  20.                     }                     
  21.                     else   
  22.                     {  
  23.                     }  
  24.                 }  
  25.   
  26.             }   
  27.             else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action))   
  28.             {                 
  29.                 usbDevice = (UsbDevice) intent  
  30.                         .getParcelableExtra(UsbManager.EXTRA_DEVICE);  
  31.                 if(usbDevice != null)  
  32.                 {  
  33.                     }  
  34.                 else  
  35.                 {  
  36.                 }  
  37.                 if (!mUsbManager.hasPermission(usbDevice)) {  
  38.                     mUsbManager.requestPermission(usbDevice, mPermissionIntent);  
  39.                 }  
  40.             }   
  41.             else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action))   
  42.             {  
  43.                 usbDevice = (UsbDevice) intent  
  44.                         .getParcelableExtra(UsbManager.EXTRA_DEVICE);  
  45.             }         
  46.           
  47.         }     
  48.     }  

二:找到智能卡接口(UsbInterface)并找到此接口中的输入,输出等端口(UsbEndpoint)

[java]  view plain  copy
  1. public void findEndPoint()  
  2.     {  
  3.         int countInterface = usbDevice.getInterfaceCount();  
  4.         Log.i("kejian","countInterface = "+countInterface);  
  5.         int i=0;  
  6.         int interfaceClass=0;  
  7.         for(i=0;i<countInterface;i++)  
  8.         {  
  9.              localUsbInterface= usbDevice.getInterface(i);  
  10.              interfaceClass=localUsbInterface.getInterfaceClass();  
  11.              //如果当前接口不是智能卡接口,则不处理   
  12.              if(interfaceClass!=0x0B)  
  13.                  continue;  
  14.             int countEndpoint=localUsbInterface.getEndpointCount();  
  15.             UsbEndpoint localUsbEndpoint;  
  16.             for(int j=0;j<countEndpoint;j++)  
  17.             {  
  18.                   
  19.                 localUsbEndpoint=localUsbInterface.getEndpoint(j);                
  20.                 int typeEndpoint=localUsbEndpoint.getType();  
  21. //              端点类型为2,批量传输  
  22.                 if(typeEndpoint==2)  
  23.                 {  
  24.                     if(localUsbEndpoint.getDirection()==0)  
  25.                     {  
  26.                         //localObject1是输出端点  
  27.                         if(localObject1==null)  
  28.                             localObject1=localUsbEndpoint;  
  29.                     }  
  30.                     else if(localObject2==null)  
  31.                     {  
  32.                         //localObject2是输入端点  
  33.                         localObject2=localUsbEndpoint;  
  34.                     }  
  35.                 }  
  36.                 else  
  37.                 {  
  38.                     //端点类型为3,中断方式  
  39.                     if(typeEndpoint!=3)  
  40.                         continue;  
  41.                     if((localUsbEndpoint.getDirection()!=0x80)||(localObject3!=null))  
  42.                     {  
  43.                         continue;  
  44.                     }  
  45.                     localObject3=localUsbEndpoint;  
  46.                 }  
  47.             }  
  48.         }  
  49.     }  

三:打开此端口

[java]  view plain  copy
  1. public void openDevice(UsbInterface mInterface) {    
  2.         if (mInterface != null) {    
  3.             UsbDeviceConnection conn = null;    
  4.             // 在open前判断是否有连接权限;对于连接权限可以静态分配,也可以动态分配权限    
  5.             if (mUsbManager.hasPermission(usbDevice)) {    
  6.                 conn = mUsbManager.openDevice(usbDevice);    
  7.             }    
  8.     
  9.             if (conn == null) {    
  10.                 return;    
  11.             }    
  12.     
  13.             if (conn.claimInterface(mInterface, true)) {    
  14.                 myDeviceConnection = conn;    
  15.                 if (myDeviceConnection != null)// 到此你的android设备已经连上zigbee设备    
  16.                     System.out.println("open设备成功!");    
  17.                 final String mySerial = myDeviceConnection.getSerial();    
  18.                 System.out.println("设备serial number:" + mySerial);    
  19.             } else {    
  20.                 System.out.println("无法打开连接通道。");    
  21.                 conn.close();    
  22.             }    
  23.         }    
  24.     }  
经过上面这些步骤,接下来就可以进行通信了

[html]  view plain  copy
  1. Button trans_btn = (Button) this.findViewById(R.id.trans);  
  2.         trans_btn.setOnClickListener(new View.OnClickListener() {  
  3.               
  4.             @Override  
  5.             public void onClick(View v) {  
  6.                 // TODO Auto-generated method stub  
  7.                 new Thread(new Runnable(){  
  8.   
  9.                     @Override  
  10.                     public void run() {  
  11.                         trans();  
  12.                     }  
  13.                 }).start();  
  14.                 }  
  15.         });  

通信方法如下:

[java]  view plain  copy
  1. public void trans() {  
  2.         int status = myDeviceConnection.bulkTransfer((UsbEndpoint)localObject1, USB_CARD_SWING_COMMAND, USB_CARD_SWING_COMMAND.length, 6000);  
  3.           
  4.         byte []tmpRecv=new byte[2048];  
  5.           
  6.         status=myDeviceConnection.bulkTransfer((UsbEndpoint)localObject2,tmpRecv ,tmpRecv.length, 60000);  
  7.         Log.d(TAG,"recv len = "+status);  
  8.         byte []dataReturn=new byte[status];  
  9.         System.arraycopy(tmpRecv, 0, dataReturn, 0, status);  
  10.           
  11.         Log.d(TAG,"sendApdu Recv = "+Utils.bytesToHexStr(dataReturn, 0,  status));  
  12.     }  
第一个bulkTransfer方法是给产品模块发送数据,产品模块对此数据进行处理之后,会返回数据,这里的第二个bulkTransfer方法就是用来接收数据的,根据log信息显示的是正确的返回信息。


参考资料:

http://blog.csdn.net/halsonhe/article/details/46648699

http://blog.csdn.net/wizardmly/article/details/8350137



关于usb host通信说的比较详细的blog系列:http://www.cnblogs.com/sowhat4999/p/4439877.html
相关文章

相关标签/搜索