我创建了一个java应用程序,它将自己设置为USB附件,并通过批量传输发送一些数据。
Android设备应该看到这个并将数据打印到TextView。目前我拥有它以便Android设备看到附件的连接并且它启动应用程序批量转移但是失败并且具有以下内容。
org.usb4java.LibUsbException: USB error 5: Bulk write error!: Entity not found
at com.xxx.xxx.AccessoryTest.writeAndRead(AccessoryTest.java:60)
at com.xxx.xxx.AccessoryTest.main(AccessoryTest.java:37)
欢迎任何建议!
我有另一个实用程序,它将Android设备的端点信息报告为
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 512
bInterval 0
extralen 0
extra:
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 512
bInterval 0
extralen 0
extra:
我正在尝试写入0x02端点
Android代码
public class MainActivity extends AppCompatActivity implements Runnable {
private UsbManager manager;
private UsbAccessory accessory;
private ParcelFileDescriptor accessoryFileDescriptor;
private FileInputStream accessoryInput;
private FileOutputStream accessoryOutput;
private TextView questionTV;
private final BroadcastReceiver usbBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(action)) {
synchronized (this) {
accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
}
} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null) {
// call your method that cleans up and closes communication with the accessory
try {
accessoryFileDescriptor.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(usbBroadcastReceiver, filter);
if (getLastNonConfigurationInstance() != null)
{
accessory = (UsbAccessory) getLastNonConfigurationInstance();
openAccessory();
}
setContentView(R.layout.activity_main);
}
private void openAccessory() {
accessoryFileDescriptor = manager.openAccessory(accessory);
if(accessoryFileDescriptor != null) {
FileDescriptor fd = accessoryFileDescriptor.getFileDescriptor();
accessoryInput = new FileInputStream(fd);
accessoryOutput = new FileOutputStream(fd);
Thread thread = new Thread(null, this, "AccessoryThread");
thread.start();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void run() {
int ret = 0;
byte[] buffer = new byte[51];
int bufferUsed = 0;
while(ret >= 0) {
try {
ret = accessoryInput.read(buffer);
} catch (IOException e) {
Log.e("MainActivity", "Exception in USB accessory input reading", e);
break;
}
}
String question = new String(buffer);
LinearLayout layout= (LinearLayout) findViewById(R.id.layout);
questionTV = new TextView(this);
questionTV.setText(question);
layout.addView(questionTV);
}
}
Java应用程序代码
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import org.usb4java.BufferUtils;
import org.usb4java.Context;
import org.usb4java.Device;
import org.usb4java.DeviceDescriptor;
import org.usb4java.DeviceHandle;
import org.usb4java.DeviceList;
import org.usb4java.LibUsb;
import org.usb4java.LibUsbException;
public class AccessoryTest {
private final static byte REQUEST_TYPE_READ = (byte) 0xC0;
private final static byte END_POINT_IN = (byte) 0x81;
private final static byte END_POINT_OUT = (byte) 0x02;
private final static short NEXUS7_VENDORID = (short) 0x18D1;
private final static short NEXUS7_PRODUCTID = (short) 0x4EE1;
private static Context context;
private static Device device;
private static DeviceHandle handle;
public static void main(String[] args) {
try {
init();
int result = setupAccessory("PCHost", "PCHost1", "Description", "1.0", "http://www.mycompany.com",
"SerialNumber");
if (result != LibUsb.SUCCESS)
throw new LibUsbException("Unable to setup Accessory", result);
writeAndRead();
} catch (Exception e) {
e.printStackTrace();
} finally {
LibUsb.releaseInterface(handle, 0);
LibUsb.resetDevice(handle);
LibUsb.close(handle);
LibUsb.exit(context);
}
}
private static void writeAndRead() {
String question = "Hello Android I'll be your host today, how are you?";
byte[] questionBuffer = question.getBytes();
ByteBuffer questionData = BufferUtils.allocateByteBuffer(questionBuffer.length);
IntBuffer transferred = IntBuffer.allocate(1);
int result = 0;
//THIS IS THE PART WHERE IT FAILS!
result = LibUsb.bulkTransfer(handle, END_POINT_OUT, questionData, transferred, 5000);
if(result < 0) {
throw new LibUsbException("Bulk write error!", result);
}
}
private static void init() {
context = new Context();
int result = LibUsb.init(context);
if (result != LibUsb.SUCCESS)
throw new LibUsbException("Unable to initialize libusb.", result);
device = findDevice(NEXUS7_VENDORID);
handle = new DeviceHandle();
result = LibUsb.open(device, handle);
if (result < 0)
throw new LibUsbException("Unable to open USB device", result);
result = LibUsb.claimInterface(handle, 0);
if (result != LibUsb.SUCCESS)
throw new LibUsbException("Unable to claim interface", result);
}
private static Device findDevice(short vendorId) {
// Read the USB device list
DeviceList list = new DeviceList();
int result = LibUsb.getDeviceList(null, list);
if (result < 0)
throw new LibUsbException("Unable to get device list", result);
try {
// Iterate over all devices and scan for the right one
for (Device device : list) {
DeviceDescriptor descriptor = new DeviceDescriptor();
result = LibUsb.getDeviceDescriptor(device, descriptor);
if (result != LibUsb.SUCCESS)
throw new LibUsbException("Unable to read device descriptor", result);
if (descriptor.idVendor() == vendorId)
return device;
}
} finally {
// Ensure the allocated device list is freed
LibUsb.freeDeviceList(list, true);
}
// Device not found
return null;
}
private static int setupAccessory(String vendor, String model, String description, String version, String url,
String serial) throws LibUsbException {
int response = 0;
// Setup setup token
response = transferSetupPacket((short) 2, REQUEST_TYPE_READ, (byte) 51);
// Setup data packet
response = transferAccessoryDataPacket(vendor, (short) 0);
response = transferAccessoryDataPacket(model, (short) 1);
response = transferAccessoryDataPacket(description, (short) 2);
response = transferAccessoryDataPacket(version, (short) 3);
response = transferAccessoryDataPacket(url, (short) 4);
response = transferAccessoryDataPacket(serial, (short) 5);
// Setup handshake packet
response = transferSetupPacket((short) 0, (byte) (LibUsb.REQUEST_TYPE_VENDOR | LibUsb.ENDPOINT_OUT), (byte) 53);
LibUsb.releaseInterface(handle, 0);
return response;
}
private static int transferSetupPacket(short bufferLength, byte requestType, byte request) throws LibUsbException {
int response = 0;
byte[] bytebuff = new byte[bufferLength];
ByteBuffer data = BufferUtils.allocateByteBuffer(bytebuff.length);
data.put(bytebuff);
final short wValue = 0;
final short wIndex = 0;
final long timeout = 1000;
data.rewind();
response = LibUsb.controlTransfer(handle, requestType, request, wValue, wIndex,
data, timeout);
if(response < 0)
throw new LibUsbException("Unable to transfer setup packet ", response);
return response;
}
private static int transferAccessoryDataPacket(String param, short index) {
int response;
byte[] byteArray = param.getBytes();
ByteBuffer data = BufferUtils.allocateByteBuffer(byteArray.length);
data.put(byteArray);
final byte bRequest = (byte) 52;
final short wValue = 0;
final long timeout = 0;
response = LibUsb.controlTransfer(handle, LibUsb.REQUEST_TYPE_VENDOR, bRequest, wValue, index,
data, timeout);
if(response < 0)
throw new LibUsbException("Unable to control transfer.", response);
return response;
}
}
的AndroidManifest.xml
<uses-feature android:name="android.hardware.usb.accessory" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<uses-library android:name="com.android.future.usb.accessory" />
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter" />
</activity>
</application>
答案 0 :(得分:2)
问题是根据AOP标准,一旦Android设备进入附件模式,它的VID和PID更改
因此,在安装附件后,需要回收设备手柄和接口。