2022-05-03 03:56:07 +00:00
# include "usb_manager.h"
2022-05-30 03:04:26 +00:00
# include "../wrapper/hg_log.h"
2022-05-03 03:56:07 +00:00
# include <iostream>
# define IF_CLASS(code, cls) \
if ( code = = cls ) \
return # cls ;
2022-07-18 08:56:03 +00:00
# if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
# include "scanner_manager.h"
2022-07-18 08:56:03 +00:00
# else
2022-05-03 03:56:07 +00:00
void memset ( void * buf , unsigned char fill , int len )
{
unsigned char * data = ( unsigned char * ) buf ;
while ( len - - > 0 )
* data + + = fill ;
}
# endif
usb_manager * usb_manager : : inst_ = NULL ;
uint8_t usb_manager : : uninit_uint8 = 0x0ff ;
usb_manager : : usb_manager ( ) : run_ ( true )
, usb_cb_handle_ ( NULL )
, usb_cb_ ( & usb_manager : : usb_event_handle ) , usb_cb_param_ ( NULL )
2022-05-17 07:04:55 +00:00
, context_ ( NULL ) , status_ ( SCANNER_ERR_OK )
2022-05-03 03:56:07 +00:00
, born_ ( std : : chrono : : system_clock : : now ( ) )
{
int ret = libusb_init ( & context_ ) ;
// libusb_set_log_cb(context_, &usb_manager::usb_log_callback, LIBUSB_LOG_CB_CONTEXT); // LIBUSB_API_VERSION >= 0x01000107
2022-05-30 03:04:26 +00:00
VLOG_MINI_4 ( LOG_LEVEL_DEBUG_INFO , " usb_manager(%s) libusb_init(%s) = %s, context = %s \n " , hg_log : : format_ptr ( this ) . c_str ( ) , hg_log : : format_ptr ( & context_ ) . c_str ( ) , libusb_error_name ( ret ) , hg_log : : format_ptr ( context_ ) . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
if ( ret )
2022-05-17 07:04:55 +00:00
status_ = SCANNER_ERR_USB_INIT_FAILED ;
2022-05-03 03:56:07 +00:00
wait_pnp_ . set_debug_info ( " Waiting PNP " ) ;
if ( ! usb_notify_thread_ . get ( ) )
{
run_ = true ;
usb_notify_thread_ . reset ( new std : : thread ( & usb_manager : : thread_notify_usb_event , this ) ) ;
}
}
usb_manager : : ~ usb_manager ( )
{
run_ = false ;
wait_pnp_ . notify ( ) ;
libusb_context * ctx = nullptr ;
2022-07-18 08:56:03 +00:00
# if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
ctx = context_ ;
libusb_quit ( ctx ) ;
# endif
if ( usb_cb_handle_ )
libusb_hotplug_deregister_callback ( ctx , usb_cb_handle_ ) ;
if ( usb_monitor_thread_ . get ( ) & & usb_monitor_thread_ - > joinable ( ) )
{
usb_monitor_thread_ - > join ( ) ;
usb_monitor_thread_ . reset ( ) ;
}
if ( usb_notify_thread_ . get ( ) & & usb_notify_thread_ - > joinable ( ) )
{
usb_notify_thread_ - > join ( ) ;
usb_notify_thread_ . reset ( ) ;
}
libusb_exit ( context_ ) ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " usb_manager(%s) destroying and free context(%s) \n " , hg_log : : format_ptr ( this ) . c_str ( ) , hg_log : : format_ptr ( context_ ) . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
}
int LIBUSB_CALL usb_manager : : usb_pnp_callback ( libusb_context * ctx , libusb_device * device , libusb_hotplug_event event , void * monitor )
{
usb_manager * obj = ( usb_manager * ) monitor ;
// if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)
2023-11-24 07:14:15 +00:00
//libusb_ref_device(device); // keep the object until handle it
2022-05-03 03:56:07 +00:00
//else if(event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
// libusb_unref_device(device);
return obj - > on_usb_pnp_event ( ctx , device , event ) ;
}
void usb_manager : : usb_event_handle ( usb_event ev , libusb_device * device , int vid , int pid , int usb_ver_h , int usb_ver_l , bool * retry , void * user ) // usb_ver_h.usb_ver_l
{
}
void usb_manager : : usb_log_callback ( libusb_context * ctx , libusb_log_level level , const char * str )
{
// used when LIBUSB_API_VERSION >= 0x01000107
if ( level = = LIBUSB_LOG_LEVEL_NONE | | LIBUSB_LOG_LEVEL_INFO | | LIBUSB_LOG_LEVEL_DEBUG )
{
2022-05-30 03:04:26 +00:00
LOG_INFO ( LOG_LEVEL_DEBUG_INFO , str ) ;
2022-05-03 03:56:07 +00:00
}
else
{
2022-05-30 03:04:26 +00:00
LOG_INFO ( LOG_LEVEL_FATAL , str ) ;
2022-05-03 03:56:07 +00:00
}
}
int usb_manager : : register_usb_pnp ( void )
{
libusb_context * ctx = nullptr ;
2022-07-18 08:56:03 +00:00
# if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
ctx = context_ ;
# endif
int ret = libusb_hotplug_register_callback ( ctx , ( libusb_hotplug_event ) ( LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT ) ,
( libusb_hotplug_flag ) LIBUSB_HOTPLUG_ENUMERATE ,
LIBUSB_HOTPLUG_MATCH_ANY , //LIBUSB_HOTPLUG_MATCH_ANY
LIBUSB_HOTPLUG_MATCH_ANY , //LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY ,
& usb_manager : : usb_pnp_callback ,
this ,
& usb_cb_handle_ ) ;
if ( ret ! = LIBUSB_SUCCESS )
{
2022-05-30 03:04:26 +00:00
LOG_INFO ( LOG_LEVEL_FATAL , ( std : : string ( " regist usbhotplug callback error msg: " ) + libusb_error_name ( ret ) + " \n " ) . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
usb_cb_handle_ = NULL ;
2022-05-17 07:04:55 +00:00
status_ = SCANNER_ERR_USB_REGISTER_PNP_FAILED ;
2022-05-03 03:56:07 +00:00
}
else
2022-05-17 07:04:55 +00:00
status_ = SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
return ret ;
}
void usb_manager : : init_notify_thread ( )
{
if ( ! usb_monitor_thread_ . get ( ) )
{
usb_monitor_thread_ . reset ( new std : : thread ( & usb_manager : : thread_trigger_usb_event , this ) ) ;
}
}
void usb_manager : : fake_usb_pnp ( std : : vector < libusb_device * > & devices )
{
libusb_device * * devs = NULL ;
libusb_get_device_list ( context_ , & devs ) ;
if ( devs )
{
std : : vector < libusb_device * > current ;
// handle arrived ...
for ( int ind = 0 ; devs [ ind ] ; + + ind )
{
std : : vector < libusb_device * > : : iterator it
= std : : find ( devices . begin ( ) , devices . end ( ) , devs [ ind ] ) ;
if ( it = = devices . end ( ) )
{
current . push_back ( devs [ ind ] ) ;
on_usb_pnp_event ( context_ , devs [ ind ] , LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED ) ;
}
}
// handle left ...
for ( int ind = 0 ; ind < devices . size ( ) ; + + ind )
{
std : : vector < libusb_device * > : : iterator it
= std : : find ( current . begin ( ) , current . end ( ) , devices [ ind ] ) ;
if ( it = = current . end ( ) )
{
on_usb_pnp_event ( context_ , devices [ ind ] , LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT ) ;
}
}
devices = current ;
libusb_free_device_list ( devs , 0 ) ;
}
}
void usb_manager : : thread_notify_usb_event ( )
{
while ( run_ )
{
if ( ! wait_pnp_ . wait ( ) )
continue ;
if ( ! run_ )
break ;
int delay = 50 ; // milliseconds ...
while ( pnp_events_ . Size ( ) & & run_ )
{
PNPDEV pd = pnp_events_ . Take ( ) ;
bool retry = false ;
if ( pd . event = = LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED )
{
unsigned ms = std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : system_clock : : now ( ) - pd . happen_time ) . count ( ) ;
if ( ms < delay )
{
this_thread : : sleep_for ( chrono : : milliseconds ( delay ) ) ;
}
}
2023-11-24 07:14:15 +00:00
libusb_ref_device ( pd . dev ) ; // for re-enter the queue pnp_events_
2022-05-03 03:56:07 +00:00
notify_usb_event ( pd , & retry ) ;
if ( retry )
{
2023-11-24 07:14:15 +00:00
if ( std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : system_clock : : now ( ) - pd . happen_time ) . count ( )
2022-05-03 03:56:07 +00:00
< = 5000 )
2022-11-25 06:19:15 +00:00
pnp_events_ . Put ( pd , sizeof ( pd ) ) ;
2023-11-24 07:14:15 +00:00
else
retry = false ;
2022-05-03 03:56:07 +00:00
if ( pnp_events_ . Size ( ) = = 1 )
this_thread : : sleep_for ( chrono : : milliseconds ( 1000 ) ) ;
else
this_thread : : sleep_for ( chrono : : milliseconds ( delay ) ) ;
}
2023-11-24 07:14:15 +00:00
if ( ! retry )
libusb_unref_device ( pd . dev ) ;
2022-05-03 03:56:07 +00:00
}
}
}
void usb_manager : : notify_usb_event ( PNPDEV & pd , bool * retry )
{
usb_event ev = USB_EVENT_NULL ;
usb_dev ud ;
bool re_try = false ;
std : : string evstr ( " " ) ;
usb_manager : : get_device_info ( pd . dev , & ud ) ;
ud . contex = pd . ctx ;
if ( LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = = pd . event )
{
ev = USB_EVENT_DEVICE_ARRIVED ;
evstr = " USB_EVENT_DEVICE_ARRIVED " ;
2023-02-24 10:10:49 +00:00
2022-05-03 03:56:07 +00:00
}
else if ( LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = = pd . event )
{
ev = USB_EVENT_DEVICE_LEFT ;
evstr = " USB_EVENT_DEVICE_LEFT " ;
}
else
{
char buf [ 20 ] ;
sprintf ( buf , " 0x%x " , pd . event ) ;
evstr = buf ;
}
2022-05-30 03:04:26 +00:00
VLOG_MINI_5 ( LOG_LEVEL_DEBUG_INFO , " USB%u.%x of pid:vid(%x:%x) event(%s) received. \n "
2022-05-03 03:56:07 +00:00
, HIBYTE ( ud . ver ) , LOBYTE ( ud . ver ) / 0x10 , ud . pid , ud . vid , evstr . c_str ( ) ) ;
if ( ev ! = USB_EVENT_NULL )
{
if ( ! retry )
retry = & re_try ;
usb_cb_ ( ev , pd . dev , ud . vid , ud . pid , HIBYTE ( ud . ver ) , LOBYTE ( ud . ver ) / 0x10 , retry , usb_cb_param_ ) ;
}
2022-07-04 08:30:01 +00:00
libusb_unref_device ( pd . dev ) ; // response for libusb_ref_device in usb_manager::usb_pnp_callback
2022-05-03 03:56:07 +00:00
}
void usb_manager : : thread_trigger_usb_event ( )
{
if ( ! usb_cb_handle_ )
{
// we try manually find device here
int times = 10 , elapse_max = 60 * 2 , elapse = elapse_max ;
std : : vector < libusb_device * > devices ;
while ( run_ )
{
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1000 ) ) ;
// simulate PNP events ...
fake_usb_pnp ( devices ) ;
// retry register pnp ...
if ( - - elapse = = 0 & & - - times > 0 )
{
elapse_max * = 2 ;
elapse = elapse_max ;
if ( register_usb_pnp ( ) = = LIBUSB_SUCCESS )
{
// ^_^
devices . clear ( ) ;
2022-05-30 03:04:26 +00:00
LOG_INFO ( LOG_LEVEL_DEBUG_INFO , " register_usb_pnp success ^_^ \n " ) ;
2022-05-03 03:56:07 +00:00
break ;
}
}
}
}
while ( run_ )
{
timeval tm = { 1 , 0 } ;
int ret = libusb_handle_events_timeout ( context_ , & tm ) ;
if ( ret < 0 )
2022-05-30 03:04:26 +00:00
LOG_INFO ( LOG_LEVEL_FATAL , ( std : : string ( " libusb_handle_events_timeout error " ) + libusb_error_name ( ret ) + " \n " ) . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 10 ) ) ;
}
}
int usb_manager : : on_usb_pnp_event ( libusb_context * ctx , libusb_device * device , libusb_hotplug_event event )
{
PNPDEV pd ;
unsigned ms = std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : system_clock : : now ( ) - born_ ) . count ( ) ;
2023-11-24 07:14:15 +00:00
libusb_ref_device ( device ) ;
2022-05-03 03:56:07 +00:00
pd . ctx = ctx ;
pd . dev = device ;
pd . event = event ;
pd . happen_time = std : : chrono : : system_clock : : now ( ) ;
if ( ms > 1000 )
{
2022-11-25 06:19:15 +00:00
pnp_events_ . Put ( pd , sizeof ( pd ) ) ;
2022-05-03 03:56:07 +00:00
wait_pnp_ . notify ( ) ;
}
else
{
bool retry = false ;
2023-11-24 07:14:15 +00:00
libusb_ref_device ( device ) ;
2022-05-03 03:56:07 +00:00
notify_usb_event ( pd , & retry ) ;
if ( retry )
2022-11-25 06:19:15 +00:00
pnp_events_ . Put ( pd , sizeof ( pd ) ) ;
2023-11-24 07:14:15 +00:00
else
libusb_unref_device ( device ) ;
2022-05-03 03:56:07 +00:00
}
return 0 ;
}
usb_manager * usb_manager : : instance ( void )
{
if ( usb_manager : : inst_ = = NULL )
usb_manager : : inst_ = new usb_manager ( ) ;
return usb_manager : : inst_ ;
}
void usb_manager : : clear ( void )
{
if ( usb_manager : : inst_ )
{
delete usb_manager : : inst_ ;
usb_manager : : inst_ = NULL ;
}
}
int usb_manager : : usb_error_2_hg_err ( int usb_err )
{
if ( usb_err = = LIBUSB_ERROR_TIMEOUT )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_TIMEOUT ;
2022-05-03 03:56:07 +00:00
else if ( usb_err = = LIBUSB_ERROR_PIPE )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_IO ;
2022-05-03 03:56:07 +00:00
else if ( usb_err = = LIBUSB_ERROR_NO_DEVICE )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_FOUND ;
2022-05-03 03:56:07 +00:00
else if ( usb_err = = LIBUSB_ERROR_BUSY )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_BUSY ;
2022-05-03 03:56:07 +00:00
else if ( usb_err = = LIBUSB_ERROR_INVALID_PARAM )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
else if ( usb_err = = LIBUSB_ERROR_OVERFLOW )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OUT_OF_RANGE ;
2022-05-03 03:56:07 +00:00
else if ( usb_err = = LIBUSB_ERROR_NO_MEM )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INSUFFICIENT_MEMORY ;
2022-05-03 03:56:07 +00:00
else if ( usb_err = = LIBUSB_ERROR_ACCESS )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_ACCESS_DENIED ;
2022-05-03 03:56:07 +00:00
else if ( usb_err < 0 )
2022-05-17 07:04:55 +00:00
return ( scanner_err ) usb_err ;
2022-05-03 03:56:07 +00:00
else
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
void usb_manager : : init_endpoint ( USBENDP * uep )
{
uep - > in . port = uep - > out . port = usb_manager : : uninit_uint8 ;
uep - > in . iface = uep - > out . iface = usb_manager : : uninit_uint8 ;
uep - > in . iconf = uep - > out . iconf = usb_manager : : uninit_uint8 ;
uep - > in . claimed = uep - > out . claimed = 0 ;
uep - > in . max_packet = uep - > out . max_packet = 0 ;
}
std : : string usb_manager : : device_class ( libusb_class_code code )
{
IF_CLASS ( code , LIBUSB_CLASS_PER_INTERFACE ) ;
IF_CLASS ( code , LIBUSB_CLASS_AUDIO ) ;
IF_CLASS ( code , LIBUSB_CLASS_COMM ) ;
IF_CLASS ( code , LIBUSB_CLASS_HID ) ;
IF_CLASS ( code , LIBUSB_CLASS_PHYSICAL ) ;
IF_CLASS ( code , LIBUSB_CLASS_IMAGE ) ;
IF_CLASS ( code , LIBUSB_CLASS_PRINTER ) ;
IF_CLASS ( code , LIBUSB_CLASS_MASS_STORAGE ) ;
IF_CLASS ( code , LIBUSB_CLASS_HUB ) ;
IF_CLASS ( code , LIBUSB_CLASS_DATA ) ;
IF_CLASS ( code , LIBUSB_CLASS_SMART_CARD ) ;
IF_CLASS ( code , LIBUSB_CLASS_CONTENT_SECURITY ) ;
IF_CLASS ( code , LIBUSB_CLASS_VIDEO ) ;
IF_CLASS ( code , LIBUSB_CLASS_PERSONAL_HEALTHCARE ) ;
IF_CLASS ( code , LIBUSB_CLASS_DIAGNOSTIC_DEVICE ) ;
IF_CLASS ( code , LIBUSB_CLASS_WIRELESS ) ;
//IF_CLASS(code, LIBUSB_CLASS_MISCELLANEOUS);
IF_CLASS ( code , LIBUSB_CLASS_APPLICATION ) ;
IF_CLASS ( code , LIBUSB_CLASS_VENDOR_SPEC ) ;
char buf [ 40 ] ;
sprintf ( buf , " unknown class: %d " , code ) ;
return buf ;
}
std : : string usb_manager : : endpoint_type ( libusb_transfer_type type )
{
IF_CLASS ( type , LIBUSB_TRANSFER_TYPE_CONTROL ) ;
IF_CLASS ( type , LIBUSB_TRANSFER_TYPE_ISOCHRONOUS ) ;
IF_CLASS ( type , LIBUSB_TRANSFER_TYPE_BULK ) ;
IF_CLASS ( type , LIBUSB_TRANSFER_TYPE_INTERRUPT ) ;
IF_CLASS ( type , LIBUSB_TRANSFER_TYPE_BULK_STREAM ) ;
char buf [ 40 ] ;
sprintf ( buf , " unknown type: %d " , type ) ;
return buf ;
}
bool usb_manager : : get_device_info ( libusb_device * device , usb_dev * devinfo )
{
libusb_device_descriptor descriptor ;
int ret = libusb_get_device_descriptor ( device , & descriptor ) ;
if ( ret ! = LIBUSB_SUCCESS )
return false ;
devinfo - > device = device ;
devinfo - > ver = descriptor . bcdUSB ;
devinfo - > vid = descriptor . idVendor ;
devinfo - > pid = descriptor . idProduct ;
2022-05-09 06:48:42 +00:00
devinfo - > addr = 0 ; // libusb_get_device_address(device); - initialize at open
2022-05-03 03:56:07 +00:00
return true ;
}
void usb_manager : : enum_endpoints ( libusb_device * device , USBTRANSENDP * endp )
{
libusb_device_descriptor desc ;
libusb_config_descriptor * conf = NULL ;
std : : string dev ( hg_log : : format_ptr ( device ) ) ;
int ret = libusb_get_device_descriptor ( device , & desc ) ;
bool found_ep = false ;
if ( ret ! = 0 )
{
2022-05-30 03:04:26 +00:00
LOG_INFO ( LOG_LEVEL_WARNING , ( std : : string ( " Get device descriptor of device( " ) + dev + " ) failed. \n " ) . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
return ;
}
if ( endp )
{
usb_manager : : init_endpoint ( & endp - > bulk ) ;
usb_manager : : init_endpoint ( & endp - > bulk_stream ) ;
usb_manager : : init_endpoint ( & endp - > control ) ;
usb_manager : : init_endpoint ( & endp - > interrupt ) ;
usb_manager : : init_endpoint ( & endp - > isochronous ) ;
}
else
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " +Device(%s) has %u configurations ... \n " , dev . c_str ( ) , desc . bNumConfigurations ) ;
2022-05-03 03:56:07 +00:00
for ( int i = 0 ; i < ( int ) desc . bNumConfigurations ; + + i )
{
ret = libusb_get_config_descriptor ( device , i , & conf ) ;
if ( ret ! = 0 )
{
if ( ! endp )
2022-05-30 03:04:26 +00:00
VLOG_MINI_1 ( LOG_LEVEL_DEBUG_INFO , " Get %d configuration failed. \n " , i + 1 ) ;
2022-05-03 03:56:07 +00:00
continue ;
}
if ( ! endp )
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " Configuration %d has %d interfaces \n " , i + 1 , conf - > bNumInterfaces ) ;
2022-05-03 03:56:07 +00:00
for ( int j = 0 ; j < conf - > bNumInterfaces ; + + j )
{
if ( ! endp )
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " Interface %d has %d alt-settings \n " , j + 1 , conf - > interface [ j ] . num_altsetting ) ;
2022-05-03 03:56:07 +00:00
for ( int k = 0 ; k < conf - > interface [ j ] . num_altsetting ; + + k )
{
if ( ! endp )
2022-05-30 03:04:26 +00:00
VLOG_MINI_4 ( LOG_LEVEL_DEBUG_INFO , " Setting %d: %d - %s has %d endpoints \n " , k + 1 , conf - > interface [ j ] . altsetting [ k ] . bInterfaceNumber
2022-05-03 03:56:07 +00:00
, usb_manager : : device_class ( ( libusb_class_code ) conf - > interface [ j ] . altsetting [ k ] . bInterfaceClass ) . c_str ( )
, conf - > interface [ j ] . altsetting [ k ] . bNumEndpoints ) ;
for ( int l = 0 ; l < conf - > interface [ j ] . altsetting [ k ] . bNumEndpoints ; + + l )
{
if ( endp )
{
USBENDP * ep = NULL ;
if ( conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bmAttributes = = LIBUSB_TRANSFER_TYPE_CONTROL )
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " Found endpoint(%x) for device(VID: %x, PID: %x) of control \n " , conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bEndpointAddress , desc . idVendor , desc . idProduct ) ;
2022-05-03 03:56:07 +00:00
ep = & endp - > control ;
}
else if ( conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bmAttributes = = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS )
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " Found endpoint(%x) for device(VID: %x, PID: %x) of isochronous \n " , conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bEndpointAddress , desc . idVendor , desc . idProduct ) ;
2022-05-03 03:56:07 +00:00
ep = & endp - > isochronous ;
}
if ( conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bmAttributes = = LIBUSB_TRANSFER_TYPE_BULK )
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " Found endpoint(%x) for device(VID: %x, PID: %x) of bulk \n " , conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bEndpointAddress , desc . idVendor , desc . idProduct ) ;
2022-05-03 03:56:07 +00:00
ep = & endp - > bulk ;
}
if ( conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bmAttributes = = LIBUSB_TRANSFER_TYPE_INTERRUPT )
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " Found endpoint(%x) for device(VID: %x, PID: %x) of interrupt \n " , conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bEndpointAddress , desc . idVendor , desc . idProduct ) ;
2022-05-03 03:56:07 +00:00
ep = & endp - > interrupt ;
}
if ( conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bmAttributes = = LIBUSB_TRANSFER_TYPE_BULK_STREAM )
{
2022-05-30 03:04:26 +00:00
VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " Found endpoint(%x) for device(VID: %x, PID: %x) of bulk-stream \n " , conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bEndpointAddress , desc . idVendor , desc . idProduct ) ;
2022-05-03 03:56:07 +00:00
ep = & endp - > bulk_stream ;
}
if ( ep )
{
USBSIMPLEX * s = NULL ;
if ( conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bEndpointAddress & LIBUSB_ENDPOINT_IN )
s = & ep - > in ; // = (conf->interface[j].altsetting[k].endpoint[l].bEndpointAddress & 3) | LIBUSB_ENDPOINT_IN;
else
s = & ep - > out ; // = (conf->interface[j].altsetting[k].endpoint[l].bEndpointAddress & 3) | LIBUSB_ENDPOINT_OUT;
2022-05-30 03:42:16 +00:00
// NOTE: 这里应该尽量将输入输出端口统一到同一个接口上来, 目前未做, 只取第一<E7ACAC> <E4B880> ?
2022-05-03 03:56:07 +00:00
if ( s - > port = = usb_manager : : uninit_uint8 )
{
s - > port = conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bEndpointAddress & ( LIBUSB_ENDPOINT_IN | LIBUSB_ENDPOINT_OUT | 3 ) ;
s - > iconf = conf - > bConfigurationValue ;
s - > iface = j ;
s - > claimed = 0 ;
s - > max_packet = conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . wMaxPacketSize ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " Endpoint address = 0x%02x, origin = 0x%02x, max packet: 0x%x \n " , s - > port , conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bEndpointAddress
2022-05-03 03:56:07 +00:00
, s - > max_packet ) ;
}
found_ep = true ;
}
}
else
2022-05-30 03:04:26 +00:00
VLOG_MINI_4 ( LOG_LEVEL_DEBUG_INFO , " Endpoint %d(%s) address: %x, Max packet: 0x%x bytes \n " , l + 1
2022-05-03 03:56:07 +00:00
, usb_manager : : endpoint_type ( ( libusb_transfer_type ) conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bmAttributes ) . c_str ( )
, conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . bEndpointAddress
, conf - > interface [ j ] . altsetting [ k ] . endpoint [ l ] . wMaxPacketSize ) ;
}
}
}
libusb_free_config_descriptor ( conf ) ;
}
if ( endp & & ! found_ep )
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_FATAL , " No endpoint has been found on device (VID: %x, PID: %x) \n " , desc . idVendor , desc . idProduct ) ;
2022-05-03 03:56:07 +00:00
}
int usb_manager : : register_hotplug ( usb_event_handler cb , void * user )
{
if ( cb )
usb_cb_ = cb ;
else
usb_cb_ = & usb_manager : : usb_event_handle ;
usb_cb_param_ = user ;
int ret = register_usb_pnp ( ) ;
if ( ret ! = LIBUSB_SUCCESS )
{
// then we find devices manually, and need not return failure here
}
init_notify_thread ( ) ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
int usb_manager : : open ( libusb_device * device , usb_io * * usbio , std : : string * msg )
{
if ( ! usbio )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
usb_dev dev ;
usb_io * usb = NULL ;
if ( ! get_device_info ( device , & dev ) )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_FOUND ;
2022-05-03 03:56:07 +00:00
dev . contex = context_ ;
usb = new usb_io ( dev ) ;
if ( ! usb - > is_ready ( ) )
{
int err = usb - > last_error ( ) ;
if ( msg )
* msg = usb - > init_error_msg ( ) ;
usb - > release ( ) ;
2022-05-30 03:42:16 +00:00
VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " Open %04x:%04x failed: %s \n " , dev . vid , dev . pid , hg_scanner_err_name ( err ) ) ;
2022-05-03 03:56:07 +00:00
return err ;
}
* usbio = dynamic_cast < usb_io * > ( usb ) ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
int usb_manager : : last_status ( void )
{
return status_ ;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usb_io
//#define USE_OLD_USB
# ifdef USE_OLD_USB
# include "libusbex.h"
std : : shared_ptr < IUsb > usb_ ;
# endif
2022-05-17 07:04:55 +00:00
usb_io : : usb_io ( const usb_dev & dev ) : ref_ ( 1 ) , handle_ ( NULL ) , dev_info_ ( dev ) , to_ ( 1000 ) , last_err_ ( SCANNER_ERR_NOT_START ) , ref_device_ ( nullptr )
2022-05-03 03:56:07 +00:00
, singleton_ ( nullptr )
{
# ifdef USE_OLD_USB
std : : list < std : : shared_ptr < IUsb > > all = Libusb_List : : find_vid_pid ( 0x3072 , 0x239 ) ;
if ( all . size ( ) )
{
usb_ = * all . begin ( ) ;
usb_ - > open ( ) ;
handle_ = ( libusb_device_handle * ) 1 ;
}
# else
clear_endpoints ( ) ;
open ( ) ;
# endif
}
usb_io : : ~ usb_io ( )
{
close ( ) ;
}
bool usb_io : : make_singleton ( void )
{
unsigned long long key = dev_info_ . vid ;
key < < = 16 ;
key | = dev_info_ . pid ;
key < < = 16 ;
2022-05-09 06:48:42 +00:00
if ( dev_info_ . addr = = 0 )
dev_info_ . addr = libusb_get_device_address ( dev_info_ . device ) ;
2022-05-03 03:56:07 +00:00
key | = dev_info_ . addr ;
if ( singleton_ )
singleton_ - > release ( ) ;
singleton_ = new shared_memory ( key ) ;
if ( singleton_ - > is_first ( ) )
{
return true ;
}
std : : string str ( singleton_ - > read ( ) ) ;
singleton_ - > release ( ) ;
singleton_ = nullptr ;
2022-05-17 07:04:55 +00:00
last_err_ = SCANNER_ERR_OPENED_BY_OTHER_PROCESS ;
2023-08-16 10:32:37 +00:00
std : : string tips ( from_default_language ( " \350 \256 \276 \345 \244 \207 \345 \267 \262 \347 \273 \217 \350 \242 \253 \350 \277 \233 \347 \250 \213 '%s' \345 \215 \240 \347 \224 \250 " ) ) ;
size_t pos = tips . find ( " %s " ) ;
if ( pos ! = std : : string : : npos )
tips . replace ( pos , 2 , str ) ;
2023-08-16 10:42:41 +00:00
str = std : : move ( tips ) ;
2022-05-16 09:26:36 +00:00
init_err_msg_ = str ;
2022-09-26 09:30:44 +00:00
VLOG_MINI_1 ( LOG_LEVEL_FATAL , " Open failed: %s \n " , str . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
return false ;
}
void usb_io : : clear_endpoints ( void )
{
usb_manager : : init_endpoint ( & endpoints_ . bulk ) ;
usb_manager : : init_endpoint ( & endpoints_ . bulk_stream ) ;
usb_manager : : init_endpoint ( & endpoints_ . control ) ;
usb_manager : : init_endpoint ( & endpoints_ . interrupt ) ;
usb_manager : : init_endpoint ( & endpoints_ . isochronous ) ;
}
bool usb_io : : claim_interterface ( usb_manager : : USBSIMPLEX * spl )
{
int ret = libusb_claim_interface ( handle_ , spl - > iface ) ;
if ( ret = = LIBUSB_SUCCESS )
{
spl - > claimed = true ;
return true ;
}
2022-06-01 03:04:10 +00:00
VLOG_MINI_2 ( LOG_LEVEL_FATAL , " libusb_claim_interface(%d) = %s, now try some actions ... \n " , spl - > iface , libusb_error_name ( ret ) ) ;
2022-05-03 03:56:07 +00:00
ret = libusb_kernel_driver_active ( handle_ , spl - > iface ) ;
if ( ret = = 1 )
{
ret = libusb_detach_kernel_driver ( handle_ , spl - > iface ) ;
2022-06-01 03:04:10 +00:00
VLOG_MINI_2 ( LOG_LEVEL_FATAL , " libusb_detach_kernel_driver(%d) = %s \n " , spl - > iface , libusb_error_name ( ret ) ) ;
2022-05-03 03:56:07 +00:00
}
else if ( ret = = LIBUSB_ERROR_NO_DEVICE )
{
2022-05-17 07:04:55 +00:00
last_err_ = SCANNER_ERR_DEVICE_NOT_FOUND ;
2022-06-01 03:04:10 +00:00
VLOG_MINI_1 ( LOG_LEVEL_FATAL , " device(%s) maybe left when libusb_kernel_driver_active. \n " , hg_log : : format_ptr ( dev_info_ . device ) . c_str ( ) ) ;
2022-05-03 03:56:07 +00:00
return false ;
}
2022-06-01 03:04:10 +00:00
else
{
VLOG_MINI_2 ( LOG_LEVEL_FATAL , " libusb_kernel_driver_active(%d) = %d \n " , spl - > iface , ret ) ;
}
ret = libusb_clear_halt ( handle_ , spl - > port ) ;
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " libusb_clear_halt(%x) = %s \n " , spl - > port , libusb_error_name ( ret ) ) ;
ret = libusb_release_interface ( handle_ , spl - > iface ) ;
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " libusb_release_interface(%u) = %s \n " , spl - > iface , libusb_error_name ( ret ) ) ;
ret = libusb_set_configuration ( handle_ , spl - > iconf ) ;
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " libusb_set_configuration(%u) = %s \n " , spl - > iconf , libusb_error_name ( ret ) ) ;
2022-05-03 03:56:07 +00:00
//ret = libusb_reset_device(handle_);
2022-05-30 03:04:26 +00:00
//VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, " libusb_reset_device = %s\n", libusb_error_name(ret));
2022-05-03 03:56:07 +00:00
//if (ret == LIBUSB_ERROR_NOT_FOUND)
//{
// last_err_ = usb_manager::usb_error_2_hg_err(ret);
2022-05-30 03:04:26 +00:00
// VLOG_MINI_1(LOG_LEVEL_FATAL, "device(%s) maybe left when libusb_reset_device.\n", hg_log::format_ptr(dev_info_.device).c_str());
2022-05-03 03:56:07 +00:00
//
// return false;
//}
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 100 ) ) ;
ret = libusb_claim_interface ( handle_ , spl - > iface ) ;
if ( ret = = LIBUSB_SUCCESS )
{
spl - > claimed = true ;
2022-06-01 03:04:10 +00:00
VLOG_MINI_2 ( LOG_LEVEL_FATAL , " second libusb_claim_interface(%d) = %s \n " , spl - > iface , libusb_error_name ( ret ) ) ;
2022-05-03 03:56:07 +00:00
return true ;
}
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_FATAL , " second try libusb_claim_interface(%d) = %s \n " , spl - > iface , libusb_error_name ( ret ) ) ;
2022-05-17 07:04:55 +00:00
last_err_ = SCANNER_ERR_USB_CLAIM_INTERFACE_FAILED ;
2022-05-03 03:56:07 +00:00
return false ;
}
int usb_io : : claim_interfaces ( bool claim )
{
usb_manager : : USBENDP * eps [ ] = { & endpoints_ . control , & endpoints_ . isochronous , & endpoints_ . bulk , & endpoints_ . interrupt , & endpoints_ . bulk_stream } ;
std : : vector < uint8_t > claimed ;
if ( claim )
{
for ( size_t i = 0 ; i < _countof ( eps ) ; + + i )
{
if ( eps [ i ] - > in . port ! = usb_manager : : uninit_uint8
& & std : : find ( claimed . begin ( ) , claimed . end ( ) , eps [ i ] - > in . iface ) = = claimed . end ( ) )
{
if ( ! claim_interterface ( & eps [ i ] - > in ) )
break ;
claimed . push_back ( eps [ i ] - > in . iface ) ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " claimed %s interface %d \n " , usb_manager : : endpoint_type ( ( libusb_transfer_type ) i ) . c_str ( ) , eps [ i ] - > in . iface ) ;
2022-05-03 03:56:07 +00:00
}
if ( eps [ i ] - > out . port ! = usb_manager : : uninit_uint8 & & eps [ i ] - > out . iface ! = eps [ i ] - > in . iface
& & std : : find ( claimed . begin ( ) , claimed . end ( ) , eps [ i ] - > out . iface ) = = claimed . end ( ) )
{
if ( ! claim_interterface ( & eps [ i ] - > out ) )
break ;
claimed . push_back ( eps [ i ] - > out . iface ) ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " claimed %s interface %d \n " , usb_manager : : endpoint_type ( ( libusb_transfer_type ) i ) . c_str ( ) , eps [ i ] - > out . iface ) ;
2022-05-03 03:56:07 +00:00
}
}
}
else
{
for ( size_t i = 0 ; i < _countof ( eps ) ; + + i )
{
if ( eps [ i ] - > in . claimed )
libusb_release_interface ( handle_ , eps [ i ] - > in . iface ) ;
if ( eps [ i ] - > out . claimed )
libusb_release_interface ( handle_ , eps [ i ] - > out . iface ) ;
}
2022-05-17 07:04:55 +00:00
last_err_ = SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
return last_err_ ;
}
void usb_io : : init_after_open ( void )
{
2022-05-17 07:04:55 +00:00
last_err_ = SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
libusb_set_auto_detach_kernel_driver ( handle_ , 1 ) ;
usb_manager : : enum_endpoints ( dev_info_ . device , & endpoints_ ) ;
2022-05-17 07:04:55 +00:00
if ( claim_interfaces ( true ) ! = SCANNER_ERR_OK )
2022-05-03 03:56:07 +00:00
{
int err = last_err_ ;
close ( ) ;
last_err_ = err ;
}
2023-12-02 09:53:25 +00:00
else
{
char str [ 128 ] = { 0 } , * ver = nullptr ;
libusb_device_descriptor dd = { 0 } ;
libusb_get_device_descriptor ( dev_info_ . device , & dd ) ;
libusb_get_string_descriptor_ascii ( handle_ , dd . iProduct , ( unsigned char * ) str , _countof ( str ) - 1 ) ;
VLOG_MINI_1 ( LOG_LEVEL_DEBUG_INFO , " Device Product: '%s' \n " , str ) ;
ver = strstr ( str , " (V " ) ;
if ( ver )
{
ver_ = ( int ) atof ( ver + 2 ) ;
}
else
{
ver_ = 1 ;
}
}
2022-05-03 03:56:07 +00:00
}
void usb_io : : open ( void )
{
if ( ! make_singleton ( ) )
return ;
if ( ref_device_ )
libusb_unref_device ( ref_device_ ) ;
ref_device_ = libusb_ref_device ( dev_info_ . device ) ;
int ret = libusb_open ( dev_info_ . device , & handle_ ) ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_3 ( LOG_LEVEL_DEBUG_INFO , " call libusb_open(%s, %s) = %s \n " , hg_log : : format_ptr ( dev_info_ . device ) . c_str ( )
2022-05-03 03:56:07 +00:00
, hg_log : : format_ptr ( handle_ ) . c_str ( ) , libusb_error_name ( ret ) ) ;
if ( ret = = LIBUSB_SUCCESS )
{
init_after_open ( ) ;
}
else
{
handle_ = libusb_open_device_with_vid_pid ( dev_info_ . contex , dev_info_ . vid , dev_info_ . pid ) ;
if ( handle_ )
{
init_after_open ( ) ;
return ;
}
last_err_ = usb_manager : : usb_error_2_hg_err ( ret ) ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_4 ( LOG_LEVEL_FATAL , " Open USB%u.%u-%s failed: %s \n " , HIBYTE ( dev_info_ . ver ) , LOBYTE ( dev_info_ . ver ) / 0x10 , hg_log : : format_ptr ( dev_info_ . device ) . c_str ( ) , libusb_error_name ( ret ) ) ;
2022-05-30 03:42:16 +00:00
init_err_msg_ = hg_scanner_err_description ( last_err_ ) ;
2022-05-03 03:56:07 +00:00
handle_ = NULL ;
}
}
2022-05-17 07:04:55 +00:00
bool usb_io : : on_io_error ( scanner_err err , usb_manager : : USBSIMPLEX * endp )
2022-05-03 03:56:07 +00:00
{
2022-05-17 07:04:55 +00:00
if ( err = = SCANNER_ERR_OK )
2022-05-03 03:56:07 +00:00
return true ;
2022-05-17 07:04:55 +00:00
if ( err = = SCANNER_ERR_TIMEOUT )
2022-05-03 03:56:07 +00:00
{
2022-05-30 03:42:16 +00:00
//因为在发送img参数出现timeout, 暂时禁<E697B6> <E7A681> ?
2022-05-30 03:04:26 +00:00
// //LOG_INFO(LOG_LEVEL_DEBUG_INFO, "Operation timeout\n");
2022-05-03 03:56:07 +00:00
// libusb_clear_halt(handle_, endp->port);
// return libusb_reset_device(handle_) == LIBUSB_SUCCESS;
return true ;
}
return true ;
}
int usb_io : : add_ref ( void )
{
return + + ref_ ; // InterlockedIncreament in linux ?
}
int usb_io : : release ( void )
{
int ref = - - ref_ ; // InterlockedDecreament in linux ?
if ( ref = = 0 )
delete this ;
return ref ;
}
int usb_io : : control_io ( uint8_t type , uint8_t req , uint16_t val , uint16_t ind , void * buf , int * len )
{
# ifdef USE_OLD_USB
return usb_ - > control_msg ( type , req , val , ind , * len , buf ) ;
# endif
if ( ! handle_ )
return last_err_ ;
//if (endpoints_.control.in == usb_manager::uninit_uint8)
2022-05-17 07:04:55 +00:00
// return SCANNER_ERR_DEVICE_NOT_SUPPORT;
2022-05-03 03:56:07 +00:00
if ( ! len )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
int ret = libusb_control_transfer ( handle_ , type , req , val , ind , ( unsigned char * ) buf , * len , to_ ) ;
if ( ret > 0 )
{
* len = ret ;
2022-05-17 07:04:55 +00:00
last_err_ = SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
else
{
2022-11-26 08:06:20 +00:00
//if (on_io_error((scanner_err)usb_manager::usb_error_2_hg_err(ret), &endpoints_.control.in))
//{
// ret = libusb_control_transfer(handle_, type, req, val, ind, (unsigned char*)buf, *len, to_);
// if (ret > 0)
// {
// *len = ret;
// last_err_ = SCANNER_ERR_OK;
// return last_err_;
// }
// else
// *len = 0;
//}
//else
2022-07-21 09:54:58 +00:00
* len = 0 ;
2022-05-30 03:04:26 +00:00
VLOG_MINI_5 ( LOG_LEVEL_DEBUG_INFO , " libusb_control_transfer(%x, %x, %d, %d) = %s \n " , type , req , val , ind , libusb_error_name ( ret ) ) ;
2022-05-03 03:56:07 +00:00
last_err_ = usb_manager : : usb_error_2_hg_err ( ret ) ;
}
return last_err_ ;
}
int usb_io : : read_bulk ( void * buf , int * len )
{
# ifdef USE_OLD_USB
* len = usb_ - > read_bulk ( buf , * len ) ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
# endif
if ( ! handle_ )
return last_err_ ;
if ( endpoints_ . bulk . in . port = = usb_manager : : uninit_uint8 )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_SUPPORT ;
2022-05-03 03:56:07 +00:00
if ( ! len )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
//if (*len < endpoints_.bulk.in.max_packet) // avoid transferring overflows ...
//{
// *len = endpoints_.bulk.in.max_packet;
//
2022-05-17 07:04:55 +00:00
// return SCANNER_ERR_INSUFFICIENT_MEMORY;
2022-05-03 03:56:07 +00:00
//}
// libusb_clear_halt(handle_,endpoints_.bulk.in.port);
int total = 0 ,
err = libusb_bulk_transfer ( handle_ , endpoints_ . bulk . in . port , ( unsigned char * ) buf , * len , & total , to_ ) ;
if ( err )
{
2022-06-01 08:11:51 +00:00
VLOG_MINI_4 ( LOG_LEVEL_DEBUG_INFO , " read_bulk(%x, %d/%d) = %s \n " , endpoints_ . bulk . in . port , total , * len , libusb_error_name ( err ) ) ;
if ( err = = LIBUSB_ERROR_TIMEOUT & & * len = = total )
{
int old = to_ ;
2022-08-18 06:50:43 +00:00
if ( to_ < 10 * 1000 )
to_ * = 1.5f ;
//err = LIBUSB_SUCCESS;
2022-06-01 08:11:51 +00:00
VLOG_MINI_2 ( LOG_LEVEL_DEBUG_INFO , " Read full length, we consider it as success, and increament timeout from %d to %d \n " , old , to_ ) ;
}
2022-05-03 03:56:07 +00:00
}
2022-06-01 08:11:51 +00:00
* len = total ;
last_err_ = usb_manager : : usb_error_2_hg_err ( err ) ;
2022-05-03 03:56:07 +00:00
return last_err_ ;
}
int usb_io : : write_bulk ( void * buf , int * len )
{
# ifdef USE_OLD_USB
* len = usb_ - > write_bulk ( buf , * len ) ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
# endif
if ( ! handle_ )
return last_err_ ;
if ( endpoints_ . bulk . out . port = = usb_manager : : uninit_uint8 )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_SUPPORT ;
2022-05-03 03:56:07 +00:00
if ( ! len )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
unsigned char * data = ( unsigned char * ) buf ;
int total = 0 , t = 0 ,
err = usb_manager : : usb_error_2_hg_err ( libusb_bulk_transfer ( handle_ , endpoints_ . bulk . out . port , data , * len , & t , to_ ) ) ;
2022-05-30 03:42:16 +00:00
//VLOG_MINI_6(LOG_LEVEL_DEBUG_INFO, "First write port %x bulk %d/%d = %s(timeout = %d, packet size = %x)\n", endpoints_.bulk.out.port, t, *len, hg_scanner_err_name((scanner_err)err).c_str(), to_, endpoints_.bulk.out.max_packet);
// printf("First write port %x bulk %d/%d = %s(timeout = %d, packet size = %x)\n", endpoints_.bulk.out.port, t, *len, hg_scanner_err_name((scanner_err)err).c_str(), to_, endpoints_.bulk.out.max_packet);
2022-05-17 07:04:55 +00:00
if ( ! on_io_error ( ( scanner_err ) err , & endpoints_ . bulk . out ) )
2022-05-03 03:56:07 +00:00
{
* len = t ;
return err ;
}
total + = t ;
2022-05-17 07:04:55 +00:00
while ( total < * len & & ( err = = SCANNER_ERR_TIMEOUT | | err = = SCANNER_ERR_DEVICE_BUSY ) )
2022-05-03 03:56:07 +00:00
{
if ( ! t )
break ;
data + = t ;
t = 0 ;
err = usb_manager : : usb_error_2_hg_err ( libusb_bulk_transfer ( handle_ , endpoints_ . bulk . out . port , data , * len - total , & t , to_ ) ) ;
total + = t ;
}
2022-05-30 03:42:16 +00:00
//VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Last write bulk %d/%d = %s\n", total, *len, hg_scanner_err_name((scanner_err)err).c_str());
2022-05-03 03:56:07 +00:00
* len = total ;
last_err_ = err ;
return last_err_ ;
}
int usb_io : : read_interrupt ( void * buf , int * len )
{
# ifdef USE_OLD_USB
* len = usb_ - > read_int ( buf , * len ) ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
# endif
if ( ! handle_ )
return last_err_ ;
if ( endpoints_ . interrupt . in . port = = usb_manager : : uninit_uint8 )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_SUPPORT ;
2022-05-03 03:56:07 +00:00
if ( ! len )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
if ( * len < endpoints_ . interrupt . in . max_packet ) // avoid transferring overflows ...
{
* len = endpoints_ . interrupt . in . max_packet ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INSUFFICIENT_MEMORY ;
2022-05-03 03:56:07 +00:00
}
int io = 0 ;
last_err_ = usb_manager : : usb_error_2_hg_err ( libusb_interrupt_transfer ( handle_ , endpoints_ . interrupt . in . port , ( unsigned char * ) buf , * len , & io , to_ ) ) ;
* len = io ;
return last_err_ ;
}
int usb_io : : write_interrupt ( void * buf , int * len )
{
if ( ! handle_ )
return last_err_ ;
if ( endpoints_ . interrupt . out . port = = usb_manager : : uninit_uint8 )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_SUPPORT ;
2022-05-03 03:56:07 +00:00
if ( ! len )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
unsigned char * data = ( unsigned char * ) buf ;
int total = 0 , t = 0 ,
err = usb_manager : : usb_error_2_hg_err ( libusb_bulk_transfer ( handle_ , endpoints_ . interrupt . out . port , data , * len , & t , to_ ) ) ;
total + = t ;
2022-05-17 07:04:55 +00:00
while ( total < * len & & ( err = = SCANNER_ERR_TIMEOUT | | err = = SCANNER_ERR_DEVICE_BUSY ) )
2022-05-03 03:56:07 +00:00
{
data + = t ;
t = 0 ;
err = usb_manager : : usb_error_2_hg_err ( libusb_interrupt_transfer ( handle_ , endpoints_ . interrupt . out . port , data , * len - total , & t , to_ ) ) ;
total + = t ;
}
* len = total ;
last_err_ = err ;
return last_err_ ;
}
int usb_io : : read_isochronous ( void * buf , int * len )
{
if ( ! handle_ )
return last_err_ ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_SUPPORT ;
2022-05-03 03:56:07 +00:00
}
int usb_io : : write_isochronous ( void * buf , int * len )
{
if ( ! handle_ )
return last_err_ ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_SUPPORT ;
2022-05-03 03:56:07 +00:00
}
int usb_io : : read_bulk_stream ( void * buf , int * len )
{
if ( ! handle_ )
return last_err_ ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_SUPPORT ;
2022-05-03 03:56:07 +00:00
}
int usb_io : : write_bulk_stream ( void * buf , int * len )
{
if ( ! handle_ )
return last_err_ ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_SUPPORT ;
2022-05-03 03:56:07 +00:00
}
int usb_io : : reset ( void )
{
if ( ! handle_ )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_NOT_OPEN ;
2022-05-03 03:56:07 +00:00
return usb_manager : : usb_error_2_hg_err ( libusb_reset_device ( handle_ ) ) ;
}
int usb_io : : reopen ( void )
{
close ( ) ;
open ( ) ;
return last_err_ ;
}
int usb_io : : close ( void )
{
# ifdef USE_OLD_USB
usb_ . reset ( ) ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
# endif
if ( singleton_ )
singleton_ - > release ( ) ;
singleton_ = nullptr ;
if ( handle_ )
{
claim_interfaces ( false ) ;
libusb_close ( handle_ ) ;
handle_ = nullptr ;
}
clear_endpoints ( ) ;
if ( ref_device_ )
{
libusb_unref_device ( ref_device_ ) ;
ref_device_ = nullptr ;
}
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
libusb_device * usb_io : : get_usb_device ( void )
{
return dev_info_ . device ;
}
int usb_io : : get_vid ( void )
{
return dev_info_ . vid ;
}
int usb_io : : get_pid ( void )
{
return dev_info_ . pid ;
}
2023-12-02 09:53:25 +00:00
int usb_io : : get_ver ( void )
{
return ver_ ;
}
2022-05-03 03:56:07 +00:00
void usb_io : : on_disconnected ( void )
{
close ( ) ;
2022-05-17 07:04:55 +00:00
last_err_ = SCANNER_ERR_DEVICE_NOT_FOUND ;
2022-05-03 03:56:07 +00:00
}
std : : string usb_io : : init_error_msg ( void )
{
return init_err_msg_ ;
}
bool usb_io : : is_ready ( void )
{
return handle_ ! = NULL ;
}
int usb_io : : last_error ( void )
{
return last_err_ ;
}
int usb_io : : get_bulk_packet_size ( int * bytes )
{
if ( ! bytes )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
if ( endpoints_ . bulk . in . port = = usb_manager : : uninit_uint8 & & endpoints_ . bulk . out . port = = usb_manager : : uninit_uint8 )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_SUPPORT ;
2022-05-03 03:56:07 +00:00
* bytes = endpoints_ . bulk . in . max_packet ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
int usb_io : : get_interrupt_packet_size ( int * bytes )
{
if ( ! bytes )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_INVALID_PARAMETER ;
2022-05-03 03:56:07 +00:00
if ( endpoints_ . interrupt . in . port = = usb_manager : : uninit_uint8 & & endpoints_ . interrupt . out . port = = usb_manager : : uninit_uint8 )
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_DEVICE_NOT_SUPPORT ;
2022-05-03 03:56:07 +00:00
* bytes = endpoints_ . interrupt . in . max_packet ;
2022-05-17 07:04:55 +00:00
return SCANNER_ERR_OK ;
2022-05-03 03:56:07 +00:00
}
unsigned int usb_io : : set_timeout ( unsigned int to )
{
unsigned int old = to_ ;
to_ = to ;
2022-07-18 08:56:03 +00:00
# if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
if ( handle_ )
{
libusb_set_timeout ( handle_ , to_ ) ;
}
# endif
return old ;
}
unsigned int usb_io : : get_timeout ( void )
{
return to_ ;
}