I try to send command to my USB custom device. I think I set all properly - for example I can get ID of device, so Android "sees" it. However , when I try to send it command I get null pointer at line :
connection.bulkTransfer(usbEndpointOut,send,send.length,SEND_TIMEOUT);
Endpoints are set correctly (I've checked it on log). This is my class. Please, help.
mTestButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
UsbDevice device;
if (usbDevices != null) {
boolean keep = true;
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
int deviceVID = device.getVendorId();
int devicePID = device.getProductId();
if (deviceVID != 0x1d6b || (devicePID != 0x0001 || devicePID != 0x0002 || devicePID != 0x0003)) {
Toast.makeText(MainActivity.this, "ID: " + device.getDeviceId()
, Toast.LENGTH_SHORT).show();
Log.e(TAG, "onCreate: " + device.getDeviceId());
UsbInterface usbInterface = null;
UsbEndpoint usbEndpointIn = null;
UsbEndpoint usbEndpointOut = null;
for (int i = 0; i < device.getInterfaceCount(); i++) {
usbInterface = device.getInterface(i);
//l("Interface[" + i + "] -> " + usbInterface);
if (usbInterface != null) {
for (int j = 0; j < usbInterface.getEndpointCount(); j++) {
UsbEndpoint usbEndpoint = usbInterface.getEndpoint(j);
//l("Endpoint[" + j + "] -> " + usbEndpoint);
if (usbEndpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_IN) {
//l("Found input!");
usbEndpointIn = usbEndpoint;
} else {
//l("Found output!");
usbEndpointOut = usbEndpoint;
}
if (usbEndpointIn != null && usbEndpointOut != null) {
break;
}
}
}
if (usbEndpointIn != null && usbEndpointOut != null) {
break;
}
} else {
//l("Interface was null");
}
}
connection = usbManager.openDevice(device);
connection.bulkTransfer(usbEndpointOut, send, send.length, SEND_TIMEOUT);
keep = false;
} else {
{
connection = null;
device = null;
}
if (!keep)
break;
}
}
}
}
});
}
private static final byte[] send = new byte[]{
(byte) 0xDA, (byte) 0xAD, // const
(byte) 0x02, (byte) 0x74, (byte) 0x00, // com
(byte) 0xBF, (byte) 0xDB // last
};
First of all, the loop which searches usbEndpointIn and usbEndpointOut might fail and then yields null. So, you should call bulkTransfer only if you have valid endpoints.
But the main thing is that you missed to claim the interface that you want to communicate with via bulkTransfer:
if (usbEndpointOut != null) {
connection = usbManager.openDevice(device);
if (connection != null) {
if (connection.claimInterface(usbInterface, true) == true) {
connection.bulkTransfer(usbEndpointOut, send, send.length, SEND_TIMEOUT);
keep = false;
}
}
}
Related
I have a program in which I attempt to attach my android device to a webcam via USB. I'm having trouble with a few things, namely properly transferring data. I've tried using bulkTransfer and there seems to be no recognition of it being used. I've been trying to find examples that may assist me such as here but none are helping me - their structure seems to be better than mine but whenever I switch my program crashes on load.
I'm fairly confident my bytes declaration is also incorrect and I should be somehow forwarding my data there, but I'm unsure how. Any help in terms of how to data transfer and how to structure my code would be appreciated.
Some declarations:
private byte[] bytes = {1,2};
private static int TIMEOUT = 0;
private boolean forceClaim = true;
In On Create:
UsbDevice device = (UsbDevice) getIntent().getParcelableExtra(UsbManager.EXTRA_DEVICE);
UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()) {
device = deviceIterator.next();
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this,0,new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
mUsbManager.requestPermission(device, mPermissionIntent);
UsbDeviceConnection connection = mUsbManager.openDevice(device);
Log.d("CAM Connection", " " + connection);
Log.d("CAM UsbManager", " " + mUsbManager);
Log.d("CAM Device", " " + device);
UsbInterface intf = device.getInterface(0);
Log.d("CAM_INTF Interface!!!!", " " + intf );
UsbEndpoint endpoint = intf.getEndpoint(0);
Log.d("CAM_END Endpoint", " " + endpoint );
connection.claimInterface(intf, forceClaim);
StringBuilder sb = new StringBuilder();
if(connection.bulkTransfer(endpoint,bytes,bytes.length,TIMEOUT) < 2)
Log.d("test", "");
//Log.d("BULK", ""+ connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT)); //do in another thread
}
Additional relevant code:
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(EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
//call method to set up device communication
}
}
else {
Log.d("Deny:", "permission denied for device " + device);
}
}
}
}
};
one of your problem is on finding endpoints. endpoint0 is for controlling task and you should find the appropriate IN and OUT endpoints in your code.
UsbInterface usbInterfaceTemp = null;
usbInterface = null;
endpointIN = null;
endpointOUT = null;
for (int i = 0; i < usbGotPermiDVC.getInterfaceCount(); i++) {
usbInterfaceTemp = usbGotPermiDVC.getInterface(i);
if (usbInterfaceTemp.getEndpointCount() >= 2) {
for (int j = 0; j < usbInterfaceTemp.getEndpointCount(); j++) {
UsbEndpoint usbEndpointTemp = usbInterfaceTemp.getEndpoint(j);
if (usbEndpointTemp.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (usbEndpointTemp.getDirection() == UsbConstants.USB_DIR_IN) {
endpointIN = usbEndpointTemp;
} else if (usbEndpointTemp.getDirection() == UsbConstants.USB_DIR_OUT) {
endpointOUT = usbEndpointTemp;
}
}
}
}
}
if (endpointIN != null && endpointOUT != null) {
usbInterface = usbInterfaceTemp;
}
if (usbInterface == null) {
return;
}
usbDeviceConnection = usbManager.openDevice(usbSelectedDevice);
if (!(usbDeviceConnection != null && usbDeviceConnection.claimInterface(usbInterface, true))) {
usbDeviceConnection = null;
return;
}
usbDeviceConnection.controlTransfer(0x21, 34, 0, 0, null, 0, 0);
usbDeviceConnection.controlTransfer(0x21, 32, 0, 0, new byte[]{(byte) 0x80,
0x25, 0x00, 0x00, 0x00, 0x00, 0x08}, 7, 0);
Toast.makeText(getApplicationContext(), "Device opened and Interface claimed!", Toast.LENGTH_SHORT).show();
in which usbGotPermiDVC is the device that got the permission to access via USB.
I am developing an application to interface an arduino duemilanove board with an android 4.1.1 smartphone over an USB interface using android’s USB host APIs. I have used the USB View application for windows to find the USB descriptors of the arduino duemelanove board. And by using these descriptors I could find the endpoints and interface on android platform. The descriptors are as follows:
Device Descriptor:
bcdUSB: 0x0200
bDeviceClass: 0x00
bDeviceSubClass: 0x00
bDeviceProtocol: 0x00
bMaxPacketSize0: 0x08 (8)
idVendor: 0x0403 (Future Technology Devices International Limited)
idProduct: 0x6001
bcdDevice: 0x0600
iManufacturer: 0x01
0x0409: "FTDI"
iProduct: 0x02
0x0409: "FT232R USB UART"
0x0409: "FT232R USB UART"
iSerialNumber: 0x03
0x0409: "A9GJFH5T"
bNumConfigurations: 0x01
Configuration Descriptor:
wTotalLength: 0x0020
bNumInterfaces: 0x01
bConfigurationValue: 0x01
iConfiguration: 0x00
bmAttributes: 0xA0 (Bus Powered Remote Wakeup)
MaxPower: 0x2D (90 Ma)
Interface Descriptor:
bInterfaceNumber: 0x00
bAlternateSetting: 0x00
bNumEndpoints: 0x02
bInterfaceClass: 0xFF
bInterfaceSubClass: 0xFF
bInterfaceProtocol: 0xFF
iInterface: 0x02
0x0409: "FT232R USB UART"
0x0409: "FT232R USB UART"
Endpoint Descriptor:
bEndpointAddress: 0x81
Transfer Type: Bulk
wMaxPacketSize: 0x0040 (64)
bInterval: 0x00
Endpoint Descriptor:
bEndpointAddress: 0x02
Transfer Type: Bulk
wMaxPacketSize: 0x0040 (64)
bInterval: 0x00
The application detects the device and displays all the descriptors in the text views assigned. But the problem is- when I try opening the device using the UsbManager.openDevice(UsbDevice) method of the UsbManager Class of the android’s USB host APIs , I find that the method returns a null value in the UsbDeviceConnection variable
This is the thread where all the methods for opening the UsbConnection are implemented
private class SetupThread extends Thread {
public void run() {
String devParam = "";
String intfepParam = "";
// display device descriptor
devParam = ardParam.devinfoRet(arduino);
devDscrptor.setText(devParam);
intf = ardParam.findIntf(arduino);
if (intf != null) {
intfepParam = ardParam.intfPara(intf);
log1.setText("Interface found");
epIn = ardParam.findepIn(intf);
epOut = ardParam.findepOut(intf);
if (epIn != null && epOut != null) {
log2.setText("Both endpoints found");
intfepParam += ardParam.epPara(epIn);
intfepParam += ardParam.epPara(epOut);
intfepDscrptor.setText(intfepParam);
// just checking if Usbdevice arduino is null
if (arduino != null) {
// this is where the problem comes
mConnection = mUsbManager.openDevice(arduino);
conxnInfo.setText("Arduino not null");
}
if (mConnection != null) {
mConnection.claimInterface(intf, false);
conxnInfo.setText("Connection opened");
}
}
else {
if ((epIn == null) && (epOut == null)) {
intfepDscrptor.setText(intfepParam);
log2.setText("Both endpoints null");
}
else if ((epIn == null) && (epOut != null)) {
intfepParam += ardParam.epPara(epOut);
intfepDscrptor.setText(intfepParam);
log2.setText("epIn null");
}
else {
intfepParam += ardParam.epPara(epIn);
intfepDscrptor.setText(intfepParam);
log2.setText("epOut null");
}
}
} else {
log1.setText("Interface is null");
}
}
}
ardParam is an object of ArduinoParams class and the code for ArduinoParams class is as follows:
package com.example.arduinobasic;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
public class ArduinoParams {
public String devinfoRet(UsbDevice device) {
String DevInfo = "";
DevInfo += "Device Name:" + device.getDeviceName();
DevInfo += "Device Id:" + device.getDeviceId();
DevInfo += "Product Id:" + device.getProductId();
DevInfo += "Vendor Id:" + device.getProductId();
DevInfo += "Device Class:" + device.getDeviceClass();
DevInfo += "Device Subclass" + device.getDeviceSubclass();
DevInfo += "Device Protocol:" + device.getDeviceProtocol() + "\n";
return DevInfo;
}
public UsbInterface findIntf(UsbDevice device) {
UsbInterface intf = null;
for (int i = 0; i < device.getInterfaceCount(); i++) {
if (device.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC
&& device.getInterface(i).getInterfaceSubclass() == 255
&& device.getInterface(i).getInterfaceProtocol() == 255) {
intf = device.getInterface(i);
}
}
return intf;
}
public UsbEndpoint findepIn(UsbInterface intf) {
UsbEndpoint epin = null;
for (int i = 0; i < intf.getEndpointCount(); i++) {
if ((intf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN)
&& (intf.getEndpoint(i).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)) {
epin = intf.getEndpoint(i);
}
}
return epin;
}
public UsbEndpoint findepOut(UsbInterface intf) {
UsbEndpoint epout = null;
for (int i = 0; i < intf.getEndpointCount(); i++) {
if ((intf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_OUT)
&& (intf.getEndpoint(i).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)) {
epout = intf.getEndpoint(i);
}
}
return epout;
}
public String intfPara(UsbInterface intf) {
String intfPara = "";
intfPara += "Interface id:" + intf.getId();
intfPara += "Interface Class:" + intf.getInterfaceClass();
intfPara += "Interface Subclass:" + intf.getInterfaceSubclass();
intfPara += "Interface Protocol:" + intf.getInterfaceProtocol() + "\n";
return intfPara;
}
public String epPara(UsbEndpoint ep) {
String epPara = "";
epPara += "Endpoint Address:" + ep.getAddress();
epPara += "Endpoint Attributes:" + ep.getAttributes();
epPara += "Endpoint Direction" + ep.getDirection();
epPara += "Endpoint Number:" + ep.getEndpointNumber();
epPara += "Endpoint max pckt size :" + ep.getMaxPacketSize();
epPara += "Endpoint Interval :" + ep.getInterval();
epPara += "Endpoint Type:" + ep.getType() + "\n";
return epPara;
}
}
Sorry for using a lot of if-else statements.I hope some one will help me out with this problem. Thanks in advance.
I'm trying to get some data out of a USB device connected to my Android phone that is on host mode. I'm able to send data to it, but reading fails.
I've looked at several examples and tried all I could but I don't have any experience in USB communication, although by now I know a little, and I've been stuck on this longer that I care to admit.
I'm not very familiar with the endpoint configuration, but I know is that my device uses a CDC type communication method and both the output (from phone to device) and input are registered.
Here's the whole class that manages the USB connection with the only device that is connected to the phone, it's not finished by any means, but I'd like to get that reading part to work before I go any further.
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");
}
}
};
}
I keep getting -1 from the read() method which indicates some kind of error, it always times out. Maybe the problem comes from the connection configuration, I've tried several (read: trial and error) and none worked, surprisingly I don't need any configuration to send data to the device.
Edit
It must also be noted that the cable I'm using is micro-USB to micro-USB and it only works in one way, that is my device is powered by my phone only when the plug A connected to phone and plug B connected to device, not the other way around... it seems very strange. The fact that I'm able to send data and not receive when plugged the right way remains.
EDIT 2
I found that somebody else had the same problem but it seems he wasn't able to solve it.
EDIT 3
I finally found the solution on 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.
So the DTR signal was mandatory and all I had to do was to add this to the interface configuration:
connection.controlTransfer(0x21, 0x22, 0x1, 0, null, 0, 0);
EDIT 4
If anybody is interested I finished the project and it's open source and published on my GitHub account. It's not stable all the time though (see the notes) and I don't plan working on it anymore, but it works. Feel free to use it for your own projects.
You can use UsbSerial Lib of from https://github.com/mik3y/usb-serial-for-android
My example code:
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());
}
I want to send a short data package (just 2 characters) via bulkTransfer to a camera connected via USB. I am using Samsung Galaxy S2 with Android 4.0.3 as a host. Everything seems fine, accept... no data is actually being sent. Theoretically, the method bulkTransfer returns a positive value, meaning the data has been transfered, but there is no visible effect. The code is as follows:
char ch = (char)34;
char[] record = {'P',ch};
String r = record.toString();
byte[] bytes = r.getBytes(Charset.forName("ASCII"));
int TIMEOUT = 10000;
boolean forceClaim = true;
UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
UsbInterface intf = device.getInterface(0);
for (int i = 0; i < intf.getEndpointCount(); i++) {
UsbEndpoint ep = intf.getEndpoint(i);
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
endpoint = ep;
//Integer dir = endpoint.getDirection();
UsbDeviceConnection connection = mUsbManager.openDevice(device);
if(connection!=null){devMessage+=" I connected";}
connection.claimInterface(intf, forceClaim);
Integer res = connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT);
if (res>0){devMessage += "some data transfered.";}
connection.releaseInterface(intf);
break;
}
}
Is there anything more I need to include before I start bulkTransfer? Is there any need for controlTransfer before I start bulkTransfer? Is there anything else I might be forgetting.
Please be understanding as this is my first app with USB communication and there are not many resources on the net. I've already read everything about usb host on developer.android... so please do not direct me there. Thanks a lot for any help.
May be the interface is not right Your using the device.getInterface(0). So this may not be right. Try this to get the interface.
for (int i = 0; i < device.getInterfaceCount(); i++) {
UsbInterface usbif = device.getInterface(i);
UsbEndpoint tOut = null;
UsbEndpoint tIn = null;
int tEndpointCnt = usbif.getEndpointCount();
if (tEndpointCnt >= 2) {
for (int j = 0; j < tEndpointCnt; j++) {
if (usbif.getEndpoint(j).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (usbif.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_OUT) {
tOut = usbif.getEndpoint(j);
} else if (usbif.getEndpoint(j).getDirection() == UsbConstants.USB_DIR_IN) {
tIn = usbif.getEndpoint(j);
}
}
}
if (tOut != null && tIn != null) {
// This interface have both USB_DIR_OUT
// and USB_DIR_IN of USB_ENDPOINT_XFER_BULK
usbInterface = usbif;
endpointOut = tOut;
endpointIn = tIn;
}
}
}
I am developing an application to receive data on an Android device from an Arduino. It displays values only up to 255 when I convert it to integer, but I want those values which are sent by the Arduino board. I have tried converting them to strings but that didn't work either.
How can I solve this problem?
Here's the code running on the Android device:
package pkg.MultipleDataReceiveFromArduinoArray;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import pkg.MultipleDataReceiveFromArduino.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.android.future.usb.UsbAccessory;
import com.android.future.usb.UsbManager;
public class MultipleDataReceiveFromArduinoActivity extends
Activity implements Runnable {
private TextView txtReceivedBytes;
private TextView txtWaterLitres;
private TextView txtSensor1;
private TextView txtSensor2;
private TextView txtSensor3;
private EditText etCallibrationValue;
private Button btnSetCallibrationValue;
private static final String ACTION_USB_PERMISSION =
"com.google.android.DemoKit.action.USB_PERMISSION";
private UsbManager mUsbManager;
private PendingIntent mPermissionIntent;
private boolean mPermissionRequestPending;
private UsbAccessory mAccessory;
private ParcelFileDescriptor mFileDescriptor;
private FileInputStream mInputStream;
private FileOutputStream mOutputStream;
int countWaterVol = 0;
private int intCallibrationValue = 270;
private static final int MESSAGE_TEMPERATURE = 1;
private static final int MESSAGE_HUMIDITY = 2;
private static final int MESSAGE_WATERLEVEL = 3;
private static final byte COMMAND_OPEN_DOOR = 0x01;
private static final byte COMMAND_CLOSE_DOOR = 0x02;
protected class TelemetryPacket {
private int value;
public TelemetryPacket(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
private int composeInt(byte hi, byte lo) {
int val = (int) hi & 0xff;
val *= 256;
val += (int) lo & 0xff;
return val;
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtReceivedBytes=(TextView)findViewById(R.id.txtReceivedBytes);
txtWaterLitres =(TextView)findViewById(R.id.txtWaterLitres);
txtSensor1 = (TextView) findViewById(R.id.txtSensor1);
txtSensor2 =(TextView)findViewById(R.id.txtSensor2);
txtSensor3 =(TextView)findViewById(R.id.txtSensor3);
etCallibrationValue = (EditText)findViewById(R.id.etCallibrationValue);
btnSetCallibrationValue =
(Button)findViewById(R.id.btnSetCallibrationValue);
setupAccessory();
btnSetCallibrationValue.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
intCallibrationValue =
Integer.parseInt(etCallibrationValue.getText().toString());
Toast.makeText(getApplicationContext(),
"Callibration Value:" + intCallibrationValue,
Toast.LENGTH_SHORT).show();
}
});
}
#Override
public Object onRetainNonConfigurationInstance() {
if (mAccessory != null) {
return mAccessory;
} else {
return super.onRetainNonConfigurationInstance();
}
}
#Override
public void onResume() {
super.onResume();
if (mInputStream != null && mOutputStream != null) {
// streams were not null");
return;
}
// streams were null");
UsbAccessory[] accessories = mUsbManager.getAccessoryList();
UsbAccessory accessory = (accessories == null ? null : accessories[0]);
if (accessory != null) {
if (mUsbManager.hasPermission(accessory)) {
openAccessory(accessory);
} else {
synchronized (mUsbReceiver) {
if (!mPermissionRequestPending) {
mUsbManager.requestPermission(
accessory, mPermissionIntent);
mPermissionRequestPending = true;
}
}
}
} else {
// null accessory
}
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onDestroy() {
unregisterReceiver(mUsbReceiver);
super.onDestroy();
}
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
//TelemetryPacket p = (TelemetryPacket) msg.obj;
ValueMsg t = (ValueMsg) msg.obj;
txtReceivedBytes.setText("Received Bytes: "+t.getRet());
if (t.getReading4()==1) {
countWaterVol = countWaterVol+1;
txtWaterLitres.setText("Water Produced in Litres:"+
(countWaterVol+"\n"+"Interrupt Signal"+t.getReading3());
} else {
}
txtSensor1.setText("S 1: "+t.getReading1()+","+
"Reading 2: "+t.getReading2());
txtSensor2.setText("S 3: "+t.getReading3()+","+
"Reading 4: "+t.getReading4());
txtSensor3.setText("S 5: "+t.getReading5()+","+
"Reading 6: "+t.getReading6());
Alets alerts = new Alets();
}
};
private void setupAccessory() {
mUsbManager = UsbManager.getInstance(this);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mUsbReceiver, filter);
if (getLastNonConfigurationInstance() != null) {
mAccessory = (UsbAccessory) getLastNonConfigurationInstance();
openAccessory(mAccessory);
}
}
private void openAccessory(UsbAccessory accessory) {
mFileDescriptor = mUsbManager.openAccessory(accessory);
if (mFileDescriptor != null) {
mAccessory = accessory;
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
Thread thread = new Thread(null, this, "OpenAccessoryTest");
thread.start();
// Accessory opened
} else {
// failed to open accessory
}
}
private void closeAccessory() {
try {
if (mFileDescriptor != null) {
mFileDescriptor.close();
}
} catch (IOException e) {
} finally {
mFileDescriptor = null;
mAccessory = null;
}
}
public void run() {
int ret = 0;
//byte[] buffer = new byte[16384];
byte[] buffer = new byte[65536];
int i;
while (true) { // read data
try {
ret = mInputStream.read(buffer);
//ret= ret/3;
} catch (IOException e) {
break;
}
i = 0;
while (i < ret) {
int len = ret - i;
// if (len >= 1) {
int value = (int) buffer[0];
Message m = Message.obtain(mHandler);
m.obj = new ValueMsg('f',value,ret,buffer[1],buffer[2],
buffer[3],buffer[4],buffer[5]);
mHandler.sendMessage(m);
i += 1;
}
}
}
public static final long unsignedIntToLong(byte[] b)
{
long l = 0;
l |= b[0] & 0xFF;
l <<= 8;
l |= b[1] & 0xFF;
l <<= 8;
l |= b[2] & 0xFF;
l <<= 8;
l |= b[3] & 0xFF;
return l;
}
public static int unsignedByteToInt(byte b) {
return (int) b & 0x10;
}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbAccessory accessory = UsbManager.getAccessory(intent);
if (intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
openAccessory(accessory);
} else {
// USB permission denied
}
}
} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbAccessory accessory = UsbManager.getAccessory(intent);
if (accessory != null && accessory.equals(mAccessory)) {
// accessory detached
closeAccessory();
}
}
}
};
}
And here's the Arduino code (sketch):
#include <Usb.h>
#include <adk.h>
uint8_t b;
USB Usb;
ADK adk(&Usb,
"Ashok Kateshiya", // Manufacturer Name
"analog TEST", // Model Name
"TDS test ", // Description (user-visible string)
"0.1", // Version
"http://www.ashokkateshiya.co.cc",
"123456789"); // Serial Number (optional)
#define tds_pin A15
#define flow_pin 22
#define LLS_pin 49
float avg[10];
float value = 0;
int count;
int pin_state = 0, pin_old_state = 0;
int pulse_counter = 0;
int LLS_state;
int LLS_flag = 0;
int sensor_flag = 0;
int timer_flag = 0;
uint8_t msg[7] = { 0x00 };
uint16_t len = sizeof(msg);
uint8_t rcode;
void setup()
{
Serial.begin(115200);
Serial.print("\r\nADK demo start");
if (Usb.Init() == -1)
{
Serial.print("\r\nOSCOKIRQ failed to assert");
while(1); // halt
}
pinMode(tds_pin, INPUT);
pinMode(flow_pin, INPUT);
pinMode(LLS_pin, INPUT);
digitalWrite(LLS_pin, HIGH);
digitalWrite(flow_pin, HIGH);
TIMSK1 = 0x01;
TCCR1A = 0x00;
TCNT1 = 0x85EF;
TCCR1B = 0x05;
}
void loop()
{
Usb.Task();
if (adk.isReady() == false)
{
return;
}
TDS();
flow();
LLS();
}
void TDS()
{
for (count = 0; count < 10; count++)
{
avg[count] = analogRead(tds_pin);
}
for (count = 0; count < 10; count ++)
{
if (count == 0)
{
value = avg[count];
}
else
{
value = value + avg[count];
}
}
if (len > 0)
{
msg[0] = 0x1;
msg[1] = value/10;
rcode = adk.SndData (6, msg );
Serial.print("TDS 0 : ");
Serial.println(msg[0]);
Serial.print("TDS 1 : ");
Serial.println(msg[1]);
delay(10);
}
if (rcode && rcode != hrNAK)
USBTRACE2("DATA rcv :", rcode);
}
void flow()
{
pin_state = digitalRead(flow_pin);
if (pin_state == LOW)
{
pin_old_state = pin_state;
}
if ((pin_state == HIGH) && (pin_old_state == LOW))
{
pin_old_state = pin_state;
pulse_counter = (pulse_counter + 1);
sensor_flag = 1;
}
if ((pulse_counter / 25 == 1) && (sensor_flag == 1))
{
pulse_counter = 0;
sensor_flag = 0;
msg[2] = 0x2;
msg[3] = 1;
rcode = adk.SndData (6, msg );
Serial.print("value :");
Serial.println(msg[3]);
if (rcode && rcode != hrNAK)
{
USBTRACE2 ("USB DATA : ", rcode);
}
}
else
{
msg[2] = 0x2;
msg[3] = 0;
rcode = adk.SndData (6, msg );
Serial.print("value :");
Serial.println(msg[3]);
if (rcode && rcode != hrNAK)
{
USBTRACE2 ("USB DATA : ", rcode);
}
}
delay(10);
}
void LLS()
{
LLS_state = digitalRead(LLS_pin);
if (LLS_state != 0)
{
if (len > 0)
{
msg[4] = 0x3;
msg[5] = 0x0;
rcode = adk.SndData (6, msg );
Serial.print("LLS 4 : ");
Serial.println(msg[4]);
Serial.print("LLS 5 : ");
Serial.println(msg[5]);
}
}
else
{
msg[4] = 0x3;
msg[5] = 0x1;
rcode = adk.SndData (6, msg );
Serial.print("LLS 0 : ");
Serial.println(msg[4]);
Serial.print("LLS 2 : ");
Serial.println(msg[5]);
}
if (rcode && rcode != hrNAK)
USBTRACE2("DATA rcv :", rcode);
delay(10);
}
/****** timer overflow *******/
ISR(TIMER1_OVF_vect)
{
TCNT1 = 0x85EF;
if (pin_state == pin_old_state )
{
timer_flag = 1;
}
}
It looks like the problem is in the Arduino sketch. The msg array contains (unsigned) bytes which have a maximum value of 255.
The line:
msg[1] = value/10
implicitly truncates value/10 (which is an integer between 0 and 1023 - see http://arduino.cc/en/Reference/analogRead) to a maximum of 255.
To send value/10 you'll need to split it over 2 bytes. For example:
msg[1] = (uint8_t) (i & 0xFF);
msg[2] = (uint8_t) ((i >> 8) & 0xFF);
And msg will have to be one byte longer to accomodate.
On the Android (Java) side you'll need to do something like:
int value = (int) buffer[0];
// ...
int tds = buffer[1] + (buffer[2] << 8);
m.obj = new ValueMsg('f', value, ret, tds,
buffer[3], buffer[4], buffer[5], buffer[6]);
which will require a change to the definition of ValueMsg to accomodate.
Also, there may be a problem with the calls to SndData (assuming the library being used here is the USB_Host_Shield_2.0) as they always send 6 bytes even though in the first time through loop all 6 bytes of msg won't have been initialized.