483 lines
14 KiB
C++
483 lines
14 KiB
C++
|
#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
|