代码跟随,以及程序输出。
我做了以下重现此问题的测试代码。这是对led板的测试(我写点东西,板上使led发光)。该问题并非特定于此硬件,我在其他硬件上具有相同的行为。实际的代码是分层的并且更好,但是表现出相同的行为。
情况1: 我连接了硬件并启动程序,它显示了提供的输出。仅在我事先连接硬件的情况下,它才会执行应该执行的操作。后续的拆装操作在设备上失败(例如,没有LED指示灯)。
情况2: 如果我启动程序并随后连接硬件,也会发生同样的情况。在这种情况下,它永远不会起作用。
我不是从根本上了解一些东西。情况1在第一次“运行”时如何没有附加内核驱动程序,而在随后的“运行”中却有一个内核驱动程序呢?我已经尝试过(很多)注释掉有关内核驱动程序的代码,将命令序列移到不可用...
请问我的错误在哪里?如果可能的话,请解释一下,因为我迷路了...
#include <stdlib.h>
#include <stdio.h>
#include <thread>
#include <iostream>
#include "libusb-1.0/libusb.h"
class test {
public:
int done = 0;
int rc = 0;
test() {
init();
}
virtual ~test() {
shutdown();
}
private:
const static uint8_t umRequestType = 0x21;
const static uint8_t umRequest = 9;
const static uint16_t umValue = 0x0200;
const static unsigned int umTimeout = 2000;
const static int interface = 0; //test board's interface
libusb_device_handle *handle = NULL;
int init() {
libusb_hotplug_callback_handle hp[2];
int product_id, vendor_id, class_id;
int rc;
vendor_id = 0xd209;
product_id = 0x1401;
class_id = LIBUSB_HOTPLUG_MATCH_ANY;
rc = libusb_init(NULL);
if (rc < 0) {
printf("failed to initialise libusb: %s\n", libusb_error_name(rc));
}
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
printf("Hotplug capabilites are not supported on this platform\n");
libusb_exit(NULL);
}
rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, LIBUSB_HOTPLUG_ENUMERATE, vendor_id,
product_id, class_id, static_hotplug_callback, this, &hp[0]);
if (LIBUSB_SUCCESS != rc) {
fprintf(stderr, "Error registering callback 0\n");
libusb_exit(NULL);
}
rc = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, vendor_id,
product_id, class_id, static_hotplug_callback_detach, this, &hp[1]);
if (LIBUSB_SUCCESS != rc) {
fprintf(stderr, "Error registering callback 1\n");
libusb_exit(NULL);
}
}
void shutdown() {
if (handle) {
libusb_close(handle);
}
libusb_exit(NULL);
}
static int LIBUSB_CALL static_hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) {
return reinterpret_cast<test *>(user_data)->hotplug_callback(ctx, dev, event, user_data);
}
int hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) {
struct libusb_device_descriptor desc;
(void) ctx;
(void) dev;
(void) event;
(void) user_data;
rc = libusb_get_device_descriptor(dev, &desc);
if (LIBUSB_SUCCESS != rc) {
fprintf(stderr, "Error getting device descriptor\n");
}
printf("Device attached: %04x:%04x\n", desc.idVendor, desc.idProduct);
rc = libusb_open(dev, &handle);
if (LIBUSB_SUCCESS != rc) {
fprintf(stderr, "Error opening device\n");
}
rc = libusb_kernel_driver_active(handle, interface);
printf("libusb_kernel_driver_active returned %d\n",rc);
if (rc == 1) { //find out if kernel driver is attached
printf("A kernel driver is active\n");
rc = libusb_detach_kernel_driver(handle, interface);
if (rc != LIBUSB_SUCCESS) {
printf("libusb_detach_kernel_driver() failed: %s - %d\n",libusb_error_name(rc),libusb_strerror((libusb_error) rc));
return false;
} else {
printf("detached kernel driver\n");
}
}
rc = libusb_set_configuration(handle, 1);
printf("libusb_set_configuration returned %d\n",rc);
if (handle) {
rc = libusb_set_auto_detach_kernel_driver(handle, 1);
if (rc != LIBUSB_SUCCESS) {
printf("libusb_set_auto_detach_kernel_driver() failed: %s - %d\n",libusb_error_name(rc),libusb_strerror((libusb_error) rc) );
} else {
printf("libusb_set_auto_detach_kernel_driver() has been set\n");
}
}
rc = libusb_claim_interface(handle, interface);
if (rc != LIBUSB_SUCCESS) {
printf("libusb_claim_interface() failed: %s - %d\n",libusb_error_name(rc),libusb_strerror((libusb_error) rc));
return false;
}
//get the bConfigurationValue
int config = 0;
rc = libusb_get_configuration(handle, &config);
std::cout << "libusb_get_configuration returned " << rc << "\n";
std::cout << "config value is " << config << "\n";
if (handle) {
std::array<unsigned char, 2> data{0x00, 0xff};
auto byteCount = libusb_control_transfer(handle, umRequestType, umRequest, umValue, interface, &data[0], data.size(), umTimeout);
printf("#bytes written to board: %d\n", data.size());
libusb_close(handle);
handle = NULL;
}
done++;
return 0;
}
static int LIBUSB_CALL static_hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) {
return reinterpret_cast<test *>(user_data)->hotplug_callback_detach(ctx, dev, event, user_data);
}
int hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) {
(void) ctx;
(void) dev;
(void) event;
(void) user_data;
printf("Device detached\n");
if (handle) {
libusb_close(handle);
handle = NULL;
}
done++;
return 0;
}
};
int main(int argc, char *argv[]) {
std::unique_ptr<test> testClass1 = std::make_unique<test>();
while (testClass1->done < 5) {
printf("#evens: %d\n",testClass1->done);
if (libusb_handle_events_completed(nullptr, nullptr) != LIBUSB_SUCCESS)
printf("libusb_handle_events() failed: %s\n", libusb_error_name(testClass1->rc));
std::this_thread::sleep_for(std::chrono::microseconds(1000000));
}
//the end
}
程序输出情况1:
/home/****/CLionProjects/usbdebugpoc/cmake-build-debug/usbdebugpoc
Device attached: d209:1401
libusb_kernel_driver_active returned 0
libusb_set_configuration returned 0
libusb_set_auto_detach_kernel_driver() has been set
libusb_get_configuration returned 0
config value is 1
#bytes written to board: 2
#evens: 1
Device detached
#evens: 2
Device attached: d209:1401
libusb_kernel_driver_active returned 1
A kernel driver is active
detached kernel driver
libusb_set_configuration returned 0
libusb_set_auto_detach_kernel_driver() has been set
libusb_get_configuration returned 0
config value is 1
#bytes written to board: 2
#evens: 3
Device detached
#evens: 4
Device attached: d209:1401
libusb_kernel_driver_active returned 1
A kernel driver is active
detached kernel driver
libusb_set_configuration returned 0
libusb_set_auto_detach_kernel_driver() has been set
libusb_get_configuration returned 0
config value is 1
#bytes written to board: 2
Process finished with exit code 0