使用Andriod的USB主机API来阅读我的USB游戏手柄/或其他USB设备的数据 [英] Using Andriod USB Host API to read my USB game controller/Or other USB device data
问题描述
我想使用的Andriod USB主机API来阅读我的USB游戏控制器的数据,一旦我得到这个工作,我将连接其他设备进行测试。
我的游戏控制器使用OTG线连接到我的Andriod手机。我现在能够得到的设备,端点的信息,但我不知道如何读的原始数据并显示它。
有人能帮帮我吗?一些示例codeS将AP preciated。
谢谢!
的TextView countDisplay;
ArrayList的<串GT;时listItems =新的ArrayList<串GT;();
ArrayAdapter<串GT;适配器;
字符串值=;
UsbManager mManager的;
UsbDevice设备= NULL;
私人字节[]字节;
私有静态诠释TIMEOUT = 0;
私人布尔forceClaim = TRUE;
静态的PendingIntent mPermissionIntent;
UsbDeviceConnection连接= NULL;
UsbEndpoint InputEndpoint = NULL;
UsbEndpoint OutputEndpoint = NULL;
私人处理程序mHandler =新的处理程序();
@覆盖
公共无效的onCreate(捆绑savedInstanceState){
super.onCreate(savedInstanceState);
mManager的=(UsbManager)getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(这一点,0,新意图(
com.android.example.USB_PERMISSION),0);
IntentFilter的过滤器=新的IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(mUsbReceiver,过滤器); HashMap的<弦乐,UsbDevice> DEVICELIST = mManager.getDeviceList();
值=价值+deviceListSize:+ deviceList.size()+的toString:
+ deviceList.toString();
迭代器< UsbDevice> deviceIterator = deviceList.values()迭代器()。
而(deviceIterator.hasNext()){
设备= deviceIterator.next();
值=价值+,设备ID:+ device.getDeviceId()
+,设备名称:+ device.getDeviceName();
值=价值+,协议:+ device.getDeviceProtocol()
+,产品编号:+ device.getProductId();
值=价值+,DEVICECLASS:+ device.getDeviceClass()
+,VENDORID:+ device.getVendorId();
}
如果(设备!= NULL){
值=价值+,getInterfaceCount:
+ device.getInterfaceCount();
的UsbInterface INTF = device.getInterface(0);
值=价值+,intf.getEndpointCount():
+ intf.getEndpointCount();
UsbEndpoint端点1 = intf.getEndpoint(0);
UsbEndpoint端点2 = intf.getEndpoint(1); mManager.requestPermission(设备,mPermissionIntent);
如果(mManager.hasPermission(设备)){
值=价值+,拥有超过设备的许可!;
连接= mManager.openDevice(设备);
如果(连接== NULL){
值=价值+,连接空;
}其他{
值=价值+,getFileDescriptor:
+ connection.getFileDescriptor();
如果(endpoint1.getDirection()== UsbConstants.USB_DIR_IN){
InputEndpoint =端点1;
}其他{
OutputEndpoint =端点1;
}
如果(endpoint2.getDirection()== UsbConstants.USB_DIR_IN){
InputEndpoint =端点2;
}其他{
OutputEndpoint =端点2;
}
}
如果(InputEndpoint == NULL){
countDisplay.setText(值+,InputEndpoint为空);
}
如果(OutputEndpoint == NULL){
countDisplay.setText(值+,OutputEndPoint为空);
}
connection.claimInterface(INTF,forceClaim);
mHandler.postDelayed(可运行,1);
}其他{
值=价值+,没有权限在设备!
} } 的setContentView(R.layout.activity_main);
LayoutInflater吹气=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 视图V = inflater.inflate(R.layout.activity_main,NULL);
LL的LinearLayout =新的LinearLayout(本);
ll.setOrientation(LinearLayout.VERTICAL);
INT计数器= 1;
countDisplay =新的TextView(本);
ll.addView(countDisplay); countDisplay.setText(值+,反在这里);
最后Button按钮=新按钮(本);
button.setOnClickListener(新OnClickListener(){ @覆盖
公共无效的onClick(视图v){
// TODO自动生成方法存根
如果(设备= NULL&放大器;!&安培; mManager.hasPermission(设备)){
值=价值+,设备ID:+ device.getDeviceId()
+,设备名称:+ device.getDeviceName();
值=价值+,协议:+ device.getDeviceProtocol()
+,产品编号:+ device.getProductId();
值=价值+,DEVICECLASS:+ device.getDeviceClass()
+,VENDORID:+ device.getVendorId(); countDisplay.setText(值+,奥科克); }其他{
如果(设备!= NULL)
mManager.requestPermission(设备,mPermissionIntent);
}
} });
ll.addView(按钮);
的setContentView(Ⅱ);
}
和Runnable接口:
私人可运行的可运行=新的Runnable(){
公共无效的run(){
如果(连接!= NULL){
诠释计数= connection.bulkTransfer(InputEndpoint,字节,
bytes.length,TIMEOUT);
countDisplay.setText(值+,bultTransferNo:+计数);
countDisplay.setText(值+bulkValue:+字节);
}其他{
countDisplay.setText(值+,连接为空);
}
}
};
该计划作为下面的USB主机功能的例子:
-
根据接口类,子类和协议(见device_filter.xml)配套设备
-
异步IO上批量端点
所有code版权所有:
/ *
*版权所有(C)2011年Android开源项目
*
*在Apache许可,2.0版(以下简称许可证);
*您不能使用这个文件除了在遵守许可。
*您可以在获得许可证的副本
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*除非适用法律要求或书面同意,软件
*许可下发布的分布在原样的基础,
*无担保或任何形式的条件,无论是前preSS或暗示的保证。
*请参阅许可证的特定语言的管理权限和
*根据许可证的限制。
* /
AdbDevice
包com.android.adb; 进口android.hardware.usb.UsbConstants;
进口android.hardware.usb.UsbDeviceConnection;
进口android.hardware.usb.UsbEndpoint;
进口android.hardware.usb.UsbInterface;
进口android.hardware.usb.UsbRequest;
进口android.util.SparseArray; 进口java.util.LinkedList中; / *这个类重presents支持亚行协议的USB设备。 * /
公共类AdbDevice { 私人最终AdbTestActivity mActivity;
私人最终UsbDeviceConnection mDeviceConnection;
私人最终UsbEndpoint mEndpointOut;
私人最终UsbEndpoint mEndpointIn; 私人字符串mSerial; //为OUT端点请求池
私人最终的LinkedList< UsbRequest> mOutRequestPool =新的LinkedList< UsbRequest>();
//为IN端点请求池
私人最终的LinkedList< UsbRequest> mInRequestPool =新的LinkedList< UsbRequest>();
//当前打开的套接字列表
私人最终SparseArray< AdbSocket> mSockets =新SparseArray< AdbSocket>();
私人INT mNextSocketId = 1; 私人最终WaiterThread mWaiterThread =新WaiterThread(); 公共AdbDevice(AdbTestActivity活动,UsbDeviceConnection连接,
INTF的UsbInterface){
mActivity =活动;
mDeviceConnection =连接;
mSerial = connection.getSerial(); UsbEndpoint epOut = NULL;
亿品UsbEndpoint = NULL;
//寻找我们的批量端点
的for(int i = 0; I< intf.getEndpointCount();我++){
UsbEndpoint EP = intf.getEndpoint(ⅰ);
如果(ep.getType()== UsbConstants.USB_ENDPOINT_XFER_BULK){
如果(ep.getDirection()== UsbConstants.USB_DIR_OUT){
epOut = EP;
}其他{
亿品= EP;
}
}
}
如果(epOut == NULL ||亿品== NULL){
抛出新抛出:IllegalArgumentException(未找到所有端点);
}
mEndpointOut = epOut;
mEndpointIn =亿品;
} //返回设备序列号
公共字符串getSerial(){
返回mSerial;
} //从我们的池出请求
公共UsbRequest getOutRequest(){
同步(mOutRequestPool){
如果(mOutRequestPool.isEmpty()){
UsbRequest要求=新UsbRequest();
request.initialize(mDeviceConnection,mEndpointOut);
返回请求;
}其他{
返回mOutRequestPool.removeFirst();
}
}
} //返回一个OUT请求池
公共无效releaseOutRequest(UsbRequest要求){
同步(mOutRequestPool){
mOutRequestPool.add(请求);
}
} //从池中获取IN请求
公共UsbRequest getInRequest(){
同步(mInRequestPool){
如果(mInRequestPool.isEmpty()){
UsbRequest要求=新UsbRequest();
request.initialize(mDeviceConnection,mEndpointIn);
返回请求;
}其他{
返回mInRequestPool.removeFirst();
}
}
} 公共无效的start(){
mWaiterThread.start();
连接();
} 公共AdbSocket openSocket(字符串目的地){
AdbSocket插座;
同步(mSockets){
INT ID = mNextSocketId ++;
插座=新AdbSocket(本,身份证);
mSockets.put(ID,插座);
}
如果(socket.open(目标)){
返回插座;
}其他{
返回null;
}
} 私人AdbSocket getSocket(INT ID){
同步(mSockets){
返回mSockets.get(ID);
}
} 公共无效socketClosed(AdbSocket插座){
同步(mSockets){
mSockets.remove(socket.getId());
}
} //发送连接命令
私人无效连接(){
AdbMessage消息=新AdbMessage();
message.set(AdbMessage.A_CNXN,AdbMessage.A_VERSION,AdbMessage.MAX_PAYLOAD,主持人:: \\ 0);
message.write(本);
} //处理连接响应
私人无效handleConnect(AdbMessage消息){
如果(message.getDataString()startsWith(设备:)){
日志(连接);
mActivity.deviceOnline(本);
}
} 公共无效停止(){
同步(mWaiterThread){
mWaiterThread.mStop = TRUE;
}
} //从设备调度的消息
无效DispatchMessage函数(AdbMessage消息){
INT命令= message.getCommand();
开关(命令){
案例AdbMessage.A_SYNC:
日志(得到A_SYNC);
打破;
案例AdbMessage.A_CNXN:
handleConnect(消息);
打破;
案例AdbMessage.A_OPEN:
案例AdbMessage.A_OKAY:
案例AdbMessage.A_CLSE:
案例AdbMessage.A_WRTE:
AdbSocket插座= getSocket(message.getArg1());
如果(插座== NULL){
日志(ERROR插座未找到);
}其他{
socket.handleMessage(消息);
}
打破;
}
} 无效日志(String s)将{
mActivity.log(多个);
}
私有类WaiterThread继承Thread {
公共布尔MSTOP; 公共无效的run(){
//启动了一个命令读
AdbMessage currentCommand =新AdbMessage();
AdbMessage CURRENTDATA = NULL;
// FIXME错误检查
currentCommand.readCommand(getInRequest()); 而(真){
同步(本){
如果(MSTOP){
返回;
}
}
UsbRequest请求= mDeviceConnection.requestWait();
如果(要求== NULL){
打破;
} AdbMessage消息=(AdbMessage)request.getClientData();
request.setClientData(NULL);
AdbMessage messageToDispatch = NULL; 如果(消息== currentCommand){
INT DATALENGTH = message.getDataLength();
//读取数据,如果长度GT; 0
如果(DATALENGTH大于0){
message.readData(getInRequest()DATALENGTH);
CURRENTDATA =消息;
}其他{
messageToDispatch =消息;
}
currentCommand = NULL;
}否则如果(消息== CURRENTDATA){
messageToDispatch =消息;
CURRENTDATA = NULL;
} 如果(messageToDispatch!= NULL){
//队列中的另一个读第一
currentCommand =新AdbMessage();
currentCommand.readCommand(getInRequest()); //然后派遣当前消息
在DispatchMessage(messageToDispatch);
} // PUT请求放回相应的池
如果(request.getEndpoint()== mEndpointOut){
releaseOutRequest(请求);
}其他{
同步(mInRequestPool){
mInRequestPool.add(请求);
}
}
}
}
}
}
AdbMessage
包com.android.adb; 进口android.hardware.usb.UsbRequest; 进口java.nio.ByteBuffer中;
进口java.nio.ByteOrder中; / *此类封装和亚行命令包* /
公共类AdbMessage { //命令名
公共静态最终诠释A_SYNC = 0x434e5953;
公共静态最终诠释A_CNXN = 0x4e584e43;
公共静态最终诠释A_OPEN = 0x4e45504f;
公共静态最终诠释A_OKAY = 0x59414b4f;
公共静态最终诠释A_CLSE = 0x45534c43;
公共静态最终诠释A_WRTE = 0x45545257; // ADB协议版本
公共静态最终诠释A_VERSION =为0x01000000; 公共静态最终诠释MAX_PAYLOAD = 4096; 私人最终的ByteBuffer mMessageBuffer;
私人最终的ByteBuffer mDataBuffer; 公共AdbMessage(){
mMessageBuffer = ByteBuffer.allocate(24);
mDataBuffer = ByteBuffer.allocate(MAX_PAYLOAD);
mMessageBuffer.order(ByteOrder.LITTLE_ENDIAN);
mDataBuffer.order(ByteOrder.LITTLE_ENDIAN);
} //设置在命令头字段
公共无效集(INT命令,诠释为arg0,ARG1 INT,字节[]数据){
mMessageBuffer.putInt(0,命令);
mMessageBuffer.putInt(4,为arg0);
mMessageBuffer.putInt(8,ARG1);
mMessageBuffer.putInt(12,(数据== NULL?0:data.length));
mMessageBuffer.putInt(16,(数据==空?0:校验(数据)));
mMessageBuffer.putInt(20,命令^ 0xFFFFFFFF的);
如果(数据!= NULL){
mDataBuffer.put(数据,0,data.length);
}
} 公共无效集(INT命令,诠释为arg0,ARG1 INT){
集(命令,为arg0,ARG1,(字节[])NULL);
}
公共无效集(INT命令,诠释为arg0,ARG1 INT,字符串数据){
//添加尾随零
数据+ ='\\ 0';
设置(指挥,为arg0,ARG1,data.getBytes());
} //返回命令的消息ID
公众诠释getCommand(){
返回mMessageBuffer.getInt(0);
} //返回命令的第一个参数
公众诠释getArg0(){
返回mMessageBuffer.getInt(4);
} //返回命令的第二个参数
公众诠释getArg1(){
返回mMessageBuffer.getInt(8);
} //返回命令的数据缓冲区
公众的ByteBuffer的getData(){
返回mDataBuffer;
} //返回命令的数据长度
公众诠释getDataLength(){
返回mMessageBuffer.getInt(12);
} //返回命令的数据作为一个字符串
公共字符串getDataString(){
INT长度= getDataLength();
如果(长度== 0)返回NULL;
//修剪尾随零
返回新的String(mDataBuffer.array(),0,长度 - 1);
}
公共布尔写(AdbDevice设备){
同步(器){
UsbRequest请求= device.getOutRequest();
request.setClientData(本);
如果(request.queue(mMessageBuffer,24)){
INT长度= getDataLength();
如果(长度大于0){
请求= device.getOutRequest();
request.setClientData(本);
如果(request.queue(mDataBuffer,长度)){
返回true;
}其他{
device.releaseOutRequest(请求);
返回false;
}
}
返回true;
}其他{
device.releaseOutRequest(请求);
返回false;
}
}
} 公共布尔readCommand(UsbRequest要求){
request.setClientData(本);
返回request.queue(mMessageBuffer,24);
} 公共布尔READDATA(UsbRequest要求,INT长度){
request.setClientData(本);
返回request.queue(mDataBuffer,长度);
} 私人静态字符串extractString(ByteBuffer的缓冲区,诠释抵消,诠释长度){
字节[]字节=新的字节[长度]
的for(int i = 0; I<长度;我++){
字节[I] = buffer.get(偏移++);
}
返回新的字符串(字节);
} @覆盖
公共字符串的toString(){
串的CommandName = extractString(mMessageBuffer,0,4);
INT DATALENGTH = getDataLength();
字符串结果=ADB消息:+ +的CommandName为arg0:+ getArg0()+
ARG1:+ getArg1()+DATALENGTH:+ DATALENGTH;
如果(DATALENGTH大于0){
结果+ =(数据:\\+ getDataString()+\\);
}
返回结果;
} 私有静态诠释校验(字节[]数据){
INT结果为0;
的for(int i = 0; I< data.length;我++){
INT X =数据[I]
//党,没有在java中的无符号整数
如果(X℃,)X + = 256;
结果+ = X;
}
返回结果;
}
}
AdbSocket
包com.android.adb; / *这个类重presents亚行插座。亚行支持多个独立
*套接字连接到一台设备。通常创建套接字
*为所执行的每个ADB命令。
* /
公共类AdbSocket { 私人最终AdbDevice mDevice;
私人最终诠释中旬;
私人诠释mPeerId; 公共AdbSocket(AdbDevice设备,INT ID){
mDevice =设备;
MID = ID;
} 公众诠释的getId(){
返回MID;
} 公共布尔开放(字符串目的地){
AdbMessage消息=新AdbMessage();
message.set(AdbMessage.A_OPEN,MID,0,目的地);
如果(!message.write(mDevice)){
返回false;
} 同步(本){
尝试{
等待();
}赶上(InterruptedException的E){
返回false;
}
}
返回true;
} 公共无效的handleMessage(AdbMessage消息){
开关(message.getCommand()){
案例AdbMessage.A_OKAY:
mPeerId = message.getArg0();
同步(本){
通知();
}
打破;
案例AdbMessage.A_WRTE:
mDevice.log(message.getDataString());
sendReady();
打破;
}
} 私人无效sendReady(){
AdbMessage消息=新AdbMessage();
message.set(AdbMessage.A_OKAY,MID,mPeerId);
message.write(mDevice);
}
}
I am trying to use Andriod USB Host API to read my USB game controller data, once I get this to work, I will connect other device to test. My game controller is connected to my Andriod phone using OTG cable. I am now able to get device, endpoints information, but I don't know how to read the raw data and display it.
Can someone please help me? Some example codes will be appreciated.
Thanks!!
TextView countDisplay;
ArrayList<String> listItems = new ArrayList<String>();
ArrayAdapter<String> adapter;
String values = "";
UsbManager mManager;
UsbDevice device = null;
private byte[] bytes;
private static int TIMEOUT = 0;
private boolean forceClaim = true;
static PendingIntent mPermissionIntent;
UsbDeviceConnection connection = null;
UsbEndpoint InputEndpoint = null;
UsbEndpoint OutputEndpoint = null;
private Handler mHandler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
"com.android.example.USB_PERMISSION"), 0);
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(mUsbReceiver, filter);
HashMap<String, UsbDevice> deviceList = mManager.getDeviceList();
values = values + "deviceListSize:" + deviceList.size() + ",tostring:"
+ deviceList.toString();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
device = deviceIterator.next();
values = values + ",device id:" + device.getDeviceId()
+ ",device name:" + device.getDeviceName();
values = values + ",Protocol:" + device.getDeviceProtocol()
+ ",ProductId:" + device.getProductId();
values = values + ",DeviceClass:" + device.getDeviceClass()
+ ",VendorId:" + device.getVendorId();
}
if (device != null) {
values = values + ",getInterfaceCount:"
+ device.getInterfaceCount();
UsbInterface intf = device.getInterface(0);
values = values + ",intf.getEndpointCount():"
+ intf.getEndpointCount();
UsbEndpoint endpoint1 = intf.getEndpoint(0);
UsbEndpoint endpoint2 = intf.getEndpoint(1);
mManager.requestPermission(device, mPermissionIntent);
if (mManager.hasPermission(device)) {
values = values + ",has permission over device!";
connection = mManager.openDevice(device);
if (connection == null) {
values = values + ",connection null";
} else {
values = values + ",getFileDescriptor:"
+ connection.getFileDescriptor();
if (endpoint1.getDirection() == UsbConstants.USB_DIR_IN) {
InputEndpoint = endpoint1;
} else {
OutputEndpoint = endpoint1;
}
if (endpoint2.getDirection() == UsbConstants.USB_DIR_IN) {
InputEndpoint = endpoint2;
} else {
OutputEndpoint = endpoint2;
}
}
if (InputEndpoint == null) {
countDisplay.setText(values + ",InputEndpoint is null");
}
if (OutputEndpoint == null) {
countDisplay.setText(values + ",OutputEndPoint is null");
}
connection.claimInterface(intf, forceClaim);
mHandler.postDelayed(runnable, 1);
} else {
values = values + ",Do not have permission over device!";
}
}
setContentView(R.layout.activity_main);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.activity_main, null);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
int counter = 1;
countDisplay = new TextView(this);
ll.addView(countDisplay);
countDisplay.setText(values + ",counter here");
final Button button = new Button(this);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (device != null && mManager.hasPermission(device)) {
values = values + ",device id:" + device.getDeviceId()
+ ",device name:" + device.getDeviceName();
values = values + ",Protocol:" + device.getDeviceProtocol()
+ ",ProductId:" + device.getProductId();
values = values + ",DeviceClass:" + device.getDeviceClass()
+ ",VendorId:" + device.getVendorId();
countDisplay.setText(values + ",okok");
} else {
if (device != null)
mManager.requestPermission(device, mPermissionIntent);
}
}
});
ll.addView(button);
setContentView(ll);
}
And Runnable:
private Runnable runnable = new Runnable() {
public void run() {
if (connection != null) {
int count = connection.bulkTransfer(InputEndpoint, bytes,
bytes.length, TIMEOUT);
countDisplay.setText(values + ",bultTransferNo:" + count);
countDisplay.setText(values + "bulkValue:" + bytes);
} else {
countDisplay.setText(values + ",connection is null");
}
}
};
This program serves as an example of the following USB host features:
Matching devices based on interface class, subclass and protocol (see device_filter.xml)
Asynchronous IO on bulk endpoints
All code Copyright:
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
AdbDevice
package com.android.adb;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbRequest;
import android.util.SparseArray;
import java.util.LinkedList;
/* This class represents a USB device that supports the adb protocol. */
public class AdbDevice {
private final AdbTestActivity mActivity;
private final UsbDeviceConnection mDeviceConnection;
private final UsbEndpoint mEndpointOut;
private final UsbEndpoint mEndpointIn;
private String mSerial;
// pool of requests for the OUT endpoint
private final LinkedList<UsbRequest> mOutRequestPool = new LinkedList<UsbRequest>();
// pool of requests for the IN endpoint
private final LinkedList<UsbRequest> mInRequestPool = new LinkedList<UsbRequest>();
// list of currently opened sockets
private final SparseArray<AdbSocket> mSockets = new SparseArray<AdbSocket>();
private int mNextSocketId = 1;
private final WaiterThread mWaiterThread = new WaiterThread();
public AdbDevice(AdbTestActivity activity, UsbDeviceConnection connection,
UsbInterface intf) {
mActivity = activity;
mDeviceConnection = connection;
mSerial = connection.getSerial();
UsbEndpoint epOut = null;
UsbEndpoint epIn = null;
// look for our bulk endpoints
for (int i = 0; i < intf.getEndpointCount(); i++) {
UsbEndpoint ep = intf.getEndpoint(i);
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
epOut = ep;
} else {
epIn = ep;
}
}
}
if (epOut == null || epIn == null) {
throw new IllegalArgumentException("not all endpoints found");
}
mEndpointOut = epOut;
mEndpointIn = epIn;
}
// return device serial number
public String getSerial() {
return mSerial;
}
// get an OUT request from our pool
public UsbRequest getOutRequest() {
synchronized(mOutRequestPool) {
if (mOutRequestPool.isEmpty()) {
UsbRequest request = new UsbRequest();
request.initialize(mDeviceConnection, mEndpointOut);
return request;
} else {
return mOutRequestPool.removeFirst();
}
}
}
// return an OUT request to the pool
public void releaseOutRequest(UsbRequest request) {
synchronized (mOutRequestPool) {
mOutRequestPool.add(request);
}
}
// get an IN request from the pool
public UsbRequest getInRequest() {
synchronized(mInRequestPool) {
if (mInRequestPool.isEmpty()) {
UsbRequest request = new UsbRequest();
request.initialize(mDeviceConnection, mEndpointIn);
return request;
} else {
return mInRequestPool.removeFirst();
}
}
}
public void start() {
mWaiterThread.start();
connect();
}
public AdbSocket openSocket(String destination) {
AdbSocket socket;
synchronized (mSockets) {
int id = mNextSocketId++;
socket = new AdbSocket(this, id);
mSockets.put(id, socket);
}
if (socket.open(destination)) {
return socket;
} else {
return null;
}
}
private AdbSocket getSocket(int id) {
synchronized (mSockets) {
return mSockets.get(id);
}
}
public void socketClosed(AdbSocket socket) {
synchronized (mSockets) {
mSockets.remove(socket.getId());
}
}
// send a connect command
private void connect() {
AdbMessage message = new AdbMessage();
message.set(AdbMessage.A_CNXN, AdbMessage.A_VERSION, AdbMessage.MAX_PAYLOAD, "host::\0");
message.write(this);
}
// handle connect response
private void handleConnect(AdbMessage message) {
if (message.getDataString().startsWith("device:")) {
log("connected");
mActivity.deviceOnline(this);
}
}
public void stop() {
synchronized (mWaiterThread) {
mWaiterThread.mStop = true;
}
}
// dispatch a message from the device
void dispatchMessage(AdbMessage message) {
int command = message.getCommand();
switch (command) {
case AdbMessage.A_SYNC:
log("got A_SYNC");
break;
case AdbMessage.A_CNXN:
handleConnect(message);
break;
case AdbMessage.A_OPEN:
case AdbMessage.A_OKAY:
case AdbMessage.A_CLSE:
case AdbMessage.A_WRTE:
AdbSocket socket = getSocket(message.getArg1());
if (socket == null) {
log("ERROR socket not found");
} else {
socket.handleMessage(message);
}
break;
}
}
void log(String s) {
mActivity.log(s);
}
private class WaiterThread extends Thread {
public boolean mStop;
public void run() {
// start out with a command read
AdbMessage currentCommand = new AdbMessage();
AdbMessage currentData = null;
// FIXME error checking
currentCommand.readCommand(getInRequest());
while (true) {
synchronized (this) {
if (mStop) {
return;
}
}
UsbRequest request = mDeviceConnection.requestWait();
if (request == null) {
break;
}
AdbMessage message = (AdbMessage)request.getClientData();
request.setClientData(null);
AdbMessage messageToDispatch = null;
if (message == currentCommand) {
int dataLength = message.getDataLength();
// read data if length > 0
if (dataLength > 0) {
message.readData(getInRequest(), dataLength);
currentData = message;
} else {
messageToDispatch = message;
}
currentCommand = null;
} else if (message == currentData) {
messageToDispatch = message;
currentData = null;
}
if (messageToDispatch != null) {
// queue another read first
currentCommand = new AdbMessage();
currentCommand.readCommand(getInRequest());
// then dispatch the current message
dispatchMessage(messageToDispatch);
}
// put request back into the appropriate pool
if (request.getEndpoint() == mEndpointOut) {
releaseOutRequest(request);
} else {
synchronized (mInRequestPool) {
mInRequestPool.add(request);
}
}
}
}
}
}
AdbMessage
package com.android.adb;
import android.hardware.usb.UsbRequest;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/* This class encapsulates and adb command packet */
public class AdbMessage {
// command names
public static final int A_SYNC = 0x434e5953;
public static final int A_CNXN = 0x4e584e43;
public static final int A_OPEN = 0x4e45504f;
public static final int A_OKAY = 0x59414b4f;
public static final int A_CLSE = 0x45534c43;
public static final int A_WRTE = 0x45545257;
// ADB protocol version
public static final int A_VERSION = 0x01000000;
public static final int MAX_PAYLOAD = 4096;
private final ByteBuffer mMessageBuffer;
private final ByteBuffer mDataBuffer;
public AdbMessage() {
mMessageBuffer = ByteBuffer.allocate(24);
mDataBuffer = ByteBuffer.allocate(MAX_PAYLOAD);
mMessageBuffer.order(ByteOrder.LITTLE_ENDIAN);
mDataBuffer.order(ByteOrder.LITTLE_ENDIAN);
}
// sets the fields in the command header
public void set(int command, int arg0, int arg1, byte[] data) {
mMessageBuffer.putInt(0, command);
mMessageBuffer.putInt(4, arg0);
mMessageBuffer.putInt(8, arg1);
mMessageBuffer.putInt(12, (data == null ? 0 : data.length));
mMessageBuffer.putInt(16, (data == null ? 0 : checksum(data)));
mMessageBuffer.putInt(20, command ^ 0xFFFFFFFF);
if (data != null) {
mDataBuffer.put(data, 0, data.length);
}
}
public void set(int command, int arg0, int arg1) {
set(command, arg0, arg1, (byte[])null);
}
public void set(int command, int arg0, int arg1, String data) {
// add trailing zero
data += "\0";
set(command, arg0, arg1, data.getBytes());
}
// returns the command's message ID
public int getCommand() {
return mMessageBuffer.getInt(0);
}
// returns command's first argument
public int getArg0() {
return mMessageBuffer.getInt(4);
}
// returns command's second argument
public int getArg1() {
return mMessageBuffer.getInt(8);
}
// returns command's data buffer
public ByteBuffer getData() {
return mDataBuffer;
}
// returns command's data length
public int getDataLength() {
return mMessageBuffer.getInt(12);
}
// returns command's data as a string
public String getDataString() {
int length = getDataLength();
if (length == 0) return null;
// trim trailing zero
return new String(mDataBuffer.array(), 0, length - 1);
}
public boolean write(AdbDevice device) {
synchronized (device) {
UsbRequest request = device.getOutRequest();
request.setClientData(this);
if (request.queue(mMessageBuffer, 24)) {
int length = getDataLength();
if (length > 0) {
request = device.getOutRequest();
request.setClientData(this);
if (request.queue(mDataBuffer, length)) {
return true;
} else {
device.releaseOutRequest(request);
return false;
}
}
return true;
} else {
device.releaseOutRequest(request);
return false;
}
}
}
public boolean readCommand(UsbRequest request) {
request.setClientData(this);
return request.queue(mMessageBuffer, 24);
}
public boolean readData(UsbRequest request, int length) {
request.setClientData(this);
return request.queue(mDataBuffer, length);
}
private static String extractString(ByteBuffer buffer, int offset, int length) {
byte[] bytes = new byte[length];
for (int i = 0; i < length; i++) {
bytes[i] = buffer.get(offset++);
}
return new String(bytes);
}
@Override
public String toString() {
String commandName = extractString(mMessageBuffer, 0, 4);
int dataLength = getDataLength();
String result = "Adb Message: " + commandName + " arg0: " + getArg0() +
" arg1: " + getArg1() + " dataLength: " + dataLength;
if (dataLength > 0) {
result += (" data: \"" + getDataString() + "\"");
}
return result;
}
private static int checksum(byte[] data) {
int result = 0;
for (int i = 0; i < data.length; i++) {
int x = data[i];
// dang, no unsigned ints in java
if (x < 0) x += 256;
result += x;
}
return result;
}
}
AdbSocket
package com.android.adb;
/* This class represents an adb socket. adb supports multiple independent
* socket connections to a single device. Typically a socket is created
* for each adb command that is executed.
*/
public class AdbSocket {
private final AdbDevice mDevice;
private final int mId;
private int mPeerId;
public AdbSocket(AdbDevice device, int id) {
mDevice = device;
mId = id;
}
public int getId() {
return mId;
}
public boolean open(String destination) {
AdbMessage message = new AdbMessage();
message.set(AdbMessage.A_OPEN, mId, 0, destination);
if (! message.write(mDevice)) {
return false;
}
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
return false;
}
}
return true;
}
public void handleMessage(AdbMessage message) {
switch (message.getCommand()) {
case AdbMessage.A_OKAY:
mPeerId = message.getArg0();
synchronized (this) {
notify();
}
break;
case AdbMessage.A_WRTE:
mDevice.log(message.getDataString());
sendReady();
break;
}
}
private void sendReady() {
AdbMessage message = new AdbMessage();
message.set(AdbMessage.A_OKAY, mId, mPeerId);
message.write(mDevice);
}
}
这篇关于使用Andriod的USB主机API来阅读我的USB游戏手柄/或其他USB设备的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!