这是我第一次使用USB通信和Android应用程序。
我正在使用https://github.com/felHR85/UsbSerial创建一个应用程序,允许平板电脑/手机使用USB OTG充当主机并与附件通信。我已经到了使用SerialInputStreams和SerialOutputStreams来发送和接收设备的地步。
这是关于USB可以使用我正在使用的电缆发送的最大数据包大小为64字节。在我的应用程序中,附件发送的数据大于64字节。如果附件没有以64字节包发送数据的代码,而是一次性全部发送数据。将丢失64字节后的任何数据吗?
我正在接收从附件到主机的消息的前64个字节,然后主机超时,因为它没有收到完整的消息并重新发送到附件。消息的前64个字节总是显示出来,这样我知道消息的其他部分不等待轮询。
修改
我要连接的设备是作为CDC设备的数据记录器。我知道我使用的连接的最大包大小为64。
每当连接USB设备并通过我设置的过滤器并且接口和端点正确时,就会发生USBConnectActivity。
public class USBConnectActivity extends Activity
{
public UsbDevice device = null;
public UsbManager manager = null;
public UsbDeviceConnection usbDeviceConnection = null;
public UsbSerialDevice serialPort = null;
public String deviceID = "";
public boolean isUSBConnected = false;
private PendingIntent mPermissionIntent;
private final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION";
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
stopUsbConnection();
unregisterReceiver(usbReceiver);
}
if(ACTION_USB_PERMISSION.equals(action))
{
setupCom();
}
}
};
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
USBConnection.getInstance().setManager(manager);
mPermissionIntent = PendingIntent.getBroadcast(
this,0,new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter mfilter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(usbReceiver,mfilter);
IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(usbReceiver, filter);
findDevice(mPermissionIntent);
finish();
}
private void findDevice(PendingIntent i)
{
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
boolean found = false;
UsbDevice xDevice = null;
while (deviceIterator.hasNext()) {
UsbDevice tDevice = deviceIterator.next();
// Loop through the interfaces of the attached USB device
for (int count = 0; count < tDevice.getInterfaceCount(); count++) {
if (found) break;
// Use temp variables to check and then match with the private variables
UsbInterface inter = tDevice.getInterface(count);
UsbEndpoint tOut = null;
UsbEndpoint tIn = null;
if (inter.getEndpointCount() >= 2) {
for (int end_count = 0; end_count < inter.getEndpointCount(); end_count++) {
UsbEndpoint end = inter.getEndpoint(end_count);
if (end.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (end.getDirection() == UsbConstants.USB_DIR_OUT) tOut = end;
else if (end.getDirection() == UsbConstants.USB_DIR_IN) tIn = end;
}
}
}
if (tOut != null && tIn != null) {
device = tDevice; manager.requestPermission(device, i); found = true;
isUSBConnected = true;
USBConnection.getInstance().setDevice(device);
USBConnection.getInstance().attach();
}
}
}
if(usbDeviceConnection == null) setupCom();
}
@Override
protected void onStop()
{
super.onStop();
unregisterReceiver(usbReceiver);
}
private void setupCom()
{
deviceID = device.getDeviceName();
if(usbDeviceConnection == null) usbDeviceConnection = manager.openDevice(device);
if(serialPort == null)
{
serialPort = UsbSerialDevice.createUsbSerialDevice(device, usbDeviceConnection);
if(serialPort != null && serialPort.open())
{
serialPort.setBaudRate(115200);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
USBConnection.getInstance().setSerialPort(serialPort);
USBConnection.getInstance().setUsbDeviceConnection(usbDeviceConnection);
}
}
}
private void stopUsbConnection(){
manager = null;
device = null;
isUSBConnected = false;
USBConnection.getInstance().detach();
deviceID = "";
try
{
if(serialPort != null)
serialPort.close();
if(usbDeviceConnection != null)
usbDeviceConnection.close();
}
finally
{
serialPort = null;
usbDeviceConnection = null;
}
}
}
此类包含所有USB信息
public class USBConnection
{
// USB information
public boolean isConnected;
public UsbDevice device;
public UsbManager manager;
public UsbSerialDevice serialPort;
public UsbDeviceConnection usbDeviceConnection;
public String deviceName;
public boolean waitForReading;
private static USBConnection instance;
public static USBConnection getInstance()
{
if(instance == null)
instance = new USBConnection();
return instance;
}
public void setDevice(UsbDevice device_)
{
device = device_;
deviceName = device.getDeviceName();
}
public void setManager(UsbManager manager_)
{
manager = manager_;
}
public void attach()
{
isConnected = true;
}
public void detach()
{
isConnected = false;
}
public void setSerialPort(UsbSerialDevice serialPort_)
{
serialPort = serialPort_;
}
public void setUsbDeviceConnection(UsbDeviceConnection usbDeviceConnection_)
{
usbDeviceConnection = usbDeviceConnection_;
}
public void writing() {
waitForReading = true;
}
public void reading(){
waitForReading = false;
}
public boolean waitingForRead()
{
return waitForReading;
}
}
这是我用来设置输入和输出流的代码
else if(USBConnection.getInstance().isConnected) // check if usb is connected
{
manager = USBConnection.getInstance().manager;
device = USBConnection.getInstance().device;
// Attempt at setting up a USB input and output stream
if (manager != null) {
if(usbDeviceConnection == null) usbDeviceConnection = manager.openDevice(device);
if(serialPort == null)
{
serialPort = UsbSerialDevice.createUsbSerialDevice(device, usbDeviceConnection);
if(serialPort != null && serialPort.open())
{
serialPort.setBaudRate(115200);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
input = new SerialInputStream(serialPort);
output = new SerialOutputStream(serialPort);
Log.d("Direct", "Connected to the USB socket");
}
}
}
} // else there is no usb connected
这是在felHR85 UsbSerialDevice中,在他的ReadThread中,被注释掉的内容是我认为如果数据大于64字节会抓取数据
int numberBytes, bytes;
if(inEndpoint != null) {
bytes = numberBytes = connection.bulkTransfer(inEndpoint, serialBuffer.getBufferCompatible(),
SerialBuffer.DEFAULT_READ_BUFFER_SIZE, 100);
}/*while(numberBytes >= 64) {
numberBytes = connection.bulkTransfer(inEndpoint, serialBuffer.getBufferCompatible(), bytes,
124, 100);
bytes += numberBytes;
Log.i("Bytes", " : " + bytes);
}*/
else
bytes = numberBytes = 0;
这是他的WriteThread
while(working.get())
{
byte[] data = serialBuffer.getWriteBuffer();
if(data.length > 0)
connection.bulkTransfer(outEndpoint, data, data.length, USB_TIMEOUT);
}
修改
这解决了我的问题,但我仍然不确定我的原始问题的答案是什么
if(serialPort == null)
{
usbDeviceConnection.claimInterface(USBConnection.getInstance().usbInterface, true);
usbDeviceConnection.controlTransfer(64,0,1,0,null,0,0); // clear tx
usbDeviceConnection.controlTransfer(64,0,2,0,null,0,0); // clear rx
serialPort = UsbSerialDevice.createUsbSerialDevice(device, usbDeviceConnection);
答案 0 :(得分:0)
请提出你的代码。请指定您作为附件使用的任何设备(Arduino,FPGA等),以便更容易找到解决方案。很难说出现了什么问题。我建议你做以下事情 -
1)检查附件的设备描述符,其中明确提到USB端点一次可以传输的最大字节数。在这里,我将它用于我的Arduino Uno
2)我请求您通过this而不是使用库。
3)有一个DTR信号必须从主机发送到附件,以指示数据传输完成;这样就可以发送下一个数据。Check this
4)您应该使用ring buffer作为接收流,这样数据就不会丢失。