hid_get_feature_report analog in Android USB Library - android

What would be analog to hid_get_feature_report in Android USB Library?
I need to get relays state from usb relays device on Android.
I found example on C (for Linux/Windows): https://github.com/darrylb123/usbrelay/blob/master/libusbrelay.c
static int get_board_features(relay_board *board, hid_device *handle)
{
unsigned char buf[9];
//Get the features of the device
buf[0] = 0x01;
int ret = hid_get_feature_report(handle, buf, sizeof(buf));
if (ret == -1)
{
perror("hid_get_feature_report\n");
}
//Set the serial number (0x0 for termination)
memset(board->serial, 0x0, sizeof(board->serial));
memcpy(board->serial, buf, Serial_Length);
//Byte 7 in the response contains the target_state of the relays
board->state = buf[7];
return ret;
}
On Android it returns only one end point Log.i(TAG, "endpointCount ${usbInterface.endpointCount}

Related

libusb - How to select an alternate setting of a usb-soundcard for stereo recording?

I have a USB sound card that has the following setup and allows for stereo recording with 48000hz 2 channels 16 bit, so I'm trying to set it up that way:
UsbConfiguration[mId=1,mName=null, mAttributes=160, mMaxPower=50,
mInterfaces=[
UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=1,mSubclass=1,mProtocol=0,
mEndpoints=[]
UsbInterface[mId=1,mAlternateSetting=0,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[]
UsbInterface[mId=1,mAlternateSetting=1,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=4,mAttributes=9,mMaxPacketSize=384,mInterval=1]]
UsbInterface[mId=1,mAlternateSetting=2,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=4,mAttributes=9,mMaxPacketSize=576,mInterval=1]]
UsbInterface[mId=1,mAlternateSetting=3,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=4,mAttributes=9,mMaxPacketSize=192,mInterval=1]]
UsbInterface[mId=2,mAlternateSetting=0,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[]
UsbInterface[mId=2,mAlternateSetting=1,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=196,mInterval=1]]
UsbInterface[mId=2,mAlternateSetting=2,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=294,mInterval=1]]
UsbInterface[mId=2,mAlternateSetting=3,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=388,mInterval=1]]
UsbInterface[mId=2,mAlternateSetting=4,mName=null,mClass=1,mSubclass=2,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=138,mAttributes=5,mMaxPacketSize=582,mInterval=1]]
UsbInterface[mId=3,mAlternateSetting=0,mName=null,mClass=3,mSubclass=0,mProtocol=0,
mEndpoints=[UsbEndpoint[mAddress=130,mAttributes=3,mMaxPacketSize=16,mInterval=16]
]
]
I'm trying to select and use the incoming interface with the alternate setting for stereo input and do the same thing with the interface for the stereo output.
For the input, I've tried to do it natively with the following code:
int AndroidUSBAudioIO_start(int sampleRate, int bufferSize, void *callback, void *clientData) {
int rc = -1;
if (androidUSBAudioIO == NULL) {
androidUSBAudioIO = (AndroidUSBAudioIOInternals *) malloc(sizeof(AndroidUSBAudioIOInternals));
}
androidUSBAudioIO->samplerate = sampleRate;
androidUSBAudioIO->buffersize = bufferSize;
androidUSBAudioIO->callback = (audioUSBProcessingCallback *) callback;
androidUSBAudioIO->clientData = clientData;
androidUSBAudioIO->maruStream = 0;
androidUSBAudioIO->isSetup = 0;
androidUSBAudioIO->isPlaying = 0;
rc = libusb_init(NULL);
if (rc < 0) {
}
androidUSBAudioIO->deviceHandle = libusb_open_device_with_vid_pid(NULL, VID, PID);
if (!androidUSBAudioIO->deviceHandle) {
rc = -1;
goto out;
}
rc = libusb_reset_device(androidUSBAudioIO->deviceHandle);
if (rc < 0) {
goto out;
}
rc = libusb_set_configuration(androidUSBAudioIO->deviceHandle, 1);
if (rc < 0) {
}
rc = libusb_kernel_driver_active(androidUSBAudioIO->deviceHandle, IFACE_NUM);
if (rc == 1) {
rc = libusb_detach_kernel_driver(androidUSBAudioIO->deviceHandle, IFACE_NUM);
if (rc < 0) {
goto out;
}
}
rc = libusb_claim_interface(androidUSBAudioIO->deviceHandle, IFACE_NUM);
if (rc < 0) {
goto out;
}
rc = libusb_set_interface_alt_setting(androidUSBAudioIO->deviceHandle, 1, 2);
if (rc < 0) {
printf("libusb_claim_interface: %s.\n", libusb_error_name(rc));
goto out;
}
...
I'm getting the following error at when setting the alternate interface:
Fatal signal 11 (SIGSEGV) at 0x0000001d (code=1), thread 10303
and also tried to do it from java with the following code upon receiving the permission to use the device:
UsbDeviceConnection mUsbDevConn = mUsbManager.openDevice(mAudioDevice);
int mReqType = 0x01; //
int mRequest = 0x0B; // SET_INTERFACE USB SPEC CONSTANT
int mValue = 0x02; // alt settings
int mIndex = 0x01; // interface nr
byte[] mBuffer = null;
int mLength = 0;
int mTimout = 1000;
mUsbDevConn.controlTransfer(UsbConstants.USB_DIR_OUT | mReqType, mRequest, mValue, mIndex, mBuffer, mLength, mTimout);
I'm getting the following error:
Error (status 6: **UNKNOWN**)
What am I missing?
I think it would be highly unusual for the libusb_set_interface_alt_setting call itself to cause the SIGSEGV. I would expect that either a prior call would cause this, or the SIGSEGV is an indirect effect of the call. That is, this call changes the alternate setting, which effectively starts the transfer of audio data. If the buffers, other data structures or the callback are not setup correctly a SIGSEGV may result.
In your situation, I would put more debug messages in the code, including in the library and your callback to try to narrow down the last thing before the crash.
If the code was working for a "mono" device, have a look at what has changed in the move to "Stereo". Perhaps the data-packet size (buffers) needs to be larger.
As far as the Java version is concerned, the error 6 may be related to the fact that you don't seem to be detaching any kernel drivers or claiming the interface before trying to change the alternate setting.
In the past I found it necessary to detach kernel drivers from each and every interface including HID interfaces to free up the allocated bus bandwidth before starting the audio.
Finally, if the free version of usbEffects (Android App) works with this device, you can connect adb to the phone via Wi-Fi and run the app with the device connected to see the debug messages that will tell if the requestType, request etc parameters are correct for this hardware.

Communicating with Nexus-4 using libusb in firmware update mode

I am trying to develop a simple program to communicate with the Nexus-4 bootloader in firmware update mode.
Nexus -4 has three usb interfaces. Interface-1 has two 2 endpoints - 2 and 131.
I wrote a program to write the command, get-device-info, through endpoint 2 and listen at endpoint 131 for the reply.
(I tried all permutations of interfaces and endpoints!).
The program successfully writes the command to the device but nothing is read from the device.
Command format: Flag(0x7e): CMD: Data (variable length): CRC-16: Flag(0x7e)
Get-device-info-command: 0x7e 0x00 0x78 0xf0 0x7e
The following is the program.
#include <stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
#define INTERFACE 1
#define EP_OUT 2
#define EP_IN 131
int main() {
libusb_device **devs; // retrieve a list of devices
libusb_device_handle *dev_handle; // device handler
libusb_context *ctx = NULL; //a libusb session
int r, r2, i;
ssize_t cnt; //holding number of devices in list
unsigned char data[30],read_data[512]; //data to write
data[0]=0x7e;data[1]=0x00;data[2]=0x78;data[3]=0xf0;data[4]=0x7e; // get-device-info command in HLDC format
int actual,read_actual;
r = libusb_init(&ctx);
if(r < 0) {
printf("Init Error\n");
return 1;
}
libusb_set_debug(ctx, 3);
cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
if(cnt < 0) {
printf("Get Device Error\n");
return 1;
}
printf("%d Devices in list\n",(int)cnt);
dev_handle = libusb_open_device_with_vid_pid(ctx, 4100, 25371); //these are vendorID and productID I found for Nexus-4 firmware update
if(dev_handle == NULL)
printf("Cannot open device\n");
else
printf("Device opened\n");
libusb_free_device_list(devs, 0); //free the device list
if(libusb_kernel_driver_active(dev_handle, INTERFACE) == 1) { //find out if kernel driver is attached
printf("Kernel Driver Active\n");
if(libusb_detach_kernel_driver(dev_handle, INTERFACE) == 0) //detach it
printf("Kernel Driver Detached!\n");
}
r = libusb_claim_interface(dev_handle, INTERFACE); //claim interface 1 Nexus-5/4 FUM
if(r < 0) {
printf("Cannot Claim Interface\n");
printf("%s\n",libusb_error_name(r));
return 1;
}
printf("Claimed Interface\n");
printf("Data to be send -> %s\n",data); //just to see the data that we are writing
printf("Writing Data...\n");
r = libusb_bulk_transfer(dev_handle, (EP_OUT | LIBUSB_ENDPOINT_OUT), data, 5, &actual, 0);
if(r == 0 && actual == 5){ //we wrote successfully 5 bytes to the device
printf("Writing Successful!\n");
printf("Waiting to read from device!\n");
r2 = libusb_bulk_transfer(dev_handle, (EP_IN | LIBUSB_ENDPOINT_IN), read_data, 512, &read_actual, 5000);
if (r2 >=0){
if (read_actual > 0){
printf("Data received by bulk transfer\n");
printf("Data is ");
for (i=0; i<read_actual; i++)
printf("%x ",read_data[i]);
printf("\n");
}
else{
printf(stderr, "No data received in bulk transfer (%d)\n", r2);
return -1;
}
}
else{
fprintf(stderr, "Error receiving data via bulk transfer %d\n", r2);
return r2;
}
}
else
printf("Write Error\n");
r = libusb_release_interface(dev_handle, INTERFACE); //release the claimed interface
if(r!=0) {
printf("Cannot Release Interface\n");
return 1;
}
printf("Released Interface\n");
libusb_close(dev_handle);
libusb_exit(ctx);
return 0;
}
The program is able to send the command successfully to the phone but it is not able to receive any response from the phone. When I run the program, I get the following output:
10 Devices in list
Device opened
Kernel Driver Active
Kernel Driver Detached!
Claimed Interface
Data to be send -> ~
Writing Data...
Writing Successful!
Waiting to read from device!
Error receiving data via bulk transfer -7
I am not sure the reason for not getting a response is because of the wrong command structure or because of the implementation of the program?

How do I convert a Linux C USB read to Android?

I have Tire Pressure Management System (TPMS) adapter that plugs into USB (http://store.mp3car.com/USB_TPMS_Version_2_20_4_Sensor_Kit_p/com-090.htm). I have it working with the original Windows software, as well as Linux C code to read the tire pressures and temperature. I'm now trying to use this adapter on Android and am having some difficulty. I can detect the device fine, but my reads are all returning -1 bytes read, whatever I try. Here's the C code I'm trying to convert:
int TpmsPlugin::readUsbSensor(int sid, unsigned char *buf)
{
int r, transferred;
buf[0] = 0x20 + sid;
r = libusb_interrupt_transfer(mDeviceHandle, ENDPOINT_OUT, buf, 1, &transferred, INTR_TIMEOUT);
if (r < 0) {
DebugOut() << "TPMS: USB write interrupt failed, code " << r << endl;
}
r = libusb_interrupt_transfer(mDeviceHandle, ENDPOINT_IN, buf, 4, &transferred, INTR_TIMEOUT);
if (r < 0) {
DebugOut() << "TPMS: USB read interrupt failed, code " << r << endl;
}
return r;
The value of sid is 1, 2, 3 or 4 depending on the wheel. The values are then extracted with:
lfPressure = ((float)buf[0]-40) * PRESSURE_SCALE * KPA_MULTIPLIER;
lfTemperature = (float)buf[1]-40;
You can see full implementation of this driver here as well: https://github.com/otcshare/automotive-message-broker/blob/master/plugins/tpms/tpmsplugin.cpp
My Android version is able to find the USB device, get permission to use it, connect to it, get the UsbEndpoints (it lists two), but whether bulkTransfer() or controlTransfer() I try, I've failed. In particular, I've tried a lot of different controlTransfer values based on all the docs I could find. Here is some code that I've tried:
UsbInterface intf = TpmsSectionFragment.device.getInterface(0);
UsbEndpoint endpoint_in = null, endpoint_out = null;
for (int i = 0; i < intf.getEndpointCount(); i++) {
UsbEndpoint ep = intf.getEndpoint(i);
if (ep.getDirection() == UsbConstants.USB_DIR_IN)
endpoint_in = ep;
else if (ep.getDirection() == UsbConstants.USB_DIR_OUT)
endpoint_out = ep;
}
UsbDeviceConnection connection = gUsbManager.openDevice(TpmsSectionFragment.device);
connection.claimInterface(intf, false);
int timeout = 1000;
int length = 4;
while (true) {
for (int sensorId = 1; sensorId <= 4 && mReadThreadActive; sensorId++) {
byte[] tpmsRaw = new byte[length];
tpmsRaw[0] = (byte) (0x20 + sensorId);
int out_len = connection.bulkTransfer(endpoint_out, tpmsRaw, 1, timeout);
int in_len = connection.bulkTransfer(endpoint_in, tpmsRaw, 4, timeout);
//int out_len = connection.controlTransfer(0x42, 0x0, 0x100, 0, tpmsRaw, tpmsRaw.length, timeout);
//int in_len = connection.controlTransfer(0x41, 0x0, 0x100, 0, tpmsRaw, tpmsRaw.length, timeout);
Any thoughts on what I could be doing wrong are greatly appreciated. I'm happy to try a few different things to debug further if you have any suggestions.
Thanks!
Here's the solution based on the help from Chris. I converted the calls to queue / requestWait:
ByteBuffer buf = ByteBuffer.allocate(4);
buf.put(0, (byte) (0x20 + sensorId));
UsbRequest send = new UsbRequest();
send.initialize(connection, endpoint_out);
Boolean sent = send.queue(buf, 1);
UsbRequest r1 = connection.requestWait();
send.initialize(connection, endpoint_in);
send.queue(buf, 4);
UsbRequest r2 = connection.requestWait();
The other thing I needed to tweak was this call and set the second parameter to true:
connection.claimInterface(intf, true);
That's it. Done. Thanks for the help!

Android Radio Interface Layer (RIL) and /dev/

Does anyone know how the RIL (/hardware/reference/reference-ril/) determines what gets mounted in /dev/ when the baseband radio gets initiated?
In older phones and in other documentation, GSM phones use /dev/smd0. Not all phones use /dev/smd0. I am trying to determine a way to find out what gets mounted regardless of the type of radio and vendor.
If someone can specifically identify where in the /hardware/reference/reference-ril/ I can see where this is set and where it's pulling the info from upon initialization, that would be perfect.
RIL is in your application Framework.
if you want to see the RIL and Implements the functionality with use of command prompt it is done.
There is below command :
void (*RIL_RequestFunc) (int request, void *data, size_t datalen, RIL_Token t);
I found this from here:
you are serious about this please go through link:
RIL Study LInk
If you want to know about example :
GIT HUB
It actually depends on what interface you are using to connect. You might use USB, UART or SPI interface to connect the upper layer with the modem. The paramter passed in the RIL_Init function determines the device you are trying to connect to. If you want to know specifically where this is done, please see the RIL_Init function in reference-ril.c.
const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
int ret;
int fd = -1;
int opt;
pthread_attr_t attr;
s_rilenv = env;
while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {
switch (opt) {
case 'p':
s_port = atoi(optarg);
if (s_port == 0) {
usage(argv[0]);
return NULL;
}
RLOGI("Opening loopback port %d\n", s_port);
break;
case 'd':
s_device_path = optarg;
RLOGI("Opening tty device %s\n", s_device_path);
break;
case 's':
s_device_path = optarg;
s_device_socket = 1;
RLOGI("Opening socket %s\n", s_device_path);
break;
default:
usage(argv[0]);
return NULL;
}
}
if (s_port < 0 && s_device_path == NULL) {
usage(argv[0]);
return NULL;
}
sMdmInfo = calloc(1, sizeof(ModemInfo));
if (!sMdmInfo) {
RLOGE("Unable to alloc memory for ModemInfo");
return NULL;
}
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
return &s_callbacks;
}
I hope things are clear now.

Trying to produce an exploitable Android Server

I'm trying to produce a simple server that will allow me test the Androids security features. I need to develop an application that will open a socket.
I've produced something similar in C, but I am having no look with java. Here's the application in C
// simpleserver3.c
#define MY_PORT 9999
#define MAXBUF 99
void indata(int clientfd, struct sockaddr_in client_addr)
{
char buffer[12];
printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
recv(clientfd, buffer, MAXBUF, 0); //this is will overflow the buffer
printf("%X \n", &buffer);
}
int main(int Count, char *Strings[])
{
struct sockaddr_in self, client_addr;
int sockfd,clientfd;
/*---Create streaming socket---*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) //socketfd = handle for socket
{
perror("Socket");
exit(errno);
}
/*---Initialize address/port structure---*/
bzero(&self, sizeof(self));
self.sin_family = AF_INET;
self.sin_port = htons(MY_PORT);
self.sin_addr.s_addr = INADDR_ANY;
/*---Bind the structure to the socket handle ---*/
if ( bind(sockfd, (struct sockaddr*)&self, sizeof(self)) != 0 )
{
perror("socket--bind");
exit(errno);
}
/*---Make it a "listening socket"---*/
if ( listen(sockfd, 20) != 0 )
{
perror("socket--listen");
exit(errno);
}
//set socklen_t to length of client address
socklen_t addrlen=sizeof(client_addr);
/*---accept a connection (creating a data pipe)---*/
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen); //create handle for communicating
indata(clientfd, client_addr);
close(clientfd);
close(sockfd);
return;
}
Any sugguestion would be great, Aneel
It's been a while since I used C, so I can't comment on your C code, but you should probably take a look at the Android documentation for the Socket class:
http://developer.android.com/reference/java/net/Socket.html
Check out this example: http://thinkandroid.wordpress.com/2010/03/27/incorporating-socket-programming-into-your-applications/

Categories

Resources