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#)
Related
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.
I'm still new to Android studio and I'm having a lot of trouble with Bluetooth, I'm currently making an app where I need to send data between devices. I'm letting the phone's default Bluetooth setup do the pairing but now I need to know how to send the data, I know I need to use input and output streams but I don't know exactly how.
And yes I have searched all over Google, I've followed a lot of Bluetooth tutorials but none of them seem to really explain how to send data from one device to another.
Thanks in advance.
After you establish a secure/insecure connection via bluetooth the rest is just socket programming simply. That is lets think about sending a text. We convert the text to byte and send that by Java OutputStream. In the same manner for the data received we can get it by InputStream.
But remember you need to maintain bunch of code and thread/handler to maintain state and others. Though the basic thing is simply socket programming over Bluetooth socket using the Bluetooth adapter. Have a look at the below repository in github. This creates a chatroom over bluetooth. i.e it sends and receives string data
https://github.com/zahansafallwa/Android-bluetooth-chat-with-emoji/tree/master/app/src/main/java/com/zahan/safallwa/donttalk
Specially have a look at the BluetoothChatService class. That contains codes related to sending data. BluetoothChatService
Edit:
As per your comment lets think that your devices are paired and also connected. Now you only need to send the text. Declare a outputstream
private final OutputStream mmOutStream;
Suppose you have a string. We convert it to byte. Then get our socket outputstream and send data by write() method
String message="this is test data";
byte[] send = message.getBytes();
mmOutStream = socket.getOutputStream(); // here socket is the bluetooth socket you establish
mmOutStream.write(send);//this is what sends the message
Remember:
Edited code is for your understanding only. It is prescribed to use separate thread for sending data.
I am working on an Android BLE project. We are using BLE to configure some settings on an embedded device. The embedded device was going to take a long time to come up so I started using BlueSim to emulate the embedded connection.
There are essentially two messages that the Android (I'm requiring KitKat) device sends off to the embedded device. One is to write settings....One is to read the settings.
A Write message is going out to endpoint 0xFFF1 like the following
byte[] data2Send = new byte[11];
data2Send[0] = 0xAA; // signifying this is a write message to device
data2Send[1] = 0x01; // data value
data2Send[2] = 0x38; // data value
data2Send[3] = 0x47; // data value
data2Send[4] = 0x24; // data value
data2Send[5] = 0x01; // data value
data2Send[6] = 0x36; // data value
data2Send[7] = 0x49; // data value
data2Send[8] = 0x0b; // data value
data2Send[9] = 0x63; // data value
data2Send[10] = 0x0D; // CR to indicate the last byte of the packet
characteristic.setValue(data2Send);
boolean status = mBluetoothGatt.writeCharacteristic(characteristic);
Log.v(TAG,"Status is:" + String.valueOf(status));
I had verified this using BlueSim and we have confirmed that this works when transmitting data to the embedded device. We can successfully change all of the settings.
The other message is a Read request of the device so I can know what settings are already in there or to confirm that the settings actually changed.......
byte[] data3Send = new byte[3];
data3Send[0] = 0x55; // Signify this is a start of a READ message
data3Send[1] = 0x42; // Second part of the read designator
data3Send[2] = 0x0d; // Carriage return saying this is the last bit
characteristic.setValue(data3Send);
boolean status = mBluetoothGatt.writeCharacteristic(characteristic);
Log.v(TAG,"Status is:" + String.valueOf(status))
When I send this message over to BlueSim, I see the message on my iPhone and immediately send the settings back out. On Android I see the 11 bytes that are coming back informing me of all the settings! This almost happens instantaneously. Great!
But when we do this on the embedded device I see one byte come back. That's it. Using a debugger on the embedded side we can see all 11 bytes going into the BLE module on the embedded device. If we use a PC rather than my Android device we can see all 11 bytes show up on the PC (the manufacturer of the BLE module has a terminal like app that you can 'sniff' the data with).
The embedded device is an 8 bit micro that is hooked up to a BLE module (TI CC2540 chipset) via a UART so it's obviously SLOWER than the iPhone where BlueSim is running. The embedded device is going to need some time to receive the BLE message, process the request, and shove data back out the BLE module. Is there some setting I have to set in my Android program to allow for a slower response to come back?
I tried downloading LightBlue on iOS and sending that read request out, and we get the same results. We see the first byte of the data packet show up in LightBlue. But only that one.
Any help would be greatly appreciated as always.
It sounds like you are experiencing an issue with the TI Module, not Android. Not sure if its the same issue, but it seems others have been getting headaches from trying to establish connections from Android to the CC254X. See here: https://e2e.ti.com/support/wireless_connectivity/f/538/t/401240
I have two phones which are paired and connected via bluetooth. How to programmatically check at one phone's end whether the other phone is getting an incoming call? Should I use a particular profile for this, that is, PBAP or HFP? If yes, how I am to do this?
Once I detect this, if I want to receive the incoming call via the connected phone, how should I implement that?
Download Hands Free Profile pdf. It is available easily. It provides you all details about how HFP works and AT commands supported by HFP for communication. No APIs available for this.
As eliasj said, you need to implement HFP and when two phones get connected, you can communicate between them via AT commands.
Suppose you have 1st phone which is Android device and 2nd phone Android or any device and they both are connected over HFP.
I don't have complete code but I can suggest you some AT commands -
1. Using AT+CIND? command you can read indicator status of other phone.
2. To enable reporting for Indicator status change, you need to use AT+CMER=3,0,0,1 command.
3. Once you get valid response from 'AT+CMER' command, you can use AlarmManager that will start a service which continuously reads the input stream of Bluetooth Socket.
4. Because of step 2., if the 2nd phone is having any incoming call, the input stream of Bluetooth Socket will contains RING as an alert.
I have used service implementing a Runnable. Here is a sample code for step 4.-
public void run()
{
try
{
// Get input and output streams from Bluetooth socket.
m_oInputStream = m_oBluetoothSocket.getInputStream();
m_oOutputStream = m_oBluetoothSocket.getOutputStream();
// Read input stream for +CIEV response is given or not.
byte[] buffer = new byte[200];
int nNumberOfBytesRead = m_oInputStream.read(buffer);
String strResponse = new String(buffer).trim();
if(true == strResponse.contains("RING"))
{
// Contains RING Alert. Answer the call.
// Start Activity for handling Incoming Call.
Intent oIncomingCallActivityIntent = new Intent(getApplicationContext(), IncomingCallActivity.class);
oIncomingCallActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
getApplicationContext().startActivity(oIncomingCallActivityIntent);
// Stop service.
stopSelf();
}
}
catch(Exception e)
{
// Log the error.
}
}
You need to implement acivity that handles incoming call. It will accept or reject call. To accept incoming call AT+ATA command is used. You will receive "OK" as a response from 2nd phone.
I hope this will help you.
You should implement HFP (the hands-free side). When I looked at this problem over a year ago it was not possible to send the audio between to phones (Android) but it could have change now.
Look at the Q/A in How to send AT commands based on BT Hands-Free profile in android? (hit on how to connect) and in the HFP spec https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=238193 (for how the profile works (incoming call on page 36))
ByteBuffer byteBuffer = ByteBuffer.allocate(9);;
UsbRequest request = new UsbRequest();
request.initialize(mConnection,mEndpointIntr);
boolean b = request.queue(byteBuffer, 9);
Log.d(TAG, "start the request wait");
UsbRequest ur = mConnection.requestWait();
I want to use Android USB interrupt. The above code is a thread to receive data from my own USB board. But when I try to call UsbRequest ur = mConnection.requestWait(); the function does not return, it always runs into requestWait(). Why does this happen?
The requestWait() in your code will wait for the result of the request.queue(byteBuffer, 9)
Here are some possible reasons why it is not returning:
Your request queue is on a different endpoint than what your USB device is actually sending data on. Double check that you are listening on the correct interface and endpoint.
On the USB device firmware side, do not create your interrupt endpoint on common interface class such as HID. Create a new vendor specific interface, otherwise kernel may get hold of the interface if it is HID and request queue may fail, this is what happened to me.
On my own USB HID device with two endpoints (IN and OUT) connected to MK802, I encountered the same problem (queuing a request returned false). I had claimInterface called with false. Setting the following helped, I receive data alright.
c.claimInterface(device.getInterface(0), true);