I found a question posted for reading of USB data for FTDI devices.
Transferring data USB
I used this code for prolific device, and the usb can be detected, etc except that the the conn.bulkTransfer() gives a -1.
private class UsbRunnable implements Runnable {
private final UsbDevice mDevice;
UsbRunnable(UsbDevice dev) {
mDevice = dev;
}
public void run() {//here the main USB functionality is implemented
UsbDeviceConnection conn = mUsbManager.openDevice(mDevice);
if (!conn.claimInterface(mDevice.getInterface(1), true)) {
l("in run(), no connection");
return;
}
l("in run(), connection");
conn.controlTransfer(0x40, 0, 0, 0, null, 0, 0);// reset
// mConnection.controlTransfer(0×40,
// 0, 1, 0, null, 0,
// 0);//clear Rx
conn.controlTransfer(0x40, 0, 2, 0, null, 0, 0);// clear Tx
conn.controlTransfer(0x40, 0x02, 0x0000, 0, null, 0, 0);// flow
// control
// none
conn.controlTransfer(0x40, 0x03, 0xC04E, 0, null, 0, 0);// baudrate
// 38400
conn.controlTransfer(0x40, 0x04, 0x0008, 0, null, 0, 0);// data bit
// 8, parity
// none,
// stop bit
// 1, tx off
UsbEndpoint epIN = null;
UsbEndpoint epOUT = null;
byte counter=0;
//conn.bulkTransfer(epOUT, new byte[]{msData}, 1, 0);
UsbInterface usbIf = mDevice.getInterface(0);
for (int i = 0; i < usbIf.getEndpointCount(); i++) {
l("EP: "
+ String.format("0x%02X", usbIf.getEndpoint(i)
.getAddress()));
l("Type:"+usbIf.getEndpoint(i).getType());
if (usbIf.getEndpoint(i).getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {
l("Bulk Endpoint");
l("direction: "+usbIf.getEndpoint(i).getDirection());
if (usbIf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN)
epIN = usbIf.getEndpoint(i);
}
else l("no bulk");
l("epIN: "+epIN.toString());
}
for (;;) {// this is the main loop for transferring
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// This is where it is meant to receive
byte[] buffer = new byte[38400];
StringBuilder str = new StringBuilder();
l("bulk transfer thing: " + conn.bulkTransfer(epIN, buffer, 38400, 1000));
if (conn.bulkTransfer(epIN, buffer, 38400, 1000) > 0 ) {
l("bulk transfer is success");
for (int i = 2; i < 64; i++) {
if (buffer[i] != 0) {
str.append((char) buffer[i]);
} else {
l(str);
break;
}
}
}
// this shows the complete string
l(str);
if (mStop) {
mConnectionHandler.onUsbStopped();
return;
}
l("sent " + counter);
counter++;
counter = (byte) (counter % 16);
}
}
}
// END MAIN LOOP
private BroadcastReceiver mPermissionReceiver = new PermissionReceiver(
new IPermissionListener() {
public void onPermissionDenied(UsbDevice d) {
l("Permission denied on " + d.getDeviceId());
}
});
private static interface IPermissionListener {
void onPermissionDenied(UsbDevice d);
}
public final static String TAG = "USBController";
private void l(Object msg) {
Log.d(TAG, ">==< " + msg.toString() + " >==<");
}
private void e(Object msg) {
Log.e(TAG, ">==< " + msg.toString() + " >==<");
}
Can anyone tell me what changes I need to make? Thank you in advance.
There are several issues.
I assume that the commented out line is where you're having problems. You may want to reformat your code indentation and supply more information. In any case, assuming that your issue is occurring here:
byte counter=0;
//conn.bulkTransfer(epOUT, new byte[]{msData}, 1, 0);
The immediate problem that I see - epOut, the endpoint to which you are sending data is null. So of course it will fail. You're sending data to nothing. I followed the link that you posted to the example code that you copied, they have a line showing:
epOUT = usbIf.getEndpoint(i);
I would strongly suggest at the very least, you first make sure you understand the original code or have it working in your own program before you start making changes. DON'T just copy the above line of code to "fix" your problem.
Related
I am trying to make an application that connects to the arduino using the HC 05 module with three ultrasonic sensors. I was able to connect to the application and receive information from a particular sensor. But when I display the distance information of each sensor it is displayed in one text view (I would like three) but I have no idea what I could change in my code. Thanks in advance for your answer. Below I put the code in sequence: from arduino ideas, android studio app, android studio thread
int LtriggerPin = 13;
int LechoPin = 12;
int RtriggerPin = 11;
int RechoPin = 10;
int CtriggerPin = 9;
int CechoPin = 8;
int info = 0;
int state = 0;
void setup() {
Serial1.begin(9600);
pinMode(LtriggerPin, OUTPUT);
pinMode(LechoPin, INPUT);
pinMode(RtriggerPin, OUTPUT);
pinMode(RechoPin, INPUT);
pinMode(CtriggerPin, OUTPUT);
pinMode(CechoPin, INPUT);
}
void loop(){
sensor();
}
void sensor() {
int durationL, distanceL;
int durationR, distanceR;
int durationC, distanceC;
digitalWrite(LtriggerPin, HIGH);
delay(10);
digitalWrite(LtriggerPin, LOW);
durationL = pulseIn(LechoPin, HIGH);
distanceL = (durationL/2) / 29.1;
digitalWrite(RtriggerPin, HIGH);
delay(10);
digitalWrite(RtriggerPin, LOW);
durationR = pulseIn(RechoPin, HIGH);
distanceR = (durationR/2) / 29.1;
digitalWrite(CtriggerPin, HIGH);
delay(10);
digitalWrite(CtriggerPin, LOW);
durationC = pulseIn(CechoPin, HIGH);
distanceC = (durationC/2) / 29.1;
Serial1.print("Left Sensor ");
Serial1.print((String) distanceL + " cm" );
delay(500);
Serial1.println(" ");
Serial1.print("Right Sensor ");
Serial1.print((String) distanceR + " cm" );
delay(500);
Serial1.println(" ");
Serial1.print("Center Sensor ");
Serial1.print((String) distanceC + " cm" );
delay(500);
Serial1.println(" ");
Serial1.println(" ");
Serial1.println(" ");
}
//android thread
#Override
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.available();
if(bytes != 0) {
buffer = new byte[1024];
SystemClock.sleep(100); //pause and wait for rest of data. Adjust this depending on your sending speed.
bytes = mmInStream.available(); // how many bytes are ready to be read?
bytes = mmInStream.read(buffer, 0, bytes); // record how many bytes we actually read
hesler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget(); // Send the obtained bytes to the UI activity
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
public void write(String input) {
byte[] bytes = input.getBytes();
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
public void cancel() {
try {
sok.close();
} catch (IOException e) { }
}
// android Handler
handler = new Handler(Looper.getMainLooper()){
#Override
public void handleMessage(Message msg){
if(msg.what == MESSAGE_READ){
String readMessageL = null;
readMessageL = new String((byte[]) msg.obj, StandardCharsets.UTF_8);
TvC.setText(readMessageL);
}
if(msg.what == CONNECTING_STATUS){
char[] sConnected;
if(msg.arg1 == 1)
Tv3.setText(getString(R.string.BTConnected) + msg.obj);
else
Tv3.setText(getString(R.string.BTconnFail));
}
}
};
I'm transfering an image of 1 mb using the following code.
The image gets transferred successfully if a thread delay is implemented between each packets.
If the thread delay is not set all the packets are sent from BluetoothGattServer but the BluetoothGattCallback does not receive all the packets.
Can anyone guide in sending the packets without the thread delay
Implement thread between each packets
private void sendingContinuePacket(BluetoothGattCharacteristic characteristic,
byte[] CHARACTERS) {
boolean isComplete = false;
runOnUiThread(() -> {
tv_status.setText("Sending Data...!!");
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
});
// Check the data length is large how many times with Default Data (BLE)
int times = CHARACTERS.length / DEFAULT_BYTES_IN_CONTINUE_PACKET;
totalPackets = times;
Log.i("", "CHARACTERS.length() " + CHARACTERS.length);
byte[] packetNoByte;
byte[] sending_continue_hex = new byte[DEFAULT_BYTES_IN_CONTINUE_PACKET];
for (int time = 0; time <= times; time++) {
final int remainingTime = time;
if (!hasDisconnected) {
this.runOnUiThread(new Runnable() {
#Override
public void run() {
mRelativeLayout.setVisibility(View.VISIBLE);
if (totalPackets != 0) {
showProgress(totalPackets, remainingTime);
}
}
});
} else {
runOnUiThread(() -> {
mProgressBar.setProgress(0);
tv_progress.setText(0 + "%");
tv_timer.setText("00:00:00");
tv_imageSize.setText("");
tv_status.setText("");
Toast.makeText(PeripheralRoleActivity.this, "Something went wrong, Please Try again", Toast.LENGTH_SHORT).show();
customHandler.removeCallbacks(updateTimerThread);
});
return;
}
int a;
int b;
/**
* #param THREAD_SLEEP_TIME_FOR_NOTIFICATION
* this delay is placed to give a small pause while sending the data packe
* */
try {
Thread.sleep(Constants.THREAD_SLEEP_TIME_FOR_NOTIFICATION);
} catch (InterruptedException e) {
e.printStackTrace();
}
sentPacket = sentPacket + 1;
byte[] packetArray = Utils.getUtilsClass().toByteArray(sentPacket);
packetNoByte = Arrays.copyOf(packetArray, packetArray.length);
if (time == times) {
Log.i("", "LAST PACKET ");
int character_length = CHARACTERS.length
- DEFAULT_BYTES_IN_CONTINUE_PACKET * times;
byte[] sending_last_hex = new byte[character_length];
a = (sending_continue_hex.length) * time;
b = a + character_length;
if(b-a ==0){
return;
}
sending_last_hex = Arrays.copyOfRange(CHARACTERS, a, b);
byte[] last_packet =
new byte[packetNoByte.length + character_length];
System.arraycopy(packetNoByte, 0, last_packet,
0, packetNoByte.length);
System.arraycopy(sending_last_hex, 0, last_packet,
packetNoByte.length, sending_last_hex.length);
Log.d("Sending packets", Arrays.toString(last_packet));
// Set value for characteristic
characteristic.setValue(last_packet);
notifyCharacteristicChanged();
isComplete = true;
customHandler.removeCallbacks(updateTimerThread);
currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());
Log.d("Collection", "End Time: " + currentDateTimeString);
Utils.getUtilsClass().sendNotification(getApplicationContext(), "Data Transfer", "Transfer Complete");
} else {
Log.i("", "CONTINUE PACKET ");
a = ((sending_continue_hex.length) * time);
b = a + DEFAULT_BYTES_IN_CONTINUE_PACKET;
sending_continue_hex = Arrays.copyOfRange(CHARACTERS, a, b);
byte[] sending_continue_packet =
new byte[packetNoByte.length + sending_continue_hex.length];
System.arraycopy(packetNoByte, 0, sending_continue_packet,
0, packetNoByte.length);
System.arraycopy(sending_continue_hex, 0, sending_continue_packet,
packetNoByte.length, sending_continue_hex.length);
Log.d("data transfer a", String.valueOf(a));
Log.d("data transfer b", String.valueOf(b));
Log.d("data trans bytes", String.valueOf(sending_continue_hex.length));
if(output == null){
output = new ByteArrayOutputStream();
}
try {
if {
characteristic.setValue(sending_continue_packet);
Log.d("Sending packets", Arrays.toString(sending_continue_packet));
notifyCharacteristicChanged();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Log.d("Data byte", "times " + time);
if (isComplete) {
characteristic.setValue("Completed");
notifyCharacteristicChanged();
}
runOnUiThread(() -> tv_status.setText("Data sent!!"));
}
}
Updated Code
//the following function is used break the image byte [] into packets and store it in an arraylist
private void breakPackets(byte[] CHARACTERS) {
// Check the data length is large how many times with Default Data (BLE)
int times = CHARACTERS.length / DEFAULT_BYTES_IN_CONTINUE_PACKET;
totalPackets = times;
packetList = new ArrayList<>();
sendingPacket = 0;
Log.i("", "CHARACTERS.length() " + CHARACTERS.length);
byte[] sending_continue_hex = new byte[DEFAULT_BYTES_IN_CONTINUE_PACKET];
for (int time = 0; time <= times; time++) {
int a;
int b;
if (time == times) {
Log.i("", "LAST PACKET ");
int character_length = CHARACTERS.length
- DEFAULT_BYTES_IN_CONTINUE_PACKET * times;
byte[] sending_last_hex = new byte[character_length];
a = (sending_continue_hex.length) * time;
b = a + character_length;
sending_last_hex = Arrays.copyOfRange(CHARACTERS, a, b);
//packetList is an ArrayList<byte[]>
packetList.add(sending_last_hex);
startSendingPackets(sendingPacket);
} else {
a = (sending_continue_hex.length) * time;
b = a + DEFAULT_BYTES_IN_CONTINUE_PACKET;
sending_continue_hex = Arrays.copyOfRange(CHARACTERS, a, b);
packetList.add(sending_continue_hex);
}
Log.d("Data byte", "times " + time);
}
}
//the following function is used to set the byte[] from the arraylist to the characteristics and then notify the characteristics
private void startSendingPackets(int packet) {
isCommand = false;
mSampleCharacteristic.setValue(packetList.get(packet));
notifyCharacteristicChanged();
Log.i("packeting", "Sending ------------> " + packet);
}
/*************************************************/
#Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
//check if status is success
if (status == BluetoothGatt.GATT_SUCCESS) {
//if status is not successful isExecutable is false and the else loop is executed to resend the same packet that has failed
if (isExecutable) {
// Log.i("packeting", "Sent ------------> " + sendingPacket);
sendingPacket = sendingPacket + 1;
int size = packetList.size();
if (sendingPacket <= size-1) {
startSendingPackets(sendingPacket);
Log.d(MainActivity.TAG, "Notification sent. Status: " + status + " sending packet no --" + sendingPacket);
} else {
sendCommand("Completed");
}
} else {
startSendingPackets(sendingPacket);
isExecutable = true;
Log.d(MainActivity.TAG, "Notification sent. Status: " + status + " sending packet no --" + sendingPacket);
}
}else{
//if status is not successful
isExecutable = false;
Log.d(MainActivity.TAG, "Notification sent. fail Status: " + status );
}
}
As can be read in the documentation at https://developer.android.com/reference/android/bluetooth/BluetoothGattServerCallback.html#onNotificationSent(android.bluetooth.BluetoothDevice,%20int):
When multiple notifications are to be sent, an application must wait
for this callback to be received before sending additional
notifications.
This means after you have called notifyCharacteristicChanged, you cannot call notifyCharacteristicChanged again until the callback onNotificationSent has been received. So you need to remove your for-loop and refactor your code to follow the API rules.
The reason for this is to get flow control. If you just push new packets faster than the BLE link's throughput, the internal buffers get full and packet loss will occur. That's why a delay might seem to work, but it's not a robust solution so that's why you should wait for the onNotificationSent callback since that means the BLE stack is ready to accept new packets.
I am using Raspberry pi3 and DHT11 sensor for temperature monitoring project.
I have following pin positions
VCC to pin no : 2
Ground to pin no : 6
Output to GPIO : BCM22 i.e pin no 15
Code that I have used:
public class WeatherStationActivity extends Activity {
private Handler mHandler = new Handler();
private TextView mTxtStatus;
private PeripheralManagerService service = new PeripheralManagerService();
private Gpio tempGpio;
private int i = 0;
int[] dht11_dat = {0, 0, 0, 0, 0};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("Weather station", "Started Weather Station");
setContentView(R.layout.activity_main);
mTxtStatus = (TextView) findViewById(R.id.txtStatus);
try {
tempGpio = service.openGpio("BCM22");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (i == 10) {
handler.removeCallbacks(this);
} else {
getTemp();
handler.postDelayed(this, 5000);
}
i++;
}
}, 5000);
} catch (Exception e) {
e.printStackTrace();
}
}
private void getTemp() {
boolean laststate = false;
try {
laststate = tempGpio.getValue();
} catch (IOException e) {
e.printStackTrace();
}
int j = 0;
final int MAXTIMINGS = 85;
dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;
try {
tempGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
// tempGpio.setActiveType(Gpio.ACTIVE_LOW);
tempGpio.setValue(false);
// Thread.sleep(18);
TimeUnit.MILLISECONDS.sleep(18);
// tempGpio.setActiveType(Gpio.ACTIVE_HIGH);
// tempGpio.setActiveType(Gpio.ACTIVE_HIGH);
tempGpio.setValue(true);
TimeUnit.MICROSECONDS.sleep(40);
tempGpio.setDirection(Gpio.DIRECTION_IN);
/* tempGpio.setActiveType(Gpio.ACTIVE_HIGH);
tempGpio.setValue(true);*/
// tempGpio.setValue(true);
StringBuilder value = new StringBuilder();
for (int i = 0; i < MAXTIMINGS; i++) {
int counter = 0;
while (tempGpio.getValue() == laststate) {
counter++;
TimeUnit.MICROSECONDS.sleep(1);
if (counter == 255) {
break;
}
}
laststate = tempGpio.getValue();
mTxtStatus.append("\nLast State of Sensor " + laststate);
if (counter == 255) {
break;
}
//* ignore first 3 transitions *//*
if ((i >= 4) && (i % 2 == 0)) {
//* shove each bit into the storage bytes *//*
dht11_dat[j / 8] <<= 1;
if (counter > 16) {
dht11_dat[j / 8] |= 1;
}
j++;
}
}
// check we read 40 bits (8bit x 5 ) + verify checksum in the last
// byte
if ((j >= 40) && checkParity()) {
value.append(dht11_dat[2]).append(".").append(dht11_dat[3]);
Log.i("Logger", "temperature value readed: " + value.toString());
mTxtStatus.append("\nTemp " + value.toString());
} else {
mTxtStatus.append("\nNothing is working ");
Log.i("Logger", "Nothing is working ");
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private boolean checkParity() {
return dht11_dat[4] == (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3] & 0xFF);
}
}
Above code is giving me "Nothing is working" as output.
Any suggestion where I might be doing wrong?
You can't read data from DHT11 using Raspberry Pi 3 with Android Things because duration of DHT11 response pulses is from 26-28 us to 70 us, but max frequency of RP3 with AT GPIO is around 3kHz, which means around 300 us pulse duration. Take a look at answers to this question.
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 am trying to send and receive data over USB, my device, the Acer Iconia A500 has everything needed to connect to the device and everything, that is fine and works properly, but when I try sending and receiving data it doesn't behave as expected. This is my code
for( ; ; ) { //this is the main loop for transferring
String get = "$getPos";
byte[] getBytes = get.getBytes();
conn.bulkTransfer( epOUT, getBytes, getBytes.length, 500 );
try {
Thread.sleep( 500 );
byte[] buffer = new byte[4096];
conn.bulkTransfer( epIN, buffer, 4096, 500 );
StringBuilder byStr = new StringBuilder();
for( int i = 0; i < buffer.length; i++ ) {
if( buffer[i] != 0 ) {
byStr.append( buffer[i] + ", " );
}
}
l( byStr );
}
catch( InterruptedException e ) {
e.printStackTrace();
}
if( mStop ) {
mStopped = true;
return;
}
l( "sent " + counter );
counter++;
counter = (byte)( counter % 16 );
}
Its meant to return an Array of bytes about 80 characters long but it only returns two bytes back which are 1 and 96, if there was a error on the USB devices end it would still return a few more then two. Is my code even close to correct? I based it of the USB to serial article by serverbox.
I was trying to send data over the wrong baud rate.
Here's the code that works. Posting it for everyone who is using FTDI devices and needs help.
private Runnable mLoop = new Runnable() {
#Override
public void run() {
UsbDevice dev = sDevice;
if (dev == null)
return;
UsbManager usbm = (UsbManager) getSystemService(USB_SERVICE);
UsbDeviceConnection conn = usbm.openDevice(dev);
l("Interface Count: " + dev.getInterfaceCount());
l("Using "
+ String.format("%04X:%04X", sDevice.getVendorId(),
sDevice.getProductId()));
if (!conn.claimInterface(dev.getInterface(0), true))
return;
conn.controlTransfer(0x40, 0, 0, 0, null, 0, 0);// reset
// mConnection.controlTransfer(0×40,
// 0, 1, 0, null, 0,
// 0);//clear Rx
conn.controlTransfer(0x40, 0, 2, 0, null, 0, 0);// clear Tx
conn.controlTransfer(0x40, 0x02, 0x0000, 0, null, 0, 0);// flow
// control
// none
conn.controlTransfer(0x40, 0x03, 0x0034, 0, null, 0, 0);// baudrate
// 57600
conn.controlTransfer(0x40, 0x04, 0x0008, 0, null, 0, 0);// data bit
// 8, parity
// none,
// stop bit
// 1, tx off
UsbEndpoint epIN = null;
UsbEndpoint epOUT = null;
byte counter = 0;
UsbInterface usbIf = dev.getInterface(0);
for (int i = 0; i < usbIf.getEndpointCount(); i++) {
l("EP: "
+ String.format("0x%02X", usbIf.getEndpoint(i)
.getAddress()));
if (usbIf.getEndpoint(i).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
l("Bulk Endpoint");
if (usbIf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN)
epIN = usbIf.getEndpoint(i);
else
epOUT = usbIf.getEndpoint(i);
} else {
l("Not Bulk");
}
}
for (;;) {// this is the main loop for transferring
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String get = "$fDump G" + "\n";
l("Sending: " + get);
byte[] by = get.getBytes();
// This is where it sends
l("out " + conn.bulkTransfer(epOUT, by, by.length, 500));
// This is where it is meant to receive
byte[] buffer = new byte[4096];
StringBuilder str = new StringBuilder();
if (conn.bulkTransfer(epIN, buffer, 4096, 500) >= 0) {
for (int i = 2; i < 4096; i++) {
if (buffer[i] != 0) {
str.append((char) buffer[i]);
} else {
l(str);
break;
}
}
}
// this shows the complete string
l(str);
if (mStop) {
mStopped = true;
return;
}
l("sent " + counter);
counter++;
counter = (byte) (counter % 16);
}
}
};