簡體   English   中英

ioctl返回ENOENT,嘗試將URB請求發布到Isoc設備端點(從android的JNI訪問)

[英]ioctl returns ENOENT trying to post URB request to Isoc device endpoint (accessed from android's JNI)

好像我在Android / JNI中缺少一些香料...

我正在嘗試訪問自定義復合USB設備,該設備通過OTG USB連接到常規(非root用戶)Android設備。 設備公開了幾個接口,其中包括音頻流和CDC終端,枚舉精細,並且在OS使用時可以播放音頻。

當我嘗試通過我的應用訪問此設備時,CDC完全沒有問題。 我可以在SDK的上下文中成功聲明接口,並從在JNI環境中啟動的單獨線程訪問其端點。

char read_buf[64];
struct usbdevfs_bulktransfer  ctrl;
memset(&ctrl, 0, sizeof(ctrl));
int fd = ((thread_arg_t*)arg)->fd;
ctrl.ep = ((thread_arg_t*)arg)->ep_in;
ctrl.len = sizeof(read_buf);
ctrl.data = read_buf;
ctrl.timeout = 0;

...

int ret = ioctl(fd, USBDEVFS_BULK, &ctrl);

因此,它可以很好地讀取來自USB設備CDC部分的數據...

但是,當涉及到音頻接口時,肯定會出問題...我可以聲明對接口的互斥訪問,公開其Isoc端點,然后返回true,但是當我嘗試通過我的獨立線程ioctl通過適當的端點流式傳輸音頻數據時在errno中返回ENOENT錯誤:

int fd = ((thread_arg_t*)arg)->fd;
struct usbdevfs_urb *urb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) + sizeof(struct usbdevfs_iso_packet_desc));

memset(urb, 0, sizeof(struct usbdevfs_urb) + sizeof(struct usbdevfs_iso_packet_desc));
uint8_t empty_buffer[192] = {0};

urb->type                = USBDEVFS_URB_TYPE_ISO;
urb->endpoint            = ((thread_arg_t*)arg)->ep_out;
urb->status              = -1;
urb->flags               = USBDEVFS_URB_ISO_ASAP;
urb->buffer              = empty_buffer;
urb->buffer_length       = 192;
urb->actual_length       = 0;
urb->start_frame         = 0;
urb->number_of_packets   = 1;
urb->error_count         = 0;
urb->signr               = 0;
urb->usercontext         = empty_buffer

struct usbdevfs_iso_packet_desc *iso_desc = &urb->iso_frame_desc[0];
iso_desc->length        = 192;
iso_desc->actual_length = 0;
iso_desc->status        = -1;

.....

int ret = ioctl(fd, USBDEVFS_SUBMITURB, urb);

有什么線索我想念的嗎?

數小時的調試結果不好。問題出在Android的API中。 當您ClaimInterface時,要求Android強制綁定驅動程序斷開連接時,僅在某些特定情況下才會將驅動程序與界面斷開連接(根據消息來源)。 如果沒有,您將沒有接口的專有使用權。 我可以采用的唯一解決方案是顯式調用ioctl():

usbdevfs_ioctl command;
command.ifno        = 0;
command.ioctl_code  = USBDEVFS_DISCONNECT;
command.data        = NULL;
ioctl(fd, USBDEVFS_IOCTL, &command );

command.ifno        = 1;
command.ioctl_code  = USBDEVFS_DISCONNECT;
command.data        = NULL;
ioctl(fd, USBDEVFS_IOCTL, &command );

然后真的有必要切換接口altsetting

struct usbdevfs_setinterface setif;
setif.altsetting = 1;
setif.interface = 1;
ioctl(fd, USBDEVFS_SETINTERFACE, &setif);

否則,端點將無法像最初發布時一樣可用(在我的USB設備中租借)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM