I am trying to port some software written in C to the Android platform. This software has a component that reads and writes from and to a connected USB device. What I am trying to do is open up a connection to the device in Java, then pass the file descriptor for the USB device(s) to the JNI code.
Below is the (relevant) output of lsof
for my app which shows I have two descriptors for the USB device:
com.tim 8861 u0_a66 35 ??? ??? ??? ??? /dev/bus/usb/001/002 com.tim 8861 u0_a66 36 ??? ??? ??? ??? socket:[51170] com.tim 8861 u0_a66 37 ??? ??? ??? ??? socket:[51173] com.tim 8861 u0_a66 38 ??? ??? ??? ??? /dev/bus/usb/001/003
I've passed both descriptors (above as 35 and 38) to my native method, but when I try and write to either of the file descriptors, write()
returns -1
, and I get an EINVAL
error.
Here is the body of my native method:
char buff[1024] = {0};
jsize len = (*env)->GetArrayLength(env, fds);
jint *arr = (*env)->GetIntArrayElements(env, fds, 0);
int i;
char data[4] = {
0x09,
0x90,
0x50,
0x50,
};
for (i = 0; i < len; i++) {
int wrote = write(arr[i], data, 4);
int flags = fcntl(arr[i], F_GETFL);
char *err = strerror(errno);
sprintf(buff, "%sFD: %d \n"
"wrote: %d \n"
"(err: %d %s) \n"
"flags: %d \n"
"NBIO %d \n"
"readonly %d \n"
"writeonly %d \n"
"both %d \n"
"append %d \n"
"large file %d \n\n", buff, arr[i], wrote, errno, err, flags, flags & O_NONBLOCK,
flags & O_RDONLY, flags & O_WRONLY, flags & O_RDWR, flags & O_APPEND,
flags & O_LARGEFILE);
}
return (*env)->NewStringUTF(env, buff);
The string that is returned when invoking that method is:
FD: 35 wrote: -1 (err: 22 Invalid argument) flags: 32770 NBIO 0 readonly 0 writeonly 0 both 2 append 0 large file 32768 FD: 38 wrote: -1 (err: 22 Invalid argument) flags: 32770 NBIO 0 readonly 0 writeonly 0 both 2 append 0 large file 32768
Writing to the USB device does work through Java, so it appears to just be an issue when trying to do it via native code.
Does anyone have any experience doing something like this?
It seems that using write()
on a USB file descriptor doesn't exactly work, since there are multiple endpoints on the USB device where the data could be written.
I was able use the ioctl()
function to perform a bulk transfer to a particular endpoint on the device:
#include <linux/usbdevice_fs.h>
#include <sys/ioctl.h>
// ...
char data[4] = {0x09, 0x90, 0x50, 0x50};
struct usbdevfs_bulktransfer bt;
bt.ep = usb_endpoint; /* endpoint (received from Java) */
bt.len = 4; /* length of data */
bt.timeout = 100; /* timeout in ms */
bt.data = data; /* the data */
int rtn = ioctl(fd, USBDEVFS_BULK, &bt);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With