Android USBシリアル通信開発基本フロー
7748 ワード
長い間文章を書いていませんが、年前に会社が新しいプロジェクトを開きました.usbシリアル通信に関連しています.需要はアンドロイドタブレットでusbを介して転送した後、いくつかの外付け機器と通信し、最近まで忙しくて、ゆっくりと暇になりました.今週末に忙しくないうちに、usbシリアル通信開発の基本的な流れを記録します.
我々が開発したのはusbホストモード,すなわち,アンドロイドタブレットをホストとし,usb外付けをスレーブとしてデータ通信を行う.開発プロセス全体は以下の点にまとめることができます.
1.デバイスの発見
UsbManagerというシステムが提供するクラスを通じて、現在接続されているすべてのusbデバイスを挙げることができます.主にUsbDeviceオブジェクトが必要です.UsbDeviceというクラスについて、公式にはこのように注釈されています.
はい、このクラスはandroidが接続されているusbデバイスを表しています.
2.デバイスを開く
次に、検索したばかりのusbデバイスを開く必要があります.タブレットとusb周辺機器の接続を1つのチャネルとして想像することができます.チャネルのドアを開けてから、両側で通信することができます.
一般的に、カスタマイズされていないandroidデバイスで初めてusbデバイスにアクセスする場合、デフォルトではアクセス権がありません.そのため、まず、現在開くusbDeviceにアクセス権があるかどうかを判断します.
ここでは、承認されたブロードキャストを受信した後、他の処理を行うブロードキャストUsbPermissionReceiverを宣言します.
次に、データ転送機能を持つインタフェースUsbInterfaceを見つけ、その中からデータ入力と出力ポートUsbEndpointを見つけます.一般的に、1つのusbDeviceには複数のUsbInterfaceがあります.私たちが必要とするのは一般的に1つ目です.
同じように、1つのusbInterfaceには複数のUsbEndpointがあり、制御ポートとデータポートなどがあります.そのため、タイプとデータの流れに基づいて、必要なデータの入力と出力の2つのポートを見つける必要があります.
最後に、本当にusbデバイスを開くには、usb周辺機器とUsbDeviceConnectionを構築する必要があります.その注釈は、その用途を簡単に説明しています.
その取得も簡単で、コードだけです.
ここまで、理論的にはタブレットとusb外付けの間の接続が確立されており、データを先発することもできますが、ほとんどの場合、ボートレート、停止ビット、データ制御など、usbシリアルポートの構成が必要です.そうしないと、両側の構成が異なり、受信したデータが文字化されません.具体的にどのように配置するかは、あなたが使っているシリアルチップが何なのかを見てみましょう.現在流行しているのはpl 2303、ch 340などです.紙面の問題で、シリアルコードを具体的に配置する必要がある友达の私信は私が送ります.
3.データ転送
ここでは,usb周辺機器とのデータ伝送が可能になったが,まずusbデバイスへのデータ送信方法を見る.
第2のステップでは、データの出力ポートusbEndpointInを取得しました.このポートによってデータを送信することで実現されます.使い方を見てみましょう.
bulkTransferこの関数は、所与のポートでデータ転送を行うために使用されます.最初のパラメータは今回の転送のポートです.ここで私たちが使用する出力ポートは、2番目のパラメータは送信するデータで、タイプはバイト配列で、3番目のパラメータは送信するデータの長さを表し、最後のパラメータはタイムアウトで、戻り値は送信に成功したバイト数を表し、-1を返すと、送信に失敗します.
同様に、データ入力ポートusbEndpointInを見つけました.データの入力は不定期であるため、別のスレッドを開いてデータを受け入れることができます.データを受け入れるコードは以下の通りです.
以上、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外付けデータを受信する方法には他にもあるはずです.不足点は指摘を歓迎します.