linux 在USB大容量存储设备上首次成功写入libusb_bulk_transfer()后,libusb_bulk_transfer()读取挂起

d6kp6zgx  于 2023-11-17  发布在  Linux
关注(0)|答案(2)|浏览(173)

我尝试在我的USB大容量存储设备上执行写/读libusb_bulk_transfer()。但是在第一次成功的libusb_bulk_transfer()写之后,我的程序只是挂起,并且不执行libusb_bulk_transfer()读。我观察到我的USB设备被分离。为什么我不能执行读?
下面是我的代码片段:

e = libusb_get_configuration(handle, &config2);
if (e!=0)
{
    printf("\n***Error in libusb_get_configuration\n");
    libusb_free_device_list(devs, 1);
    libusb_close(handle);
    return -1;
}
printf("\nConfigured value : %d", config2);

if (config2 != 1)
{
    libusb_set_configuration(handle, 1);
    if (e!=0)
    {
        printf("Error in libusb_set_configuration\n");
        libusb_free_device_list(devs, 1);
        libusb_close(handle);
        return -1;
    }
    else
        printf("\nDevice is in configured state!");
}

if (libusb_kernel_driver_active(handle, 0) == 1)
{
    printf("\nKernel Driver Active");
    if (libusb_detach_kernel_driver(handle, 0) == 0)
        printf("\nKernel Driver Detached!");
    else
    {
        printf("\nCouldn't detach kernel driver!\n");
        libusb_free_device_list(devs, 1);
        libusb_close(handle);
        return -1;
    }
}

e = libusb_claim_interface(handle, 0);
if (e < 0)
{
    printf("\nCannot Claim Interface");
    libusb_free_device_list(devs, 1);
    libusb_close(handle);
    return -1;
}
else
    printf("\nClaimed Interface\n");

char *Report_to_write, *Report_to_read;
int transferred = 0;
int received = 0;
int nbytes = 8; // As protocol suggested it should be 8 bytes

Report_to_write = (char *)malloc(nbytes);
Report_to_read = (char *)malloc(nbytes);

Report_to_write[0] = 0x01; // cmd
Report_to_write[1] = Report_to_write[2] = Report_to_write[3] = 15; // HOUR
Report_to_write[4] = Report_to_write[5] = Report_to_write[6] = 30; // MIN
Report_to_write[7] = 255; // some checksum

memset(Report_to_read, '\0', 8);

e = libusb_bulk_transfer(handle, BULK_EP_OUT, Report_to_write, 8, &transferred, 0);

if (e == 0 && transferred == 8)
{
    printf("\nWrite successful!");
    printf("\nSent %d bytes with string: %s\n", transferred, Report_to_write);
}
else
    printf("\nError in write! e = %d and transferred = %d\n", e, transferred);

e = libusb_bulk_transfer(handle, BULK_EP_IN, Report_to_read, 8, &received, 0);  //64: Max Packet   Length
if (e == 0)
{
    printf("\nReceived: ");
    printf("%c", Report_to_read[1]); //Will read a string
    //sleep(1);
}
else
{
    printf("\nError in read! e = %d and received = %d\n", e, received);
    return -1;
}

e = libusb_release_interface(handle, 0);
libusb_free_device_list(devs, 1);
libusb_close(handle);
libusb_exit(NULL);

字符串

eyh26e7m

eyh26e7m1#

字符串和字符串看起来非常类似于堆栈溢出问题 Read/write on a pen drive using libusb: libusb_bulk_transfer() 中的代码(由我编写)。
通过观察您的代码,我只能预测您没有使用正确的端点地址。

sigwle7e

sigwle7e2#

我知道OP问题很老了,但这个主题仍然相关。
我最近遇到了类似的问题,我试图在virtualbox机器上用wireshark(usbmon)从制造商的原始windows程序中重放我录制的内容,我像你一样发送了一个命令,但没有收到答案。
Wireshark是调试此类问题的一个很好的工具。如果你有一个记录它应该是如何的,以及你自己的一个实现,你可以很容易地在所有细节上比较它们。
以下是代码中可能出现的错误:

端点地址错误

如前所述,端点地址可能错误。请确保BULK_EP_OUT < 0x80(写入设备)和BULK_EP_IN >= 0x80(从设备阅读)。
还要注意的是,所有的通信都是从主机开始的,甚至是传入的。这与下一点有关。

消息顺序

x1c 0d1x的数据
当使用libusb_bulk_transfer时,两个URB_BULK消息几乎是以原子方式传输的(host->device,然后device->host)。但是有些驱动程序在提交命令之前会打开接收通道。我对USB的了解还不够深入,但我认为这也有助于避免竞争条件。
如果你想在发送前打开传入通道,你必须将接收libusb_bulk_transfer拆分为libusb_alloc_transferlibusb_fill_bulk_transferlibusb_submit_transfer,并在发送命令后等待回调设置标志,最后是libusb_free_transfer。如果你正在寻找代码,请查看libusb_bulk_transfer的源代码。
对于我的设备,这不是问题,但我最后还是把它留了下来,因为我喜欢有一个100%相同的wireshark跟踪。

控制消息

在上述仍然没有成功之后,我还在wireshark中发现了一些SET_CONTROL消息。在我的情况下,相关的一个是SET CONTROL LINE STATE。我不知道它到底是什么,它可能是一些非常特定于设备的东西。但在我的情况下,从设备成功接收很重要。

int sync_send_control(libusb_device_handle * dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char * payload, int payload_size, unsigned int timeout){
    char *buf;
    int completed = 0;
    int nbytes = 8 + payload_size;
    struct libusb_transfer * transfer = libusb_alloc_transfer(0);
    if (!transfer)
        return LIBUSB_ERROR_NO_MEM;
    buf = (char *)malloc(nbytes + 1);
    memset(buf, '\0', nbytes);
    libusb_fill_control_setup(buf, bmRequestType, bRequest, wValue, wIndex, payload_size);
    if (payload_size>0)
        memcpy(&buf[8],payload,payload_size);
    libusb_fill_control_transfer(transfer, dev_handle, buf, syncread_transfer_cb, &completed, timeout); 
    int e = libusb_submit_transfer(transfer);
    if (e < 0){
        libusb_free_transfer(transfer);
        printf("error while sending control\n");
        return e;                   
    }

    sync_transfer_wait_for_completion(transfer); //from libusb-1 sources
}

sync_send_control(handle, 0x21, 0x22 /* set line state*/, 3, 0, NULL, 0, 2000);

字符串

更多

在原始软件的wireshark日志中,我甚至发现一个URB_INTERRUPT通道被打开了。我没有发现任何相关性,但它是一个很好的例子,有很多可能的原因是什么设备可能需要响应。

相关问题