无法从主机模式下android的USB hid设备读取数据
我可以连接到设备并询问设备规格: 规格:无法从主机模式下android的USB hid设备读取数据,android,usb,hid,Android,Usb,Hid,我可以连接到设备并询问设备规格: 规格: Model: /dev/bus/usb/001/002 ID: 1002 Class: 0 Protocol: 0 Vendor ID 1155 Product ID: 22352 Interface count: 1 --------------------------------------- ***** ***** Interface index: 0 Interface ID: 0 Inteface class: 3 USB_CLASS_
Model: /dev/bus/usb/001/002
ID: 1002
Class: 0
Protocol: 0
Vendor ID 1155
Product ID: 22352
Interface count: 1
---------------------------------------
***** *****
Interface index: 0
Interface ID: 0
Inteface class: 3 USB_CLASS_HID
Interface protocol: 0
Endpoint count: 2
++++ ++++ ++++
Endpoint index: 0
Attributes: 3
Direction: 128 (device to host)
Number: 1
Interval: 1
Packet size: 64
Type: 3 USB_ENDPOINT_XFER_INT (interrupt endpoint)
++++ ++++ ++++
Endpoint index: 1
Attributes: 3
Direction: 0 (host to device)
Number: 1
Interval: 1
Packet size: 64
Type: 3 USB_ENDPOINT_XFER_INT (interrupt endpoint)
No more devices connected.
我还可以使用以下方法将数据从主机发送到设备:
int bufferDataLength = mEndpointOut.getMaxPacketSize();
ByteBuffer buffer = ByteBuffer.allocate(bufferDataLength + 1);
UsbRequest request = new UsbRequest();
buffer.put(DataToSend);
request.initialize(mDeviceConnection, mEndpointOut);
request.queue(buffer, bufferDataLength);
try
{
if (request.equals(mDeviceConnection.requestWait()))
{
// Read an analyze the incoming data here
byte[] byteBuffer = new byte[buffer.remaining()];
buffer.get(byteBuffer, 0, buffer.remaining());
return true;
}
}
catch (Exception ex)
{
Log.e(TAG, "Error sending data: " + ex.toString());
}
return false;
但我无法从设备上读取数据,我已经测试了几种方法,但都没有成功
例如,这不起作用:
int bufferDataLength = mEndpointIn.getMaxPacketSize();
ByteBuffer buffer = ByteBuffer.allocate(bufferDataLength + 1);
//Make a request
UsbRequest request = new UsbRequest();
request.initialize(mDeviceConnection, mEndpointIn);
ByteBuffer buffer = ByteBuffer.allocate(bufferDataLength);
//For IN endpoints, data is read into the buffer
request.queue(buffer, bufferDataLength);
//This blocks until the request is successful
//Make sure the request that finished is the one you need
if (mDeviceConnection.requestWait() == request) {
// Read an analyze the incoming data here
byte[] byteBuffer = new byte[buffer.remaining()];
buffer.get(byteBuffer, 0, buffer.remaining());
}
建议?我用这门课解决了我的问题,我在回答我的问题,希望它能帮助其他人:
/**
* This class is used for talking to hid of the dongle, connecting, disconnencting and enumerating the devices.
* @author gai
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
public class HidBridge {
private Context _context;
private int _productId;
private int _vendorId;
//private HidBridgeLogSupporter _logSupporter = new HidBridgeLogSupporter();
private static final String ACTION_USB_PERMISSION =
"com.example.company.app.testhid.USB_PERMISSION";
// Locker object that is responsible for locking read/write thread.
private final Object _locker = new Object();
private Thread _readingThread = null;
private boolean _runReadingThread = false;
private String _deviceName;
private UsbManager _usbManager;
private UsbDevice _usbDevice;
// The queue that contains the read data.
private Queue<byte[]> _receivedQueue;
/**
* Creates a hid bridge to the dongle. Should be created once.
* @param context is the UI context of Android.
* @param productId of the device.
* @param vendorId of the device.
*/
public HidBridge(Context context, int productId, int vendorId) {
_context = context;
_productId = productId;
_vendorId = vendorId;
_receivedQueue = new LinkedList<byte[]>();
}
/**
* Searches for the device and opens it if successful
* @return true, if connection was successful
*/
public boolean OpenDevice() {
_usbManager = (UsbManager) _context.getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = _usbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
_usbDevice = null;
// Iterate all the available devices and find ours.
while(deviceIterator.hasNext()){
UsbDevice device = deviceIterator.next();
if (device.getProductId() == _productId && device.getVendorId() == _vendorId) {
_usbDevice = device;
_deviceName = _usbDevice.getDeviceName();
}
}
if (_usbDevice == null) {
Log("Cannot find the device. Did you forgot to plug it?");
Log(String.format("\t I search for VendorId: %s and ProductId: %s", _vendorId, _productId));
return false;
}
// Create and intent and request a permission.
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(_context, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
_context.registerReceiver(mUsbReceiver, filter);
_usbManager.requestPermission(_usbDevice, mPermissionIntent);
Log("Found the device");
return true;
}
/**
* Closes the reading thread of the device.
*/
public void CloseTheDevice() {
try
{
StopReadingThread();
_context.unregisterReceiver(mUsbReceiver);
}
catch(RuntimeException e)
{
Log("Error happend while closing device. Usb reciver not connected.");
}
}
/**
* Starts the thread that continuously reads the data from the device.
* Should be called in order to be able to talk with the device.
*/
public void StartReadingThread() {
if (_readingThread == null) {
_runReadingThread = true;
_readingThread = new Thread(readerReceiver);
_readingThread.start();
} else {
Log("Reading thread already started");
}
}
/**
* Stops the thread that continuously reads the data from the device.
* If it is stopped - talking to the device would be impossible.
*/
public void StopReadingThread() {
if (_readingThread != null) {
// Just kill the thread. It is better to do that fast if we need that asap.
_runReadingThread = false;
_readingThread = null;
} else {
Log("No reading thread to stop");
}
}
/**
* Write data to the usb hid. Data is written as-is, so calling method is responsible for adding header data.
* @param bytes is the data to be written.
* @return true if succeed.
*/
public boolean WriteData(byte[] bytes) {
try
{
// Lock that is common for read/write methods.
synchronized (_locker) {
UsbInterface writeIntf = _usbDevice.getInterface(0);
UsbEndpoint writeEp = writeIntf.getEndpoint(1);
UsbDeviceConnection writeConnection = _usbManager.openDevice(_usbDevice);
// Lock the usb interface.
writeConnection.claimInterface(writeIntf, true);
// Write the data as a bulk transfer with defined data length.
int r = writeConnection.bulkTransfer(writeEp, bytes, bytes.length, 0);
if (r != -1) {
Log(String.format("Written %s bytes to the dongle. Data written: %s", r, composeString(bytes)));
} else {
Log("Error happened while writing data. No ACK");
}
// Release the usb interface.
writeConnection.releaseInterface(writeIntf);
writeConnection.close();
}
} catch(NullPointerException e)
{
Log("Error happend while writing. Could not connect to the device or interface is busy?");
Log.e("HidBridge", Log.getStackTraceString(e));
return false;
}
return true;
}
/**
* @return true if there are any data in the queue to be read.
*/
public boolean IsThereAnyReceivedData() {
synchronized(_locker) {
return !_receivedQueue.isEmpty();
}
}
/**
* Queue the data from the read queue.
* @return queued data.
*/
public byte[] GetReceivedDataFromQueue() {
synchronized(_locker) {
return _receivedQueue.poll();
}
}
// The thread that continuously receives data from the dongle and put it to the queue.
private Runnable readerReceiver = new Runnable() {
public void run() {
if (_usbDevice == null) {
Log("No device to read from");
return;
}
UsbEndpoint readEp;
UsbDeviceConnection readConnection = null;
UsbInterface readIntf = null;
boolean readerStartedMsgWasShown = false;
// We will continuously ask for the data from the device and store it in the queue.
while (_runReadingThread) {
// Lock that is common for read/write methods.
synchronized (_locker) {
try
{
if (_usbDevice == null) {
OpenDevice();
Log("No device. Recheking in 10 sec...");
Sleep(10000);
continue;
}
readIntf = _usbDevice.getInterface(0);
readEp = readIntf.getEndpoint(0);
if (!_usbManager.getDeviceList().containsKey(_deviceName)) {
Log("Failed to connect to the device. Retrying to acquire it.");
OpenDevice();
if (!_usbManager.getDeviceList().containsKey(_deviceName)) {
Log("No device. Recheking in 10 sec...");
Sleep(10000);
continue;
}
}
try
{
readConnection = _usbManager.openDevice(_usbDevice);
if (readConnection == null) {
Log("Cannot start reader because the user didn't gave me permissions or the device is not present. Retrying in 2 sec...");
Sleep(2000);
continue;
}
// Claim and lock the interface in the android system.
readConnection.claimInterface(readIntf, true);
}
catch (SecurityException e) {
Log("Cannot start reader because the user didn't gave me permissions. Retrying in 2 sec...");
Sleep(2000);
continue;
}
// Show the reader started message once.
if (!readerStartedMsgWasShown) {
Log("!!! Reader was started !!!");
readerStartedMsgWasShown = true;
}
// Read the data as a bulk transfer with the size = MaxPacketSize
int packetSize = readEp.getMaxPacketSize();
byte[] bytes = new byte[packetSize];
int r = readConnection.bulkTransfer(readEp, bytes, packetSize, 50);
if (r >= 0) {
byte[] trancatedBytes = new byte[r - 1]; // Truncate bytes in the honor of r
int i=0;
for (byte b : bytes) {
if (i > 0)
trancatedBytes[i - 1] = b;
i++;
}
_receivedQueue.add(trancatedBytes); // Store received data
Log(String.format("Message received of lengths %s and content: %s", r, composeString(bytes)));
}
// Release the interface lock.
readConnection.releaseInterface(readIntf);
readConnection.close();
}
catch (NullPointerException e) {
Log("Error happened while reading. No device or the connection is busy");
Log.e("HidBridge", Log.getStackTraceString(e));
}
catch (ThreadDeath e) {
if (readConnection != null) {
readConnection.releaseInterface(readIntf);
readConnection.close();
}
throw e;
}
}
// Sleep for 10 ms to pause, so other thread can write data or anything.
// As both read and write data methods lock each other - they cannot be run in parallel.
// Looks like Android is not so smart in planning the threads, so we need to give it a small time
// to switch the thread context.
Sleep(10);
}
}
};
private void Sleep(int milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
//call method to set up device communication
}
}
else {
Log.d("TAG", "permission denied for the device " + device);
}
}
}
}
};
/**
* Logs the message from HidBridge.
* @param message to log.
*/
private void Log(String message) {
//LogHandler logHandler = LogHandler.getInstance();
//logHandler.WriteMessage("HidBridge: " + message, LogHandler.GetNormalColor());
Log.i("HidBridge: ", message);
}
/**
* Composes a string from byte array.
*/
private String composeString(byte[] bytes) {
StringBuilder builder = new StringBuilder();
for (byte b: bytes) {
builder.append(b);
builder.append(" ");
}
return builder.toString();
}
}
/**
*这个类用于和加密狗的hid对话、连接、断开和枚举设备。
*@作者盖
*/
@TargetApi(构建版本代码蜂窝MR1)
公共级HidBridge{
私人语境(private Context)(私人语境);;
私有int_productId;
私人国际供应商;
//私有HidBridgeLogSupporter _logSupporter=新HidBridgeLogSupporter();
私有静态最终字符串操作\u USB\u权限=
“com.example.company.app.testhid.USB_权限”;
//负责锁定读/写线程的Locker对象。
私有最终对象_locker=新对象();
私有线程_readingThread=null;
私有布尔值_runReadingThread=false;
私有字符串_deviceName;
私人UsbManager(U UsbManager);
私人使用设备;
//包含读取数据的队列。
专用队列_receivedQueue;
/**
*创建到加密狗的hid桥接。应创建一次。
*@param context是Android的UI上下文。
*设备的@param productId。
*@param vendorId的设备。
*/
公共HidBridge(上下文上下文、int-productId、int-vendorId){
_上下文=上下文;
_productId=productId;
_vendorId=vendorId;
_receivedQueue=newlinkedlist();
}
/**
*搜索设备并在成功时打开它
*@return true,如果连接成功
*/
公共布尔OpenDevice(){
_usbManager=(usbManager)_context.getSystemService(context.USB_SERVICE);
HashMap deviceList=_usbManager.getDeviceList();
迭代器deviceIterator=deviceList.values().Iterator();
_usbDevice=null;
//迭代所有可用的设备并找到我们的。
while(deviceIterator.hasNext()){
UsbDevice device=deviceIterator.next();
if(device.getProductId()==\u productId&&device.getVendorId()=\u vendorId){
_usbDevice=设备;
_deviceName=_usbDevice.getDeviceName();
}
}
如果(_usbDevice==null){
日志(“找不到设备。您忘记插上插头了吗?”);
日志(String.format(“\t我搜索供应商ID:%s和产品ID:%s”,\u供应商ID,\u产品ID));
返回false;
}
//创建、意图和请求权限。
pendingent mPermissionIntent=pendingent.getBroadcast(_context,0,新意图(ACTION_USB_PERMISSION),0);
IntentFilter筛选器=新建IntentFilter(操作\u USB\u权限);
_registerReceiver(mUsbReceiver,filter);
_usbManager.requestPermission(_usbDevice,mPermissionIntent);
日志(“找到设备”);
返回true;
}
/**
*关闭设备的读取线程。
*/
公共无效关闭设备(){
尝试
{
停止读取线程();
_未注册接收人(mUsbReceiver);
}
捕获(运行时异常e)
{
日志(“关闭设备时发生错误。Usb接收器未连接。”);
}
}
/**
*启动从设备连续读取数据的线程。
*应调用,以便能够与设备对话。
*/
public void startedingthread(){
if(_readingThread==null){
_runReadingThread=true;
_readingThread=新线程(readerReceiver);
_readingThread.start();
}否则{
日志(“读取线程已启动”);
}
}
/**
*停止从设备连续读取数据的线程。
*如果它被停止-与设备对话将是不可能的。
*/
public void StopReadingThread(){
if(_readingThread!=null){
//只要停止线程。如果我们需要尽快这样做,最好尽快这样做。
_runReadingThread=false;
_readingThread=null;
}否则{
日志(“没有要停止的读取线程”);
}
}
/**
*将数据写入usb hid。数据按原样写入,所以调用方法负责添加头数据。
*@param bytes是要写入的数据。
*@成功返回true。
*/
公共布尔写数据(字节[]字节){
尝试
{
//读/写方法常用的锁。
已同步(_locker){
UsbInterface writeIntf=\u usbDevice.getInterface(0);
UsbEndpoint writeEp=writeIntf.getEndpoint(1);
UsbDeviceConnection writeConnection=\u usbManager.openDevice(\u usbDevice);
//锁定usb接口。
writeConnection.claimInterface(writeIntf,true);
//以具有定义数据长度的批量传输方式写入数据。
int r=writeConnection.bulkTransfer(writeEp,bytes,bytes.length,0);
如果(r!=-1){
日志(String.format(“写入%s字节到加密狗。写入数据:%s”,r,composeString(字节));
}否则{
日志(“写入数据时出错,无确认”);
}
//释放usb接口。
writeConnection.releaseInterface(writeIntf);
writeConnection.close();
}
}捕获(NullPointerException e)
{
日志(“写入时出错。无法连接到设备或接口正忙?”);
Log.e(“HidBridge