qt-correction-tool/hgdev/libusbex.cpp

483 lines
14 KiB
C++
Raw Normal View History

2022-06-28 01:24:29 +00:00
#pragma once
#include "libusbex.h"
#include <thread>
#include <iostream>
using namespace std;
#ifdef WIN32
#ifdef __cplusplus
FILE iob[] = { *stdin, *stdout, *stderr };
extern "C" {
FILE* __cdecl _iob(void) { return iob; }
}
#endif
#endif
#ifdef __linux__
class LibusbContext
{
public:
LibusbContext()
:ctx(0)
{
libusb_init(&ctx);
//libusb_set_debug(ctx,LIBUSB_LOG_LEVEL_DEBUG);
}
~LibusbContext()
{
libusb_exit(ctx);
}
libusb_context* ctx;
};
class Libusb_device_handle
{
public:
Libusb_device_handle()
: ldh(0)
, start_callback(false)
, isconnected(false)
, m_usbcallback(0)
, usrdata(0)
{
if (!ctxa.get()) {
ctxa.reset(new LibusbContext);
}
}
~Libusb_device_handle()
{
std::cout<<"~Libusb_device_handle enter"<<std::endl;
close();
std::cout<<"~Libusb_device_handle exit"<<std::endl;
}
int open(uint16_t vendor_id, uint16_t product_id)
{
std::cout<<"Libusb_device_handle enter"<<std::endl;
if (ldh != 0) {
close();
return -1;
}
if (!start_callback) {
int ret = libusb_hotplug_register_callback(ctxa->ctx,
(libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
(libusb_hotplug_flag)LIBUSB_HOTPLUG_ENUMERATE,
product_id, // vid
product_id, // pid
LIBUSB_HOTPLUG_MATCH_ANY, // class
OnUsbHotplugCallback,
this,
&handle);
std::string errorinfo=ret==LIBUSB_SUCCESS?" success":"failed";
std::cout<<"Libusb_device_handle at libusb_hotplug_register_callback regist "<<errorinfo <<std::endl;
if(ret == LIBUSB_SUCCESS)
{
std::cout<<"Libusb_device_handle at libusb_hotplug_register_callback regist "<<errorinfo <<std::endl;
if (hotplug_thread.get() && hotplug_thread->joinable()) {
start_callback = false;
hotplug_thread->join();
}
start_callback=true;
hotplug_thread = shared_ptr<thread>(new thread(&Libusb_device_handle::loop, this));
std::cout<<"Libusb_device_handle at hotplug_thread "<<" start" <<std::endl;
}
else
{
ldh = libusb_open_device_with_vid_pid(ctxa->ctx, vendor_id, product_id);
if(ldh!=0)
{
libusb_claim_interface(ldh,0);
isconnected=true;
}
}
}
}
int open(libusb_device* dev) {
if (ldh != 0)
close();
struct libusb_device_descriptor desc;
int ret = libusb_get_device_descriptor(dev, &desc);
if (!start_callback) {
int ret = libusb_hotplug_register_callback(ctxa->ctx,
(libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
(libusb_hotplug_flag)LIBUSB_HOTPLUG_ENUMERATE,
desc.idVendor, // vid
desc.idProduct, // pid
LIBUSB_HOTPLUG_MATCH_ANY, // class
OnUsbHotplugCallback,
this,
&handle);
std::string errorinfo=ret==LIBUSB_SUCCESS?" success":"failed";
if(ret == LIBUSB_SUCCESS)
{
std::cout<<"Libusb_device_handle at libusb_hotplug_register_callback regist "<<errorinfo <<std::endl;
if (hotplug_thread.get() && hotplug_thread->joinable()) {
start_callback = false;
hotplug_thread->join();
}
start_callback=true;
hotplug_thread = shared_ptr<thread>(new thread(&Libusb_device_handle::loop, this));
std::cout<<"Libusb_device_handle at hotplug_thread "<<" start" <<std::endl;
}
else
{
ldh = libusb_open_device_with_vid_pid(ctxa->ctx, desc.idVendor, desc.idProduct);
if(ldh!=0)
{
libusb_claim_interface(ldh,0);
isconnected=true;
}
}
}
return 0;
}
bool is_open() {
return ldh&&isconnected;
}
int bulk_transfer(unsigned char endpoint, unsigned char* data, int length, int* actual_length, unsigned int timeout)
{
int ret= libusb_bulk_transfer(ldh, endpoint, data, length, actual_length, timeout);
if (ret != LIBUSB_SUCCESS) {
cout << "libusb error info :" << libusb_error_name(ret) << endl;
if(m_usbcallback&&usrdata){
m_usbcallback(3,usrdata);
}
}
return ret;
}
int int_transfer(unsigned char endpoint, unsigned char* data, int length, int* actual_length, unsigned int timeout)
{
int ret =libusb_interrupt_transfer(ldh, endpoint, data, length, actual_length, timeout);
if (ret != LIBUSB_SUCCESS) {
//cout << "libusb error info :" << libusb_error_name(ret) << endl;
if(ret != LIBUSB_ERROR_TIMEOUT)
{
if(m_usbcallback&&usrdata){
m_usbcallback(4,usrdata);
}
}
}
return ret;
}
int control_transfer(uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
unsigned char* data, uint16_t wLength, unsigned int timeout)
{
int ret = libusb_control_transfer(ldh, request_type, bRequest, wValue, wIndex, data, wLength, timeout);
if (ret != LIBUSB_SUCCESS) {
cout << "libusb error info :" << libusb_error_name(ret) << endl;
if(m_usbcallback&&usrdata){
//m_usbcallback(2,usrdata);
}
}
return ret;
}
void close()
{
// if (start_callback)
// {
// std::cout << "Stop" << std::endl;
// libusb_hotplug_deregister_callback(ctxa->ctx, handle);
// start_callback = false;
// hotplug_thread->join();
// hotplug_thread.reset();
// hotplug_thread = 0;
// }
if (ldh != 0)
{
libusb_release_interface(ldh, 0); //release the claimed interface
libusb_close(ldh);
ldh = 0;
}
if (start_callback)
{
std::cout << "close Stop enter" << std::endl;
libusb_hotplug_deregister_callback(ctxa->ctx, handle);
std::cout << "close Stop enter 1" << std::endl;
start_callback = false;
hotplug_thread->join();
std::cout << "close Stop enter 2" << std::endl;
//hotplug_thread->detach();
hotplug_thread = 0;
std::cout << "close Stop exit" << std::endl;
}
}
void set_report_callback(usbcallback usbcall, void *usrdata){
m_usbcallback=usbcall;
this->usrdata =usrdata;
}
private:
static int LIBUSB_CALL OnUsbHotplugCallback(struct libusb_context* ctx,
struct libusb_device* device,
libusb_hotplug_event event,
void* monitor) {
Libusb_device_handle* This = (Libusb_device_handle*)monitor;
return This->OnUsbHotplug(ctx, device, event);
}
int OnUsbHotplug(struct libusb_context* ctx,
struct libusb_device* device,
libusb_hotplug_event event)
{
struct libusb_device_descriptor descriptor;
int ret = libusb_get_device_descriptor(device, &descriptor);
if (LIBUSB_SUCCESS == ret)
{
std::cout << "Got a device: vid= " << std::hex << descriptor.idVendor << ",pid=" << descriptor.idProduct << std::endl;
}
switch (event) {
case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
isconnected = true;
ldh = libusb_open_device_with_vid_pid(ctxa->ctx, descriptor.idVendor, descriptor.idProduct);
if (ldh != 0) {
ret= libusb_claim_interface(ldh, 0);
if(ret==LIBUSB_SUCCESS){
if(m_usbcallback&&usrdata){
m_usbcallback(0,usrdata);
}
std::cout << "USBScanner claim_interface success" << std::endl;
}
else{
std::cout << "USBScanner arriverd and claim_interface failed" << std::endl;
}
}else{
std::cout << "USBScanner libusb_open_device_with_vid_pid failed" << std::endl;
}
break;
case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
isconnected = false;
std::cout << "USBScanner left" << std::endl;
if(m_usbcallback&&usrdata){
m_usbcallback(1,usrdata);
}
if(ldh!=0){
libusb_release_interface(ldh, 0); //release the claimed interface
libusb_close(ldh);
ldh = 0;
}
break;
default:
break;
}
return 0;
}
void loop() {
while (start_callback)
{
//libusb_handle_events_completed(ctxa->ctx, 0);
timeval tm={1,0};
auto ret=libusb_handle_events_timeout(ctxa->ctx,&tm);
if(ret<0)
printf("libusb_handle_events_timeout error %s\n",libusb_error_name(ret));
}
}
private:
libusb_device_handle* ldh;
std::shared_ptr<std::thread> hotplug_thread;
libusb_hotplug_callback_handle handle;
bool start_callback;
bool isconnected;
static std::shared_ptr<LibusbContext> ctxa;
usbcallback m_usbcallback;
void* usrdata;
};
std::shared_ptr<LibusbContext> Libusb_device_handle::ctxa = std::shared_ptr<LibusbContext>();
LibUsbEx::LibUsbEx(std::shared_ptr<Libusb_List> usblist, int index)
: m_usblist(usblist),
m_index(index)
{
// #if defined(G100SCANNER)||defined(G200SCANNER)
// eps[EP_INT_IN] = LIBUSB_ENDPOINT_IN + 2;
// eps[EP_BULK_IN] = LIBUSB_ENDPOINT_IN + 1;
// eps[EP_BULK_OUT] = LIBUSB_ENDPOINT_OUT + 1;
// #else
// eps[EP_INT_IN] = LIBUSB_ENDPOINT_IN + 3;
// eps[EP_BULK_IN] = LIBUSB_ENDPOINT_IN + 1;
// eps[EP_BULK_OUT] = LIBUSB_ENDPOINT_OUT + 2;
// #endif
timeout = 100;
}
bool LibUsbEx::open()
{
m_usb = m_usblist->open(m_index);
Usb_endpoint info = m_usblist->GetendpointInfo(m_index);
eps[EP_INT_IN] = info.int_in;
eps[EP_BULK_IN] = info.bulk_in;
eps[EP_BULK_OUT] = info.bulk_out;
return is_open();
}
bool LibUsbEx::close()
{
if (m_usb.get())
m_usb->close();
return true;
}
bool LibUsbEx::is_open()
{
return m_usb.get() && m_usb->is_open();
}
bool LibUsbEx::is_connected()
{
return m_usb.get() && m_usb->is_open();
}
void LibUsbEx::set_timeout(int timeout)
{
this->timeout = timeout;
}
int LibUsbEx::read_bulk(void* data, int len)
{
m_usb->bulk_transfer(eps[EP_BULK_IN], (unsigned char*)data, len, &len, timeout);
return len;
}
int LibUsbEx::write_bulk(void* data, int len)
{
m_usb->bulk_transfer(eps[EP_BULK_OUT], (unsigned char*)data, len, &len, timeout);
return len;
}
int LibUsbEx::read_int(void* data, int len)
{
m_usb->int_transfer(eps[EP_INT_IN], (unsigned char*)data, len, &len, timeout);
return len;
}
int LibUsbEx::control_msg(int rtype, int req, int value, int index, int len, void* data)
{
return m_usb->control_transfer(rtype, req, value, index, (unsigned char*)data, len, timeout);
}
void LibUsbEx::set_usbcallback(usbcallback usbcall, void *usrdata)
{
m_usb->set_report_callback(usbcall,usrdata);
}
Libusb_List::Libusb_List() :
Libusb_List(0, 0)
{
}
Libusb_List::Libusb_List(uint16_t vendor_id, uint16_t product_id)
{
std::cout<<vendor_id<<"+"<<product_id<<std::endl;
devs = 0;
std::cout<<"Libusb_List cnt:"<<111<<std::endl;
libusb_init(0);
ssize_t cnt = libusb_get_device_list(0, &devs);
libusb_device_descriptor desc;
std::cout<<"Libusb_List cnt:"<<cnt<<std::endl;
for (int i = 0; i < cnt; i++) {
int ret=libusb_get_device_descriptor(devs[i], &desc);
std::cout<<"vid :"<<desc.idVendor<<" pid:"<<desc.idProduct <<"ret :"<<ret<<std::endl;
if ((ret==LIBUSB_SUCCESS)&& (((desc.idVendor == vendor_id) && (desc.idProduct == product_id)) || (vendor_id == 0))) {
std::cout<<libusb_error_name(ret)<<std::endl;
std::cout<<"vid :"<<desc.idVendor<<" pid:"<<desc.idProduct <<"i :"<<i<<std::endl;
v_dev.push_back(devs[i]);
}
}
}
Libusb_List::~Libusb_List() {
close();
libusb_exit(0);
}
std::list<std::shared_ptr<IUsb>> Libusb_List::find_all()
{
std::list<std::shared_ptr<IUsb>> usblists;
std::shared_ptr<Libusb_List> libusblists(new Libusb_List());
for (int i = 0; i < libusblists->device_count(); i++)
usblists.push_back(std::shared_ptr<IUsb>(new LibUsbEx(libusblists, i)));
return usblists;
}
std::list<std::shared_ptr<IUsb>> Libusb_List::find_vid_pid(int vid, int pid)
{
std::cout<<"enter find_vid_pid"<<std::endl;
std::list<std::shared_ptr<IUsb>> usblists;
std::shared_ptr<Libusb_List> libusblists(new Libusb_List(vid, pid));
std::cout<<"vid "<<vid<<" pid="<<pid<<std::endl;
for (int i = 0; i < libusblists->device_count(); i++)
usblists.push_back(std::shared_ptr<IUsb>(new LibUsbEx(libusblists, i)));
return usblists;
}
int Libusb_List::device_count() {
return v_dev.size();
}
std::shared_ptr<Libusb_device_handle> Libusb_List::open(int index) {
if (v_dev[index] != 0) {
std::shared_ptr<Libusb_device_handle> dev(new Libusb_device_handle);
dev->open(v_dev[index]);
return dev;
}
return std::shared_ptr<Libusb_device_handle>();
}
void Libusb_List::close() {
std::cout<<"Libusb_List close enter"<<std::endl;
if (devs)
libusb_free_device_list(devs, 1);
std::cout<<"Libusb_List close exit"<<std::endl;
}
Usb_endpoint Libusb_List::GetendpointInfo(int index)
{
return GetendpointInfo(v_dev[index]);
}
Usb_endpoint Libusb_List::GetendpointInfo(libusb_device * device)
{
Usb_endpoint m_info(0,0,0);
struct libusb_config_descriptor *config;
int ret = libusb_get_config_descriptor(device, 0, &config);
if (LIBUSB_SUCCESS != ret) {
return m_info;
}
for(int i=0;i<config->interface->altsetting->bNumEndpoints;i++)
{
if(config->interface->altsetting->endpoint[i].bEndpointAddress & 0x80)
{
if((config->interface->altsetting->endpoint[i].bmAttributes&0x3) == 2)
m_info.bulk_in = config->interface->altsetting->endpoint[i].bEndpointAddress;
if((config->interface->altsetting->endpoint[i].bmAttributes&0x3) == 3)
m_info.int_in = config->interface->altsetting->endpoint[i].bEndpointAddress;
}
else {
if((config->interface->altsetting->endpoint[i].bmAttributes&0x3) == 2)
m_info.bulk_out = config->interface->altsetting->endpoint[i].bEndpointAddress;
}
}
libusb_free_config_descriptor(config);
return m_info;
}
#endif