Ошибка при использовании «user_data» в обратном вызове libusb_fill_interrupt_transfer - PullRequest
0 голосов
/ 18 сентября 2018

Я использую libusb-1.0 для сопряжения ключа BLE с RCU.

Для этого я успешно пишу запрос на сопряжение в интерфейс ключа.Чтобы прослушать ответ ключа, я использую функцию libusb_fill_interrupt_transfer и передаю обратный вызов, который будет выполнен при получении ответа.Эта функция принимает параметр, упомянутый в документации (void *user_data), который можно использовать при обратном вызове.Но когда я пытаюсь использовать этот параметр, я получаю ошибку компиляции.

undeclared (первое использование в этой функции)

После вызова предыдущей функции иобъявление моего обратного вызова:

libusb_fill_interrupt_transfer(pairing->transfer, dctx->devh, 0x84, pairing->buffer,
    sizeof(pairing->buffer), cb_aknowledgement, pairing, 0);

static void cb_aknowledgement(struct libusb_transfer *transfer)
{
    if (pairing->transfer->status != LIBUSB_TRANSFER_COMPLETED) {
        printf( "img transfer status %d?\n", pairing->transfer->status);
        libusb_free_transfer(pairing->transfer);
        pairing->transfer = NULL;
        return;
    }

    if(pairing->buffer[0]!=0x05 || pairing->buffer[1]!=0x21)
    {
        printf( "wrong command recieved\n");
        libusb_free_transfer(pairing->transfer);
        pairing->transfer = NULL;
        return;
    }

    printf("I've read data  \n");
    printf("USB Report Id           =  0x%x \n",pairing->buffer[0]);
    printf("Command                 =  0x%x \n",pairing->buffer[1]);
    printf("Acknowledgement type    =  0x%x \n",pairing->buffer[2]);
    return ;
}

Вопрос: как я могу использовать user_data, который я передал в качестве параметра для обратного вызова?

1 Ответ

0 голосов
/ 18 сентября 2018

Используйте transfer->user_data.Из структуры libusb_transfer doc :

Поля данных
void * user_data
Данные контекста пользователя для передачи в функцию обратного вызова.

Я не знаю, какой тип pairing, но это выглядело бы так:

int main() {
   ...
   struct pairing_type_s *pairing = pairing_init();
   ...
   libusb_fill_interrupt_transfer(pairing->transfer, dctx->devh, 0x84, pairing->buffer,
    sizeof(pairing->buffer), cb_aknowledgement, pairing, 0);
    ...
}

// Then later:

static void cb_aknowledgement(struct libusb_transfer *transfer)
{
     assert(transfer != NULL);
     struct pairing_type_s *pairing = transfer->user_data;
     assert(pairing != NULL);
     // use pairing like a pro
     ...
}

Но вы также можете быть более профессионалом, если вы убедитесь, чтоВы всегда вызываете libusb_fill_interrupt_transfer с pairing->transfer с cb_aknowledgement и используете макрос container_of:

int main() {
   ...
   struct pairing_type_s *pairing = pairing_init();
   ...
   libusb_fill_interrupt_transfer(pairing->transfer, dctx->devh, 0x84, pairing->buffer,
    sizeof(pairing->buffer), cb_aknowledgement, NULL, 0);
    ...
}

// Then later:

static void cb_aknowledgement(struct libusb_transfer *transfer)
{
     assert(transfer != NULL);
     struct pairing_type_s *pairing = container_of(transfer, struct pairing_type_s, transfer);
     assert(pairing != NULL);
     // use pairing like a pro
     ...
}

Но я бы предпочел первый метод в этом случае, так как он более читабелен и более безошибочен.

...