Android USBシリアル通信開発基本フロー

7748 ワード

長い間文章を書いていませんが、年前に会社が新しいプロジェクトを開きました.usbシリアル通信に関連しています.需要はアンドロイドタブレットでusbを介して転送した後、いくつかの外付け機器と通信し、最近まで忙しくて、ゆっくりと暇になりました.今週末に忙しくないうちに、usbシリアル通信開発の基本的な流れを記録します.
我々が開発したのはusbホストモード,すなわち,アンドロイドタブレットをホストとし,usb外付けをスレーブとしてデータ通信を行う.開発プロセス全体は以下の点にまとめることができます.
1.デバイスの発見
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
Map<String, UsbDevice> usbList = usbManager.getDeviceList();

UsbManagerというシステムが提供するクラスを通じて、現在接続されているすべてのusbデバイスを挙げることができます.主にUsbDeviceオブジェクトが必要です.UsbDeviceというクラスについて、公式にはこのように注釈されています.
This class represents a USB device attached to the android device with the android device
 acting as the USB host.

はい、このクラスはandroidが接続されているusbデバイスを表しています.
2.デバイスを開く
次に、検索したばかりのusbデバイスを開く必要があります.タブレットとusb周辺機器の接続を1つのチャネルとして想像することができます.チャネルのドアを開けてから、両側で通信することができます.
一般的に、カスタマイズされていないandroidデバイスで初めてusbデバイスにアクセスする場合、デフォルトではアクセス権がありません.そのため、まず、現在開くusbDeviceにアクセス権があるかどうかを判断します.
if (!usbManager.hasPermission(usbDevice)) {
       usbPermissionReceiver = new UsbPermissionReceiver();
       //    
       Intent intent = new Intent(ACTION_DEVICE_PERMISSION);
       PendingIntent mPermissionIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
       IntentFilter permissionFilter = new IntentFilter(ACTION_DEVICE_PERMISSION);
       context.registerReceiver(usbPermissionReceiver, permissionFilter);
       usbManager.requestPermission(usbDevice, mPermissionIntent);
        }

ここでは、承認されたブロードキャストを受信した後、他の処理を行うブロードキャストUsbPermissionReceiverを宣言します.
  private class UsbPermissionReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_DEVICE_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (device.getDeviceName().equals(usbDevice.getDeviceName()) {
                        if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                          //    ,           
                        } else {
                          //    
                        }
                    }
                }
            }
        }
    }

次に、データ転送機能を持つインタフェースUsbInterfaceを見つけ、その中からデータ入力と出力ポートUsbEndpointを見つけます.一般的に、1つのusbDeviceには複数のUsbInterfaceがあります.私たちが必要とするのは一般的に1つ目です.
usbInterface=usbDevice.getInterface(0);

同じように、1つのusbInterfaceには複数のUsbEndpointがあり、制御ポートとデータポートなどがあります.そのため、タイプとデータの流れに基づいて、必要なデータの入力と出力の2つのポートを見つける必要があります.
for (int index = 0; index < usbInterface.getEndpointCount(); index++) {
                UsbEndpoint point = usbInterface.getEndpoint(index);
                if (point.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                    if (point.getDirection() == UsbConstants.USB_DIR_IN) {
                        usbEndpointIn = point;
                    } else if (point.getDirection() == UsbConstants.USB_DIR_OUT) {
                        usbEndpointOut = point;
                    }
                }
            }

最後に、本当にusbデバイスを開くには、usb周辺機器とUsbDeviceConnectionを構築する必要があります.その注釈は、その用途を簡単に説明しています.
This class is used for sending and receiving data and control messages to a USB device.

その取得も簡単で、コードだけです.
usbDeviceConnection = usbManager.openDevice(usbDevice);

ここまで、理論的にはタブレットとusb外付けの間の接続が確立されており、データを先発することもできますが、ほとんどの場合、ボートレート、停止ビット、データ制御など、usbシリアルポートの構成が必要です.そうしないと、両側の構成が異なり、受信したデータが文字化されません.具体的にどのように配置するかは、あなたが使っているシリアルチップが何なのかを見てみましょう.現在流行しているのはpl 2303、ch 340などです.紙面の問題で、シリアルコードを具体的に配置する必要がある友达の私信は私が送ります.
3.データ転送
ここでは,usb周辺機器とのデータ伝送が可能になったが,まずusbデバイスへのデータ送信方法を見る.
 1. usb      

第2のステップでは、データの出力ポートusbEndpointInを取得しました.このポートによってデータを送信することで実現されます.使い方を見てみましょう.
int ret = usbDeviceConnection.bulkTransfer(usbEndpointOut, data, data.length, DEFAULT_TIMEOUT);

bulkTransferこの関数は、所与のポートでデータ転送を行うために使用されます.最初のパラメータは今回の転送のポートです.ここで私たちが使用する出力ポートは、2番目のパラメータは送信するデータで、タイプはバイト配列で、3番目のパラメータは送信するデータの長さを表し、最後のパラメータはタイムアウトで、戻り値は送信に成功したバイト数を表し、-1を返すと、送信に失敗します.
2.  usb        

同様に、データ入力ポートusbEndpointInを見つけました.データの入力は不定期であるため、別のスレッドを開いてデータを受け入れることができます.データを受け入れるコードは以下の通りです.
int inMax = inEndpoint.getMaxPacketSize(); 
ByteBuffer byteBuffer = ByteBuffer.allocate(inMax); 
UsbRequest usbRequest = new UsbRequest(); 
usbRequest.initialize(connection, inEndpoint); 
usbRequest.queue(byteBuffer, inMax); 
if(connection.requestWait() == usbRequest){ 
    byte[] retData = byteBuffer.array(); 
    for(Byte byte1 : retData){ 
        System.err.println(byte1); 
    } 
}

以上、usbシリアル通信の基本的な流れですが、一部の場所では全面的に書かれていません.例えば、usb外付けデータを受信する方法には他にもあるはずです.不足点は指摘を歓迎します.