I'm mencoba untuk mendapatkan beberapa data dari perangkat USB yang tersambung ke ponsel Android saya yang di host mode. I'm dapat mengirim data untuk itu, tapi membaca gagal.
I've melihat beberapa contoh dan mencoba semua yang saya bisa tapi aku don't memiliki pengalaman dalam komunikasi USB, meskipun sekarang saya tahu sedikit, dan I've telah terjebak pada hal lagi yang saya peduli untuk mengakui.
I'm tidak sangat akrab dengan akhir konfigurasi, tapi aku tahu adalah bahwa perangkat saya menggunakan CDC jenis metode komunikasi dan kedua output (dari telepon ke perangkat) dan input terdaftar.
Berikut ini's seluruh kelas yang mengelola koneksi USB dengan satu-satunya perangkat yang terhubung ke ponsel, it's tidak selesai dengan cara apapun, tapi aku'd ingin mendapatkan yang membaca bagian untuk bekerja sebelum saya pergi lebih jauh.
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");
}
}
};
}
Saya terus mendapatkan -1
dari read()
metode yang menunjukkan beberapa jenis kesalahan, itu selalu kali keluar. Mungkin masalah datang dari konfigurasi koneksi, I've mencoba beberapa (baca: trial and error) dan tidak bekerja, anehnya aku don't perlu konfigurasi apapun untuk mengirim data ke perangkat.
Edit
Hal ini juga harus dicatat bahwa kabel I'm menggunakan micro-USB ke micro-USB dan hanya bekerja dalam satu arah, yang saya perangkat ini didukung oleh telepon saya hanya ketika steker Yang terhubung ke ponsel dan plug B yang terhubung ke perangkat, bukan sebaliknya... tampaknya sangat aneh. Fakta bahwa saya'm dapat mengirim data dan menerima ketika terpasang ke kanan way tetap.
EDIT 2
Saya menemukan bahwa orang lain memiliki masalah yang sama tetapi tampaknya dia tidak't mampu menyelesaikannya.
EDIT 3
Akhirnya saya menemukan solusi di halaman ini:
Lain pengawasan utama adalah bahwa tidak ada mekanisme bagi tuan rumah untuk memberitahu perangkat yang ada adalah data tenggelam pada sisi host siap untuk menerima data. Ini berarti bahwa perangkat dapat mencoba untuk mengirim data sementara tuan rumah isn't mendengarkan, menyebabkan panjang memblokir timeout dalam transmisi rutinitas. Dengan demikian sangat dianjurkan bahwa virtual serial line DTR (Data Terminal Ready) sinyal dapat digunakan di mana mungkin untuk menentukan apakah host aplikasi siap untuk di data.
Sehingga sinyal DTR adalah wajib dan semua saya harus lakukan adalah untuk menambahkan ini ke antarmuka konfigurasi:
connection.controlTransfer(0x21, 0x22, 0x1, 0, null, 0, 0);
EDIT 4
Jika ada yang tertarik saya menyelesaikan proyek ini dan itu's open source dan diterbitkan di akun GitHub. It's tidak stabil sepanjang waktu sekalipun (lihat catatan) dan saya don't rencana kerja yang di atasnya lagi, tapi itu bekerja. Merasa bebas untuk menggunakannya untuk proyek-proyek anda sendiri.
Anda dapat menggunakan UsbSerial Lib dari https://github.com/mik3y/usb-serial-for-android
Contoh kode:
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());
}