gpt4 book ai didi

从设备读取的 Android USB 主机

转载 作者:IT王子 更新时间:2023-10-28 23:40:04 26 4
gpt4 key购买 nike

我正在尝试从连接到我处于主机模式的 Android 手机的 USB 设备中获取一些数据。我可以向它发送数据,但读取失败。

我看过 several examples并尽我所能,但我对 USB 通信没有任何经验,虽然现在我知道一点,而且我一直坚持这个我愿意承认的时间。

我对端点配置不是很熟悉,但我知道我的设备使用 CDC 类型的通信方法,并且输出(从手机到设备)和输入都已注册。

这是使用连接到手机的唯一设备管理 USB 连接的整个类(class),无论如何都没有完成,但我想在继续之前让阅读部分开始工作。

public class UsbCommunicationManager
{
static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

UsbManager usbManager;
UsbDevice usbDevice;
UsbInterface intf = null;
UsbEndpoint input, output;
UsbDeviceConnection connection;

PendingIntent permissionIntent;

Context context;

byte[] readBytes = new byte[64];

public UsbCommunicationManager(Context context)
{
this.context = context;
usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

// ask permission from user to use the usb device
permissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
context.registerReceiver(usbReceiver, filter);
}

public void connect()
{
// check if there's a connected usb device
if(usbManager.getDeviceList().isEmpty())
{
Log.d("trebla", "No connected devices");
return;
}

// get the first (only) connected device
usbDevice = usbManager.getDeviceList().values().iterator().next();

// user must approve of connection
usbManager.requestPermission(usbDevice, permissionIntent);
}

public void stop()
{
context.unregisterReceiver(usbReceiver);
}

public String send(String data)
{
if(usbDevice == null)
{
return "no usb device selected";
}

int sentBytes = 0;
if(!data.equals(""))
{
synchronized(this)
{
// send data to usb device
byte[] bytes = data.getBytes();
sentBytes = connection.bulkTransfer(output, bytes, bytes.length, 1000);
}
}

return Integer.toString(sentBytes);
}

public String read()
{
// reinitialize read value byte array
Arrays.fill(readBytes, (byte) 0);

// wait for some data from the mcu
int recvBytes = connection.bulkTransfer(input, readBytes, readBytes.length, 3000);

if(recvBytes > 0)
{
Log.d("trebla", "Got some data: " + new String(readBytes));
}
else
{
Log.d("trebla", "Did not get any data: " + recvBytes);
}

return Integer.toString(recvBytes);
}

public String listUsbDevices()
{
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();

if(deviceList.size() == 0)
{
return "no usb devices found";
}

Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
String returnValue = "";
UsbInterface usbInterface;

while(deviceIterator.hasNext())
{
UsbDevice device = deviceIterator.next();
returnValue += "Name: " + device.getDeviceName();
returnValue += "\nID: " + device.getDeviceId();
returnValue += "\nProtocol: " + device.getDeviceProtocol();
returnValue += "\nClass: " + device.getDeviceClass();
returnValue += "\nSubclass: " + device.getDeviceSubclass();
returnValue += "\nProduct ID: " + device.getProductId();
returnValue += "\nVendor ID: " + device.getVendorId();
returnValue += "\nInterface count: " + device.getInterfaceCount();

for(int i = 0; i < device.getInterfaceCount(); i++)
{
usbInterface = device.getInterface(i);
returnValue += "\n Interface " + i;
returnValue += "\n\tInterface ID: " + usbInterface.getId();
returnValue += "\n\tClass: " + usbInterface.getInterfaceClass();
returnValue += "\n\tProtocol: " + usbInterface.getInterfaceProtocol();
returnValue += "\n\tSubclass: " + usbInterface.getInterfaceSubclass();
returnValue += "\n\tEndpoint count: " + usbInterface.getEndpointCount();

for(int j = 0; j < usbInterface.getEndpointCount(); j++)
{
returnValue += "\n\t Endpoint " + j;
returnValue += "\n\t\tAddress: " + usbInterface.getEndpoint(j).getAddress();
returnValue += "\n\t\tAttributes: " + usbInterface.getEndpoint(j).getAttributes();
returnValue += "\n\t\tDirection: " + usbInterface.getEndpoint(j).getDirection();
returnValue += "\n\t\tNumber: " + usbInterface.getEndpoint(j).getEndpointNumber();
returnValue += "\n\t\tInterval: " + usbInterface.getEndpoint(j).getInterval();
returnValue += "\n\t\tType: " + usbInterface.getEndpoint(j).getType();
returnValue += "\n\t\tMax packet size: " + usbInterface.getEndpoint(j).getMaxPacketSize();
}
}
}

return returnValue;
}

private void setupConnection()
{
// find the right interface
for(int i = 0; i < usbDevice.getInterfaceCount(); i++)
{
// communications device class (CDC) type device
if(usbDevice.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA)
{
intf = usbDevice.getInterface(i);

// find the endpoints
for(int j = 0; j < intf.getEndpointCount(); j++)
{
if(intf.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_OUT && intf.getEndpoint(j).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)
{
// from android to device
output = intf.getEndpoint(j);
}

if(intf.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_IN && intf.getEndpoint(j).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)
{
// from device to android
input = intf.getEndpoint(j);
}
}
}
}
}

private final BroadcastReceiver usbReceiver = new BroadcastReceiver()
{
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(ACTION_USB_PERMISSION.equals(action))
{
// broadcast is like an interrupt and works asynchronously with the class, it must be synced just in case
synchronized(this)
{
if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))
{
setupConnection();

connection = usbManager.openDevice(usbDevice);
connection.claimInterface(intf, true);

// set flow control to 8N1 at 9600 baud
int baudRate = 9600;
byte stopBitsByte = 1;
byte parityBitesByte = 0;
byte dataBits = 8;
byte[] msg = {
(byte) (baudRate & 0xff),
(byte) ((baudRate >> 8) & 0xff),
(byte) ((baudRate >> 16) & 0xff),
(byte) ((baudRate >> 24) & 0xff),
stopBitsByte,
parityBitesByte,
(byte) dataBits
};

connection.controlTransfer(UsbConstants.USB_TYPE_CLASS | 0x01, 0x20, 0, 0, msg, msg.length, 5000);
}
else
{
Log.d("trebla", "Permission denied for USB device");
}
}
}
else if(UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action))
{
Log.d("trebla", "USB device detached");
}
}
};
}

我不断从 read() 方法中获取 -1,这表明某种错误,它总是超时。可能问题出在连接配置上,我尝试了几次(阅读:反复试验),但都没有成功,令人惊讶的是,我不需要任何配置即可将数据发送到设备。


编辑

还必须注意的是,我使用的电缆是 micro-USB 到 micro-USB,它只能以一种方式工作,即只有当插头 A 连接到手机并插入时,我的设备才由手机供电B 连接到设备,而不是相反...看起来很奇怪。以正确的方式插入时我能够发送数据但无法接收的事实仍然存在。


编辑 2

我发现 somebody else had the same problem但他似乎无法解决它。


编辑 3

我终于在 this page 上找到了解决方案:

Another major oversight is that there is no mechanism for the host to notify the device that there is a data sink on the host side ready to accept data. This means that the device may try to send data while the host isn't listening, causing lengthy blocking timeouts in the transmission routines. It is thus highly recommended that the virtual serial line DTR (Data Terminal Ready) signal be used where possible to determine if a host application is ready for data.

所以 DTR 信号是强制性的,我所要做的就是将它添加到接口(interface)配置中:

connection.controlTransfer(0x21, 0x22, 0x1, 0, null, 0, 0);

编辑 4

如果有人感兴趣,我完成了这个项目,它是 open source and published on my GitHub account .虽然它一直不稳定(参见 notes ),我不打算再研究它,但它确实有效。随意将其用于您自己的项目。

最佳答案

您可以使用来自 https://github.com/mik3y/usb-serial-for-android 的 UsbSerial Lib

我的示例代码:

    UsbManager usbManager = null;
UsbDeviceConnection connection = null;
UsbSerialDriver driver = null;
UsbSerialPort port = null;

usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
// Open a connection to the first available driver.

for (UsbSerialDriver usd : availableDrivers) {
UsbDevice udv = usd.getDevice();
if (udv.getVendorId()==0x067B || udv.getProductId()==2303){
driver = usd;
break;
}
}
connection = usbManager.openDevice(driver.getDevice());

port = driver.getPorts().get(0);

driver.getDevice().

}

if (connection == null) return;

try{

port.open(connection);
port.setParameters(4800, UsbSerialPort.DATABITS_8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);

try{

byte buffer[] = new byte[250];
//Log.d("GPS_REQ", "->");
int numBytesRead = port.read(buffer, 500); //5000;

}catch (Exception e) {
Log.d("GPS_ERR", e.getLocalizedMessage());
}

关于从设备读取的 Android USB 主机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19736301/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com