Этап передачи данных управления RaspberryPi gadgetfs

#c #io #raspberry-pi #usb #gadgetfs

Вопрос:

Я настроил пользовательский USB-гаджет на RasperryPi 4, следуя этому идентификатору guid: https://blog.soutade.fr/post/2016/07/create-your-own-usb-gadget-with-gadgetfs.html

Теперь у меня следующая проблема:

Я получаю запрос класса с дополнительными данными в DataStage. Итак, вызывается функция:

 void handle_setup_request(int fd, struct usb_ctrlrequest *setup)
 

с

 setup->bRequestType: 0x21
setup->bRequest: 0x09
setup->wValue: 0x0202
setup->wIndex: 0x0001
setup->wLength: 0x00ff 
 

Поскольку это запрос OUT с дополнительными данными (wLength> 0), я вызываю

 ret = read(fd, request_buffer, setup->wLength); 
 

При чтении считывается 255 байт (ret == 255), но содержимое request_buffer не является данными, отправленными хостом. На самом деле он содержит данные, которые были последними отправлены на хост.

Затем я добавил

 struct pollfd fds[1];
fds[0].fd = fd;
fds[0].events = POLLIN;

poll(fds, 1, 400); 
 

перед read . Это всегда приводит к таймауту (возвращает 0). но у timeout = 400 меня когда-нибудь будут правильные данные в request_buffer .

Кто-нибудь знает, что я делаю не так? что я пропустил?

Для получения дополнительной информации у меня есть скриншот USB-анализатора, показывающий запрос. Скриншот USB-сниффера

Здесь соответствующий код:

     int init_device()
    {
        .
        .
        int fd = -1;
        fd = open(USB_DEV, O_RDWR | O_SYNC   ); 
        .
        .
        handle_ep0(fd);
    }

    int handle_ep0(int fd)
    {
        .
        .
        struct usb_gadgetfs_event events[5];
        
        struct pollfd fds[1];
        fds[0].fd = fd;
        fds[0].events = POLLIN;
        
        while (1)
        {
            ret = poll(fds,1,10);

            if (ret <= 0)
            {
                continue;
            }
            
            ret = read(fd, events, sizeof(events));
            
            int nevents = ret / sizeof(events[0]);

            for(i = 0; i < nevents; i  )
            {
                switch (events[i].type)
                {
                case GADGETFS_CONNECT:
                        printf("EP0 CONNECTn");
                    break;
                case GADGETFS_DISCONNECT:
                        printf("EP0 DISCONNECTn");
                        return 0;
                    break;
                case GADGETFS_SETUP:
                        printf("EP0 SETUPn");                
                        handle_setup_request(fd, amp;(events[i].u.setup));
                    break;
                case GADGETFS_NOP:
                case GADGETFS_SUSPEND:
                default:
                    printf("NOP %d n", events[i].type);
                    return 0;
                    break;

                }
            }
        }
    }


    void handle_setup_request(int fd, struct usb_ctrlrequest *setup)
    {
        uint8_t buffer[512];
        
        int ret = 0;

        if((setup->bRequestType amp; USB_DIR_IN) == 0)
        {
            if(setup->wLength)
            {
                ret = read(fd, buffer, setup->wLength);
                printf("Setup Read  %d / %d   n", ret, setup->wLength);
                //ret equals wLength but content of buffer is only sometimes correct
            }
        }
        
        .
        .
        .
        
    }