Android of Things communication with USB peripherals - android

I started my adventure with AoT (I have basic toolkit).
1rst Idea that I try to implement is to communicate via USB with Card Reader (USB Card Reader HID Prox v3).
But I don't get it correctly.
This is "sample" code:
usbRequest = new UsbRequest();
usbConnection = mUsbManager.openDevice(device);
usbRequest.initialize(usbConnection, device.getInterface(0).getEndpoint(0));//communication from card scanner
//In handler:
byte[] byteArray = new byte[16];
int transfer = usbConnection.bulkTransfer(device.getInterface(0).getEndpoint(0), byteArray, 16, 300);
transfer result is = -1, did anyone has the same issue?

Assumption: Your USB device conforms to the USB CCID Device Class. If this is not true, you will need to provide the datasheet for your specific card reader.
Before you can execute any communications with USB endpoints, your app has to claim the interface first. In other words, there should be a call to claimInterface() in your code before any requests are sent.
Next, you are mixing two different forms of communication. Your app should EITHER use UsbRequest for asynchronous use OR bulkTransfer() for synchronous use. You don't need to initialize a UsbRequest if you are using bulkTransfer() instead.
You should verify what the max packet size of your UsbEndpoint is. Bulk CCID endpoints can support up to 512 byte packets, so a fixed length of 16 bytes may not be enough to read a full packet response (assuming this transaction was on the Bulk IN endpoint). Match your array size with your endpoint's packet size.

Related

How to receive files programmatically using bluetooth

I am trying to receive data (strings) from a Bluetooth enabled device whose MAC_ID is known.
I have searched many examples ,but each article is pointing to Bluetooth Chat example, I think in Bluetooth Chat example, application need to be installed on both the devices for them to be connected and exchange strings.Correct me if I am wrong.
But I need to install application only on Receiver device.I have tried installing the application only on one device and tried connecting to the sender device, without success.
Bluetooth is a peer to peer protocol where you need to have application running on both sides. Hence if you want to exchange data very good example would be Bluetooth chat. If you want to download or transfer a file you should either implement obex or FTP profile based applications.
Yes you need to deploy an application on both sides. If you are really restricted in a way that you only can deploy on one side, you have to figure out which standard protocols/bluetooth profiles the other side is capable of. You can figure that out by doing a SDP lookup. For a device, you will then get a list of UUIDs identifying these services. See the bluetooth spec for well known UUIDs. As #7383 pointed out, your are most probably looking for OBEX or FTP.
If you can deploy on both sides, you can write your own app using Blaubot (disclaimer: I wrote it). A simple Blaubot program would do this:
UUID MY_UUID = UUID.fromString("33bb1246-1472-11e5-b60b-1697f925ec7b");
// onCreate() or in a service, we create a blaubot instance
// using Bluetooth to form a network and Bluetooth + NFC to find devices
IBlaubotDevice ownDevice = new BlaubotDevice();
BlaubotUUIDSet uuidSet = new BlaubotUUIDSet(MY_UUID);
BlaubotBluetoothAdapter bluetoothAdapter = new BlaubotBluetoothAdapter(uuidSet, ownDevice);
BlaubotNFCBeacon nfcBeacon = new BlaubotNFCBeacon();
BlaubotBluetoothBeacon bluetoothBeacon = new BlaubotBluetoothBeacon();
this.mBlaubot = BlaubotAndroidFactory.createBlaubot(MY_UUID, ownDevice, adapter, nfcBeacon, bluetoothBeacon);
// start and wait until connected
this.mBlaubot.startBlaubot();
// create a channel and send your file
IBlaubotChannel fileChannel = this.mBlaubot.createChannel(1);
// convert your file to its bytes
File yourFile = // ... however you get it
byte[] fileBytes = ...// ... see http://stackoverflow.com/questions/858980/file-to-byte-in-java
// send it to all connected devices
fileChannel.publish(fileBytes, true);
// to receive it on the other device, do this:
// subscribe to the channel
fileChannel.subscribe(new IBlaubotMessageListener() {
#Override
public void onMessage(BlaubotMessage message) {
// extract your bytes from the message
byte[] fileBytes = message.getPayload();
// .. do something useful or write it to a file again
// to write it to a file
File file = new File(yourFilePath);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bos.write(fileBytes);
bos.flush();
bos.close();
}
});
This should be all you need. To allow the devices to connect, you have to pair them before or use NFC (just hold them together, when Blaubot is started). If you go with Blaubot let me know if you have problems that can't be solved with the documentation or the android quickstart guide.
I can only guess what your actual scenario looks like. If you have two android phones, this should work. If that is not the case, you should add more informations about the involved devices. Are we really talking about (classic) Bluetooth connections or are you trying to get data from a Bluetooth Low Energy device?
In this case the famous chat example will not help you either.

Asynchronous bulk data transfer

I am working on USB communication between an Android Galaxy S III smartphone and a device which does not conform to Android Open Accessory device definition. I want to transfer asynchronously bulk data from the device to the host. The connection between the host and device works correctly, what has been verified by sending control commands to the device.
Can this transfer be done with an endpoint of the bulk type (USB_ENDPOINT_XFER_BULK) or it has to be the interrupt type (USB_ENDPOINT_XFER_INT) as it is specified in the MissileLauncher app sample?
Does the request.queue call fill the data buffer after the connection.requestWait returns or some other conditions need to be checked?
You must do your bulk transfer with your bulk endpoints either you do asynchronous or synchronous transfer(USB_ENDPOINT_XFER_BULK).
I can not give clear answer for you second question because I have too problem about this subject. I can fill my buffer with below code. Generally connection.requestWait() method is calling after request.queu(...) method. But I have problem in this state
ByteBuffer buffer = ByteBuffer.allocate(512);
buffer.order(ByteOrder.LITTLE_ENDIAN);
UsbRequest request = new UsbRequest();
request.initialize(usbDeviceModel.getConnection(), usbEndpoint2);
request.queue(buffer, 512);
if(request == usbDeviceModel.getConnection().requestWait()){
Message msg = imageViewFragment.usbDataHandler.obtainMessage();
msg.obj = buffer.array();
imageViewFragment.usbDataHandler.sendMessage(msg);
}
I want to send data to my activity with handler after if condition but I can not send when my device plugged in to android device. Only when I plugged out my device if condition is working and I can send data to activity with handler. (https://stackoverflow.com/questions/35350251/android-asynchronous-bulk-transfer-with-usb-host-api#)

Android BluetoothSocket OutputStream write blocks infinitely

I need to programmatically write data of say 1 to 100 MB in chunks of 1024 bytes to the remote Bluetooth device. Both are android devices. Here is a sample code snippet in my client program to transfer data –
bTSocket.connect(); //connect to remote BT device
DataOutputStream outStream = new DataOutputStream(bTSocket.getOutputStream());
byte[] buffer = new byte[1024];
int bytesToTransfer = 1000000;
while (bytesToTransfer > 0) {
outStream.write(buffer);
outStream.flush();
bytesToTransfer -= 1024;
}
outStream.close();
While running this piece of code on Android 2.2(Froyo), it works fine. However in case of Android 2.3.4 and 4.0.4, outStream.write(buffer) blocks infinitely after transfer of some data (say of 100 KB). Worth mentioning, the remote device is not configured for listening data. Is there any limitation on the amount of data that can be written?
The Bluetooth socket operates in blocking mode for both reads and writes.
If you fill up the send buffer, then the only thing that .write() can do to stop you trying to send any more data is to block. The alternative to it blocking would be to return an "operation would block!" error code, just like TCP sockets can do when placed in non-blocking mode. But the Bluetooth socket doesn't provide any such non-blocking mode.
You state that the remote Bluetooth device is not reading from its socket. With this being the case, the local sending buffer and remote receive buffer, with each only being of a certain finite size, will eventually fill up. At this point, your .write() operation is going to block until the remote end reads something from its socket. You can't just keep pumping in megabytes of data and expect it to just buffer it all somewhere.
The differences you experience between different Android platforms are probably down to the different amounts of buffer space available in the related Bluetooth stacks.

Android USB Host API: bulk transfer buffer size

I am writing software to communicate between tablet (Motorola Xoom with Android version 4.0.3 and Kernel version 2.6.39.4) and a peripheral device using USB Host API provided by Android. I use only two types of communication:
control: controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)
bulk: bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout)
Control transfer works fine, but I have a problem with bulk transfer. I can use only 32768 as a size of the buffer for bulkTransfer function. It is not possible to use less or more. I know that I cannot use more because of the limit of the buffer pipe (size: 32769 bytes).
This peripheral device streams data which is not correctly read by bulkTranfer function. I suppose that some data is lost.
I find this: In Linux If a process attempts to read from an empty pipe (buffer), then read(2) will block until data is available. If a process attempts to write to a full pipe , then write(2) blocks until sufficient data has been read from the pipe to allow the write to complete.
And based on that, my explanation of the problem is that some data is not written to pipe (buffer) because of blocking flag made by write(2) function. Am I correct? If this is true I could change pipe buffer.
My first solution for this problem is greater buffer. For
kernel >= 2.6.35, you can change the size of a pipe with fcntl(fd, F_SETPIPE_SZ, size) but how can I find fd (file descriptor) for
USB pipes?
Second option is to use ulimit -p SIZE but parameter p for my kernel is not for pipe but process.
Has anyone faced the same problem, any solutions?
You should get a USB data analyzer, Im using this one: http://www.ellisys.com/products/usbex200/index.php
Using something like this really helped me when I was doing the same type of thing, what I found was that you had to do some type of while loop.
For my device I had 64 bytes of data coming in packets to me, the packet would be two control bytes and 62 for data, so for my transfer I had to do something like
StringBuilder sb = new StringBuilder();
while(bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout) > 2){
for(int i = 2; i < buffer.length(); i++){
sb.append((char) buffer[i]);
}
}
something a long these lines worked good for me, i had exactly the same issue and this is how I fixed it. I have more information if you need it. Just comment :). I know this was really frustrating for me to. Im using an Acer Iconia A500 with Android 4.0.3 btw
Transferring larger amounts of data USB
Transferring data USB
According to the same .pdf gfour posted, I found this paragraph in there:
"The size of the packet will affect the performance and is dependent on the data rate. For very high speed, the largest packet size is needed. For 'real-time' applications that are transferring audio data at 115200 Baud for example, the smallest packet possible is desirable, otherwise the device will be holding up 4k of data at a time. This can give the effect of 'jerky' data transfer if the USB request size is too large and the data rate too low (relatively)."
I'm running into a situation similar to SmartLemon with a FTDI Serial device, so I've been recently looking up ways to alleviate it. This will require me to pretty much write my own functions from scratch while previously I was using a library.
However, it seems that in your case, you could try using bulkTransfer's lowest buffer size instead of shooting for the biggest. You may have tried this already, but maybe not. I see that you say 32768 is the only size, but maybe you only meant the max. It seems weird that it'd only allow one specific size.
The Android SDK's UsbEndpoint object provides a getMaxPacketSize() method, allowing you to check what is appropriate for your device. Generally, the maximum allowable packet size is 64 bytes for USB 'Full-speed' devices and 512 for 'High-speed' devices - far less than 32,768 you are attempting. Are you perhaps confusing the underlying USB packet size with that of some higher-level protocol?
According to AN232B-04_DataLatencyFlow.pdf, flow control is needed for high data rates:
It is strongly encouraged that flow control is used because it is
impossible to ensure that the FTDI driver will always be scheduled.
Have you tried using one of the flow control options (RTS/CTS, DTR/DSR, XON/XOFF) to synchronize your data?
You can try this for Bulk transfer issue
byte[] buffer = new byte[4096];
StringBuilder strIN = new StringBuilder();
if (conn.bulkTransfer(epIN, buffer, 4096, 500) >= 0) {
for (int i = 2; i < 4096; i++) {
if (buffer[i] != 0) {
strIN.append((char) buffer[i]);
textReceiveDataInfo.append(strIN + "\n");
} else {
l(strIN);
break;
}
}
}

Bluetooth Inputstream Android 2.2

I'm trying to connect a bluetooth device and to read out information from it.
I've used the Bluetooth chat example and changed the UUID tp SPP mode.
The connection works, but the Information that I get from the Inputstream is wrong.
The transmitted String is 20 signs long, but the Inputstream just returns a 7. The rest of the bufferstream is empty.
Does anyone has a clue?
After write try flushing the transmitter's stream.
And on the receiver you will need to wait till you receive the expected bytes.
SPP does not have packet boundaries. So you can receive the packets in multiple chunks and you need have some logic to determine packet boundaries.

Categories

Resources