1.版本:LIBUSB 1.x
2.HID的數據傳輸方式,通常是中斷模式。
3.bEndpointAddress : 0x81 (Direction=IN EndpointID=1)
這個屬性纔是讀取的節點。usb->pc
4.bEndpointAddress : 0x02 (Direction=OUT EndpointID=2)
pc->usb
5. bInterval 查詢頻率,ms,
必須手動創建查詢線程 才能實現異步讀取操作
6.熱插拔回調
USB搖桿訪問成功!
找到USB設備 !
端口號: 6e
總線號: 1
bDescriptorType: 4
bEndpointAddress: 02h
傳輸類型: 03h
wMaxPacketSize: 64
傳輸速率: 10 ms
static libusb_device_handle* g_usb_handle;
static libusb_context *ctx;
static libusb_interface_descriptor *describe;
static libusb_transfer *main_transfer;
/// 熱插拔回調事件
void hotplugin(){
while (1) {
libusb_handle_events_completed(ctx, NULL);
std::this_thread::sleep_for( std::chrono::milliseconds(1000) ) ;
}
}
static int LIBUSB_CALL
usb_arrived_callback(struct libusb_context *_ctx, struct libusb_device *dev,
libusb_hotplug_event event, void *userdata)
{
struct libusb_device_handle *handle;
struct libusb_device_descriptor desc;
unsigned char buf[512];
int rc;
libusb_get_device_descriptor(dev, &desc);
// printf("Add usb device: \n");
// printf("\tCLASS(0x%x) SUBCLASS(0x%x) PROTOCOL(0x%x)\n",desc.bDeviceClass, desc.bDeviceSubClass, desc.bDeviceProtocol);
// printf("\tVENDOR(0x%x) PRODUCT(0x%x)\n", desc.idVendor, desc.idProduct);
if((desc.idVendor == user_device.idVendor) && (desc.idProduct == user_device.idProduct)){
g_usb_handle = libusb_open_device_with_vid_pid(NULL, user_device.idVendor, user_device.idProduct);
int ret = 0;
struct libusb_config_descriptor *config;
ret = libusb_get_config_descriptor(dev, 0, &config);
if (LIBUSB_SUCCESS != ret) {
printf("不能獲取設備描述符\n");
}
user_device.outEndPoint = (config->interface->altsetting->endpoint->bEndpointAddress & 0x07);
describe = const_cast<libusb_interface_descriptor*>(config->interface->altsetting);
printf(" 端口號: %0x\n", libusb_get_device_address(dev));
printf(" 總線號: %0x\n", libusb_get_bus_number(dev));
printf(" bDescriptorType: %d\n", config->interface->altsetting->bDescriptorType);
printf(" bEndpointAddress: %02xh\n", config->interface->altsetting->endpoint->bEndpointAddress);
printf(" 傳輸類型: %02xh\n", config->interface->altsetting->endpoint->bmAttributes);
printf(" wMaxPacketSize: %d\n", config->interface->altsetting->endpoint->wMaxPacketSize);
printf(" 傳輸速率: %d ms\n", config->interface->altsetting->endpoint->bInterval);
user_device.ms_Request = config->interface->altsetting->endpoint->bInterval;
//libusb_free_config_descriptor(config);
if(g_usb_handle == NULL) {
qWarning("拒絕訪問USB設備!\n");
qWarning("請USB檢查驅動,權限!\n");
user_device.isOpen= false;
return -1;
}else {
user_device.isOpen= true;
qDebug()<<"USB搖桿訪問成功!";
}
}else {
return 0;
rc = libusb_open(dev, &handle);
if (LIBUSB_SUCCESS != rc) {
printf("Could not open USB device\n");
return 0;
}
memset(buf, 0, sizeof(buf));
rc = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, buf, sizeof(buf));
if (rc < 0) {
printf("Get Manufacturer failed\n");
} else {
printf("\tManufacturer: %s\n", buf);
}
memset(buf, 0, sizeof(buf));
rc = libusb_get_string_descriptor_ascii(handle, desc.iProduct, buf, sizeof(buf));
if (rc < 0) {
printf("Get Product failed\n");
} else {
printf("\tProduct: %s\n", buf);
}
memset(buf, 0, sizeof(buf));
rc = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, buf, sizeof(buf));
if (rc < 0) {
printf("Get SerialNumber failed\n");
} else {
printf("\tSerialNumber: %s\n", buf);
}
libusb_close(handle);
}
return 0;
}
static int LIBUSB_CALL
usb_left_callback(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event, void *userdata)
{
struct libusb_device_descriptor desc;
libusb_get_device_descriptor(dev, &desc);
printf("Remove usb device: CLASS(0x%x) SUBCLASS(0x%x) iSerialNumber(0x%x)\n",
desc.bDeviceClass, desc.bDeviceSubClass, desc.iSerialNumber);
return 0;
}
int LibUSBControl::init_libusb(void)
{
libusb_hotplug_callback_handle usb_arrived_handle;
libusb_hotplug_callback_handle usb_left_handle;
libusb_hotplug_flag flag = static_cast<libusb_hotplug_flag>(1);
int rv = 0;
rv = libusb_init(&ctx);
rv = libusb_hotplug_register_callback(ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
flag, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY, usb_arrived_callback, NULL, &usb_arrived_handle);
if (LIBUSB_SUCCESS != rv) {
printf("註冊USB熱插拔失敗! \n");
libusb_exit(ctx);
return EXIT_FAILURE;
}
rv = libusb_hotplug_register_callback(ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
flag, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY, usb_left_callback, NULL, &usb_left_handle);
if (LIBUSB_SUCCESS != rv) {
printf("註冊USB熱插拔失敗! \n");
libusb_exit(ctx);
return EXIT_FAILURE;
}
libusb_hotplug_deregister_callback(ctx, usb_arrived_handle);
libusb_hotplug_deregister_callback(ctx, usb_left_handle);
auto th = new std::thread(hotplugin);
th->detach();
return rv;
}
6.usb初始化
int LibUSBControl::openDevice(int pid, int vid)
{
user_device.idProduct = pid;
user_device.idVendor = vid ;
int ret = init_libusb();
user_device.outEndPoint = 0x00;
ret = libusb_kernel_driver_active(g_usb_handle, user_device.outEndPoint);
if(ret == 1){
/// 卸載驅動
ret = libusb_detach_kernel_driver(g_usb_handle, user_device.outEndPoint);
if(ret < 0){
qDebug("libusb libusb_detach_kernel_driver_np #0: %s", libusb_error_name(ret));
}
}
/// 爲指定的設備申請接口,bInterfaceNumber
if ((ret=libusb_claim_interface(g_usb_handle, user_device.outEndPoint)) < 0) { //設置usb設備接口爲0
qDebug("error claiming interface #0: %s", libusb_error_name(ret));
}
/// 後臺去查
std::thread([this](){
while (user_device.isOpen) {
thread_callback();
std::this_thread::sleep_for( std::chrono::milliseconds(user_device.ms_Request) ) ;
}
}).detach();
return ret;
}
7.數據讀取
/// 後臺線程查詢中斷
void LibUSBControl::thread_callback()
{
int length ,rv= 0;
UC _readbuff[HID_PROTO_LEN];
memset(_readbuff,0,sizeof(_readbuff));
//讀中斷端點1,HID,此3D搖桿使用中斷讀取模式
rv=libusb_interrupt_transfer(g_usb_handle,HID_ENDPOINT_IN,_readbuff,sizeof(_readbuff),&length,0);
if((rv < 0)){
qDebug()<<libusb_error_name(rv);
}else {
std::string recv;
for(int i = 0;i < sizeof(_readbuff);i++){
recv.push_back(UC(_readbuff[i]));
}
_sigUpdate(recv);
}
}