LibUSB C ++ Формат передачи USB отличается - PullRequest
0 голосов
/ 23 октября 2018

Я давно использую переполнение стека, и большинство проблем, решение которых уже доступно.Это первый раз, когда я действительно не могу понять это с помощью Интернета.Я надеюсь, что у кого-то есть ответ на следующую проблему.

Введение В настоящее время я работаю над проектом, который должен быть способен выполнить команду и действовать в соответствии с ее ответом.Этот проект выполняется в системе на основе Debian в консольном приложении c ++.Чтобы иметь возможность выполнять такие команды, я попытался использовать библиотеку LibUSB .

Проблема Всякий раз, когда отправляются пакеты, он не возвращает действительный ответ, как описанов документации оборудования.доступен инструмент по умолчанию, который запускает команду callibration, я прослушал эти пакеты с помощью Wireshark , но структура вызовов прерываний OUT для инструмента callibration отличается от сгенерированной LibUSB, поэтому (я думаю) вызываеткоманда не должна быть выполнена.

В документации представлена ​​одна из следующих команд, которая должна выполнить диагностическую проверку, которая возвращает 5 байтов данных.

[0] Header: 0x02   
[1] Command: 0x4C  
[2] Byte to send: 0x02 (N bytes to send, Argument + data size)   
[3] Argument: 0x09  
[4] Data: 0x00

Ответ должен иметь следующий формат:

[0] Header: 0x02  
[1] Command: 0x4C  
[2] Byte to send: 0x03 (N bytes to send, Argument + data size)  
[3] Argument: 0x09  
[4] Processing result: D-1  
[5] Diagnostic result: D-2

D-1 : либо 0x01: нормальное, либо 0x00 Ошибка D-2 : либо 0x00: нормальное или нет 0x00, связанный код ошибки.

Испытанные вещи

  • Типы передачи:
    • Синхронный:
    • Libusb_bulk_transfer
    • Libusb_control_transfer
    • libusb_interrupt_transfer
    • Асинхронный:
    • Libusb_fill_bulk_transfer
    • Libusb_fill_control_transf_t_5_51_transf_5pt_transfer

Я пробовал обе асинхронные синхронные реализации библиотеки LibUSB.Передача управления Я попытался случайным образом переключить переменные после того, как наиболее логичные способы их заполнения закончились, но безуспешно, как и следовало ожидать.Поскольку результаты, обнаруженные при перехвате пакетов, четко указывают на то, что выполняются вызовы INTERRUPT.

Интерфейсы: Аппаратное обеспечение имеет два интерфейса.Интерфейс 0, который содержит OUT 0x02 и IN 0x81, и интерфейс 1, который содержит OUT 0x04 и IN 0x83.Обнаружение прерывания USB-вызова на устройство, запускаемое инструментом, при условии, что интерфейс 1 используется для команды диагностики.(Также пробовал интерфейс 0 как с IN, так и с OUT, не смог заставить его работать.

Обнаружение пакетов с помощью Wireshark

Результаты запроса и ответа об обнаружении пакетов, сгенерированных с помощью инструментария: IMG: прерывание OUT (я отметил бит, где команда фактически предоставляется) IMG: прерывание IN-ответ Этот код фактически работает и возвращает ожидаемый набор данных в своем слоте данных (как описановыше, формат возврата правильный, 0x01 и 0x00).

Запрос и ответ, сгенерированные с помощью LibUSB с использованием кода: IMG: прерывание OUT IMG: прерывание IN ответ

Да, я также попытался установить максимальный размер буфера для оборудования, равный 64. К сожалению, не сработал. Как видно, оба запроса сильно отличаются, использую ли я неправильную передачуметод? Это другой поддерживаемый формат, в котором вы можете отправлять команды?

Используемый фрагмент кода: фрагмент кода немного устарел, я пытался переписывать / редактировать его несколько раз,последние реализации используются из онлайн-примеров.

#define USB_VENDOR_ID       <VENDOR_ID>/* USB vendor ID used by the device
                                         * 0x0483 is STMs ID
                                         */
#define USB_PRODUCT_ID      <PRODUCT_ID>      /* USB product ID used by the device */
#define USB_ENDPOINT_IN     (LIBUSB_ENDPOINT_IN  | 0x83)   /* endpoint address */
#define USB_ENDPOINT_OUT    (LIBUSB_ENDPOINT_OUT | 0x04)   /* endpoint address */
#define USB_TIMEOUT         3000        /* Connection timeout (in ms) */
#define INTERFACE_NO        1

static libusb_context *ctx = NULL;
static libusb_device_handle *handle;

static uint8_t receiveBuf[64];
uint8_t transferBuf[64];

uint16_t counter=0;


int main(int argc, char **argv) {
    libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
    libusb_device_handle *dev_handle; //a device handle
    libusb_context *ctx = NULL; //a libusb session
    int r; //for return values
    ssize_t cnt; //holding number of devices in list
    r = libusb_init(&ctx); //initialize the library for the session we just declared
    if(r < 0) {
        qDebug()<<"Init Error "<<r<<endl; //there was an error
        return 1;
    }
    libusb_set_debug(ctx, 4); //set verbosity level to 3, as suggested in the documentation

    cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
    if(cnt < 0) {
        qDebug()<<"Get Device Error"<<endl; //there was an error
        return 1;
    }
    qDebug()<<cnt<<" Devices in list."<<endl;

    dev_handle = libusb_open_device_with_vid_pid(ctx, 0x0AFA, 0x7D3); //these are vendorID and productID I found for my usb device
    if(dev_handle == NULL)
        qDebug()<<"Cannot open device"<<endl;
    else
        qDebug()<<"Device Opened"<<endl;
    libusb_free_device_list(devs, 1); //free the list, unref the devices in it

    unsigned char *data = new unsigned char[5] { 0x02, 0x4C, 0x02, 0x09, 0 }; //data to write
    data[0]= 0x02;data[1]= 0x4C;data[2]=0x02;data[3]=0x09; data[4]= 0; //some dummy values

    int actual; //used to find out how many bytes were written
    if(libusb_kernel_driver_active(dev_handle, INTERFACE_NO) == 1) { //find out if kernel driver is attached
        qDebug()<<"Kernel Driver Active"<<endl;
        if(libusb_detach_kernel_driver(dev_handle, INTERFACE_NO) == 0) //detach it
            qDebug()<<"Kernel Driver Detached!"<<endl;
    }
    r = libusb_claim_interface(dev_handle, INTERFACE_NO); //claim interface 0 (the first) of device (mine had jsut 1)
    if(r < 0) {
        qDebug()<<"Cannot Claim Interface"<<endl;
        return 1;
    }
    qDebug()<<"Claimed Interface"<<endl;

    for(int i = 0; i != sizeof(data); i++) {
        fprintf(stderr, "[%d] - %02x\n", i, data[i]);
    }
    qDebug()<<"Writing Data..."<<endl;
    r = libusb_bulk_transfer(dev_handle, (USB_ENDPOINT_OUT | LIBUSB_ENDPOINT_OUT), data, sizeof(data), &actual, 0); //my device's out endpoint was 2, found with trial- the device had 2 endpoints: 2 and 129
    if(r == 0 && actual == sizeof(data)) //we wrote the 4 bytes successfully
        qDebug()<<"Writing Successful!"<<endl;
    else
        qDebug()<<"Write Error"<<endl;
        fprintf(stderr, "Error Writing: %s", libusb_strerror(static_cast<libusb_error>(r)));

    r = libusb_release_interface(dev_handle, INTERFACE_NO); //release the claimed interface
    if(r!=0) {
        qDebug()<<"Cannot Release Interface"<<endl;
        return 1;
    }
    qDebug()<<"Released Interface"<<endl;

    libusb_close(dev_handle); //close the device we opened
    libusb_exit(ctx); //needs to be called to end the

    delete[] data; //delete the allocated memory for data
    return 0;
}

Я надеюсь, что есть кто-то, способный и готовый помочь мне здесь, потому что я работал над этим в течение трех дней подряд и до сих пор укрылсяне получил логическое решение этой проблемы.

Заранее спасибо!

~ Mark

1 Ответ

0 голосов
/ 24 октября 2018

Спасибо за ваш ответ!Я в настоящее время нашел решение проблемы!Это не имело ничего общего с использованием обоих C / C ++.Извините за то, что код немного грязный.Я написал это несколько раз, чтобы аккуратность не была моим приоритетом, хотя я буду помнить об этом для возможного будущего поста в StackOverflow.Несмотря на то, что я решил проблему, я добавил результаты прослушивания обоих входящих и исходящих пакетов, надеясь, что это может помочь другим в решении одной и той же проблемы.

Ну, в чем проблема?
Итак,захват инструмента показал, что последний 64-битный является полезной нагрузкой запроса и его данных, это как для OUT, так и для IN.(Как видно на изображениях, которые теперь фактически представлены), и, как я уже говорил, я попытался выделить массивы размером 64 и задать первые несколько слотов данными, необходимыми для операции.Что касается других слотов, они были заполнены остатками, расположенными по этим выделенным адресам памяти.

Что я сделал, чтобы исправить это
Итак, я сделал следующее.После инициализации массива и присвоения ему размера 64 я установил все выделенные слоты на 0 с помощью команды memset, чтобы массив был полностью очищен от оставшихся данных.Это оставило мне чистый массив, в котором я мог установить переменные, необходимые для команды, которую я хотел отправить.(См. Следующий фрагмент)

// Initialize array of 64 bytes.
    uint8_t *data = new uint8_t[64];
    memset(data, 0x00, 64);
    data[0] = 0x02; data[1] = 0x4C; data[2] = 0x01; data[3] = 0x17;

Я немного прибрал код, чтобы обеспечить лучшую читаемость, вот код, который я использовал, который работает!Надеюсь, другие найдут эту информацию полезной.

//*** DEPENDENCIES *************************************************************
// QT
#include <QCoreApplication>
#include <QtCore/QDebug>
// Others
#include <libusb.h>
#include <iostream>


//*** VARIABLES ****************************************************************
#define USB_VENDOR_ID      <VENDOR_ID_GOES_HERE>
#define USB_PRODUCT_ID     <PRODUCT_ID_GOES_HERE>
#define USB_ENDPOINT_OUT    0x04
#define USB_ENDPOINT_IN     0x83

#define INTERFACE_NO        0x01

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    libusb_device *dev;
    libusb_device_handle *dev_handle;
    libusb_context *ctx = NULL;


    //*** INITIALIZATION *******************************************************
    uint r = libusb_init(&ctx);
    // Check if initiated succesfully
    if ( r < 0 )                            { qDebug() << "Init error."; return 1; }
    libusb_set_debug(ctx, 4);

    dev_handle = libusb_open_device_with_vid_pid(ctx, USB_VENDOR_ID, USB_PRODUCT_ID);

    if (dev_handle == NULL) { qDebug() << "Could not open device."; return 1;}
    qDebug() << "Device opened succesfully!";


    // Check if kernel driver, detach
    if(libusb_kernel_driver_active(dev_handle, INTERFACE_NO) == 1) {
            qDebug() << "Kernel Driver Active";
            if(libusb_detach_kernel_driver(dev_handle, INTERFACE_NO) == 0) {
               qDebug() << "Kernel Driver Detached";
        }
    }

    // Claim interface
    r = libusb_claim_interface(dev_handle, INTERFACE_NO);
    if ( r < 0 ) {
        qDebug() << "Could not claim interface.";
        return 1;
    }
    qDebug() << "Interface claimed.";


    //*** EXECUTION OF USB TRANSFERS *******************************************

    // Prepare command
    int actual_written;
    // Initialize array of 64 bytes.
    uint8_t *data = new uint8_t[64];
    memset(data, 0x00, 64);
    data[0] = 0x02; data[1] = 0x4C; data[2] = 0x01; data[3] = 0x17;

    qDebug() << "================= OUT ==============================";
    //*** ATTEMPT TO WRITE COMMAND *********************************************
    r = libusb_bulk_transfer(dev_handle,
                             USB_ENDPOINT_OUT,
                             data, 64,
                             &actual_written,
                             10000);

    qDebug() << "OUT status: " << libusb_strerror(static_cast<libusb_error>(r));
    if (r == 0 && actual_written == 64) {
        qDebug() << "Succesfully written!";
    } else {
        qDebug() << "||" << r << "||"<< actual_written << "||"
                 << "Could not write.";
    }
    qDebug() << "================== IN ===============================";


    //*** ATTEMPT TO READ FEEDBACK *********************************************
    // Initialize array of 64 bytes.
    uint8_t *feedback = new uint8_t[64];
    memset(feedback, 0x00, 64);

    int actual_received;
    r = libusb_bulk_transfer(
                dev_handle,
                USB_ENDPOINT_IN,
                feedback,
                64,
                &actual_received,
                0);

    qDebug() << "IN status: " << libusb_strerror(static_cast<libusb_error>(r));
   if(r == 0 && actual_received == 64) {
            qDebug("\nRetrieval successful!");
            qDebug("\nSent %d bytes with string: %s\n", actual_received, feedback);
    } else {
       qDebug() << actual_received << "||" <<feedback << "||"
                << "Could not read incoming data. ||";
   }

    for( int m = 0; m < 64; m++)
    {
        fprintf(stderr, "[%d] - %02x\n", m, feedback[m]);
    }

    if (feedback[4] != 0x01) {
        qDebug() << "Unsuccesful offset adjustment.";
        return -1;
    }

    // Further code should go here.

    //*** FREEING USB **********************************************************
    // Releasing interface
    r = libusb_release_interface(dev_handle, INTERFACE_NO);
    if ( r < 0 )        { qDebug() << "Could not release interface."; return 1; }
    qDebug() << "Interface released.";

    libusb_close(dev_handle);
    libusb_exit(ctx);
    delete[] data;
    delete[] feedback;


    qDebug() << "End of main";
    return 0;
}

Томас и Дэвид, большое спасибо!

~ Mark

...