00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "usbwrap.h"
00024 #include "data.h"
00025 #include "error.h"
00026 #include "debug.h"
00027
00028 #include <iomanip>
00029 #include <sstream>
00030 #include <errno.h>
00031 #include <string.h>
00032 #include <limits.h>
00033
00034 #ifndef __DEBUG_MODE__
00035 #define __DEBUG_MODE__
00036 #endif
00037 #include "debug.h"
00038
00039 namespace Usb {
00040
00041
00042
00043
00044 static std::string GetErrorString(int libusb_errcode, const std::string &str)
00045 {
00046 std::ostringstream oss;
00047 oss << "(";
00048
00049 if( libusb_errcode ) {
00050 oss << std::setbase(10) << libusb_errcode << ", ";
00051 }
00052
00053
00054 oss << usb_strerror() << "): ";
00055 oss << str;
00056 return oss.str();
00057 }
00058
00059 Error::Error(const std::string &str)
00060 : Barry::Error(GetErrorString(0, str))
00061 , m_libusb_errcode(0)
00062 {
00063 }
00064
00065 Error::Error(int libusb_errcode, const std::string &str)
00066 : Barry::Error(GetErrorString(libusb_errcode, str))
00067 , m_libusb_errcode(libusb_errcode)
00068 {
00069 }
00070
00071
00072
00073
00074
00075 Match::Match(int vendor, int product,
00076 const char *busname, const char *devname)
00077 : m_busses(0)
00078 , m_dev(0)
00079 , m_vendor(vendor)
00080 , m_product(product)
00081 , m_busname(busname)
00082 , m_devname(devname)
00083 {
00084 usb_find_busses();
00085 usb_find_devices();
00086 m_busses = usb_get_busses();
00087 }
00088
00089 Match::~Match()
00090 {
00091 }
00092
00093 bool Match::ToNum(const char *str, long &num)
00094 {
00095 char *end = 0;
00096 num = strtol(str, &end, 10);
00097 return num >= 0 &&
00098 num != LONG_MIN && num != LONG_MAX &&
00099 str != end && *end == '\0';
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 bool Match::NameCompare(const char *n1, const char *n2)
00112 {
00113 long l1, l2;
00114 if( ToNum(n1, l1) && ToNum(n2, l2) ) {
00115 return l1 == l2;
00116 }
00117 else {
00118 return strcmp(n1, n2) == 0;
00119 }
00120 }
00121
00122 bool Match::next_device(Usb::DeviceIDType *devid)
00123 {
00124 for( ; m_busses; m_busses = m_busses->next ) {
00125
00126
00127 if( m_busname && !NameCompare(m_busname, m_busses->dirname) )
00128 continue;
00129
00130 if( !m_dev )
00131 m_dev = m_busses->devices;
00132
00133 for( ; m_dev; m_dev = m_dev->next ) {
00134
00135
00136 if( m_devname && !NameCompare(m_devname, m_dev->filename) )
00137 continue;
00138
00139
00140 if( m_dev->descriptor.idVendor == m_vendor &&
00141 m_dev->descriptor.idProduct == m_product ) {
00142
00143 *devid = m_dev;
00144
00145
00146 m_dev = m_dev->next;
00147 if( !m_dev )
00148 m_busses = m_busses->next;
00149
00150
00151 return true;
00152 }
00153 }
00154 }
00155 return false;
00156 }
00157
00158
00159
00160
00161
00162 Device::Device(Usb::DeviceIDType id, int timeout)
00163 : m_id(id),
00164 m_timeout(timeout)
00165 {
00166 dout("usb_open(" << std::dec << id << ")");
00167 if( !id )
00168 throw Error("invalid USB device ID");
00169 m_handle = usb_open(id);
00170 if( !m_handle )
00171 throw Error("open failed");
00172 }
00173
00174 Device::~Device()
00175 {
00176 dout("usb_close(" << std::dec << m_handle << ")");
00177 usb_close(m_handle);
00178 }
00179
00180 bool Device::SetConfiguration(unsigned char cfg)
00181 {
00182 dout("usb_set_configuration(" << std::dec << m_handle << ", 0x" << std::hex << (unsigned int) cfg << ")");
00183 int ret = usb_set_configuration(m_handle, cfg);
00184 m_lasterror = ret;
00185 return ret >= 0;
00186 }
00187
00188 bool Device::ClearHalt(int ep)
00189 {
00190 dout("usb_clear_halt(" << std::dec << m_handle << ", 0x" << std::hex << ep << ")");
00191 int ret = usb_clear_halt(m_handle, ep);
00192 m_lasterror = ret;
00193 return ret >= 0;
00194 }
00195
00196 bool Device::Reset()
00197 {
00198 dout("usb_reset(" << std::dec << m_handle << ")");
00199 int ret = usb_reset(m_handle);
00200 m_lasterror = ret;
00201 return ret == 0;
00202 }
00203
00204 bool Device::BulkRead(int ep, Barry::Data &data, int timeout)
00205 {
00206 int ret;
00207 do {
00208 data.QuickZap();
00209 ret = usb_bulk_read(m_handle, ep,
00210 (char*) data.GetBuffer(), data.GetBufSize(),
00211 timeout == -1 ? m_timeout : timeout);
00212 if( ret < 0 && ret != -EINTR && ret != -EAGAIN ) {
00213 m_lasterror = ret;
00214 if( ret == -ETIMEDOUT )
00215 throw Timeout(ret, "Timeout in usb_bulk_read");
00216 else
00217 throw Error(ret, "Error in usb_bulk_read");
00218 }
00219 else if( ret > 0 )
00220 data.ReleaseBuffer(ret);
00221 } while( ret == -EINTR || ret == -EAGAIN );
00222
00223 return ret >= 0;
00224 }
00225
00226 bool Device::BulkWrite(int ep, const Barry::Data &data, int timeout)
00227 {
00228 ddout("BulkWrite to endpoint 0x" << std::hex << ep << ":\n" << data);
00229 int ret;
00230 do {
00231 ret = usb_bulk_write(m_handle, ep,
00232 (char*) data.GetData(), data.GetSize(),
00233 timeout == -1 ? m_timeout : timeout);
00234 if( ret < 0 && ret != -EINTR && ret != -EAGAIN ) {
00235 m_lasterror = ret;
00236 if( ret == -ETIMEDOUT )
00237 throw Timeout(ret, "Timeout in usb_bulk_write (1)");
00238 else
00239 throw Error(ret, "Error in usb_bulk_write (1)");
00240 }
00241 } while( ret == -EINTR || ret == -EAGAIN );
00242
00243 return ret >= 0;
00244 }
00245
00246 bool Device::BulkWrite(int ep, const void *data, size_t size, int timeout)
00247 {
00248 #ifdef __DEBUG_MODE__
00249 Barry::Data dump(data, size);
00250 ddout("BulkWrite to endpoint 0x" << std::hex << ep << ":\n" << dump);
00251 #endif
00252
00253 int ret;
00254 do {
00255 ret = usb_bulk_write(m_handle, ep,
00256 (char*) data, size,
00257 timeout == -1 ? m_timeout : timeout);
00258 if( ret < 0 && ret != -EINTR && ret != -EAGAIN ) {
00259 m_lasterror = ret;
00260 if( ret == -ETIMEDOUT )
00261 throw Timeout(ret, "Timeout in usb_bulk_write (2)");
00262 else
00263 throw Error(ret, "Error in usb_bulk_write (2)");
00264 }
00265 } while( ret == -EINTR || ret == -EAGAIN );
00266
00267 return ret >= 0;
00268 }
00269
00270 bool Device::InterruptRead(int ep, Barry::Data &data, int timeout)
00271 {
00272 int ret;
00273 do {
00274 data.QuickZap();
00275 ret = usb_interrupt_read(m_handle, ep,
00276 (char*) data.GetBuffer(), data.GetBufSize(),
00277 timeout == -1 ? m_timeout : timeout);
00278 if( ret < 0 && ret != -EINTR && ret != -EAGAIN ) {
00279 m_lasterror = ret;
00280 if( ret == -ETIMEDOUT )
00281 throw Timeout(ret, "Timeout in usb_interrupt_read");
00282 else
00283 throw Error(ret, "Error in usb_interrupt_read");
00284 }
00285 else if( ret > 0 )
00286 data.ReleaseBuffer(ret);
00287 } while( ret == -EINTR || ret == -EAGAIN );
00288
00289 return ret >= 0;
00290 }
00291
00292 bool Device::InterruptWrite(int ep, const Barry::Data &data, int timeout)
00293 {
00294 ddout("InterruptWrite to endpoint 0x" << std::hex << ep << ":\n" << data);
00295
00296 int ret;
00297 do {
00298 ret = usb_interrupt_write(m_handle, ep,
00299 (char*) data.GetData(), data.GetSize(),
00300 timeout == -1 ? m_timeout : timeout);
00301 if( ret < 0 && ret != -EINTR && ret != -EAGAIN ) {
00302 m_lasterror = ret;
00303 if( ret == -ETIMEDOUT )
00304 throw Timeout(ret, "Timeout in usb_interrupt_write");
00305 else
00306 throw Error(ret, "Error in usb_interrupt_write");
00307 }
00308 } while( ret == -EINTR || ret == -EAGAIN );
00309
00310 return ret >= 0;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319 void Device::BulkDrain(int ep, int timeout)
00320 {
00321 try {
00322 Barry::Data data;
00323 while( BulkRead(ep, data, timeout) )
00324 ;
00325 }
00326 catch( Usb::Error & ) {}
00327 }
00328
00329
00330
00331
00332
00333
00334
00335
00336 bool Device::GetConfiguration(unsigned char &cfg)
00337 {
00338 int result = usb_control_msg(m_handle, 0x80, USB_REQ_GET_CONFIGURATION, 0, 0,
00339 (char*) &cfg, 1, m_timeout);
00340 m_lasterror = result;
00341 return result >= 0;
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 bool Device::SetAltInterface(int iface)
00354 {
00355 int result = usb_set_altinterface(m_handle, iface);
00356 m_lasterror = result;
00357 return result >= 0;
00358 }
00359
00360
00361
00362
00363
00364
00365 Interface::Interface(Device &dev, int iface)
00366 : m_dev(dev), m_iface(iface)
00367 {
00368 dout("usb_claim_interface(" << dev.GetHandle() << ", 0x" << std::hex << iface << ")");
00369 int ret = usb_claim_interface(dev.GetHandle(), iface);
00370 if( ret < 0 )
00371 throw Error(ret, "claim interface failed");
00372 }
00373
00374 Interface::~Interface()
00375 {
00376 dout("usb_release_interface(" << m_dev.GetHandle() << ", 0x" << std::hex << m_iface << ")");
00377 usb_release_interface(m_dev.GetHandle(), m_iface);
00378 }
00379
00380
00381
00382
00383
00384
00385 bool EndpointDiscovery::Discover(struct usb_interface_descriptor *interface, int epcount)
00386 {
00387
00388 clear();
00389 m_valid = false;
00390
00391 EndpointPair pair;
00392
00393 if( !interface || !interface->endpoint ) {
00394 dout("EndpointDiscovery::Discover: empty interface pointer");
00395 return false;
00396 }
00397
00398 for( int i = 0; i < epcount; i++ ) {
00399
00400 usb_endpoint_descriptor desc;
00401 desc = interface->endpoint[i];
00402 dout(" endpoint_desc #" << std::dec << i << " loaded"
00403 << "\nbLength: " << std::dec << (unsigned ) desc.bLength
00404 << "\nbDescriptorType: " << std::dec << (unsigned ) desc.bDescriptorType
00405 << "\nbEndpointAddress: 0x" << std::hex << (unsigned ) desc.bEndpointAddress
00406 << "\nbmAttributes: 0x" << std::hex << (unsigned ) desc.bmAttributes
00407 << "\nwMaxPacketSize: " << std::dec << (unsigned ) desc.wMaxPacketSize
00408 << "\nbInterval: " << std::dec << (unsigned ) desc.bInterval
00409 << "\nbRefresh: " << std::dec << (unsigned ) desc.bRefresh
00410 << "\nbSynchAddress: " << std::dec << (unsigned ) desc.bSynchAddress
00411 << "\n"
00412 );
00413
00414
00415 (*this)[desc.bEndpointAddress] = desc;
00416 dout(" endpoint added to map with bEndpointAddress: 0x" << std::hex << (unsigned int)desc.bEndpointAddress);
00417
00418
00419
00420
00421
00422
00423
00424
00425 unsigned char type = desc.bmAttributes & USB_ENDPOINT_TYPE_MASK;
00426 if( desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK ) {
00427
00428 pair.read = desc.bEndpointAddress;
00429 dout(" pair.read = 0x" << std::hex << (unsigned int)pair.read);
00430 if( pair.IsTypeSet() && pair.type != type ) {
00431
00432 pair.write = 0;
00433 }
00434 }
00435 else {
00436
00437 pair.write = desc.bEndpointAddress;
00438 dout(" pair.write = 0x" << std::hex << (unsigned int)pair.write);
00439 if( pair.IsTypeSet() && pair.type != type ) {
00440
00441 pair.read = 0;
00442 }
00443 }
00444
00445 pair.type = type;
00446 dout(" pair.type = 0x" << std::hex << (unsigned int)pair.type);
00447
00448
00449 if( pair.IsComplete() ) {
00450 m_endpoints.push_back(pair);
00451 dout(" pair added! ("
00452 << "read: 0x" << std::hex << (unsigned int)pair.read << ","
00453 << "write: 0x" << std::hex << (unsigned int)pair.write << ","
00454 << "type: 0x" << std::hex << (unsigned int)pair.type << ")");
00455 pair = EndpointPair();
00456 }
00457 }
00458
00459
00460
00461 if( interface->extra ) {
00462 dout("while parsing endpoints, found a block of extra descriptors:");
00463 Barry::Data data(interface->extra, interface->extralen);
00464 dout(data);
00465 }
00466
00467 return m_valid = true;
00468 }
00469
00470
00471
00472
00473
00474 bool InterfaceDiscovery::DiscoverInterface(struct usb_interface *interface)
00475 {
00476 if( !interface->altsetting ) {
00477 dout("InterfaceDiscovery::DiscoverIterface: empty altsetting");
00478
00479
00480
00481 return true;
00482 }
00483
00484 for( int i = 0; i < interface->num_altsetting; i++ ) {
00485
00486 InterfaceDesc desc;
00487 desc.desc = interface->altsetting[i];
00488 dout(" interface_desc #" << std::dec << i << " loaded"
00489 << "\nbLength: " << std::dec << (unsigned) desc.desc.bLength
00490 << "\nbDescriptorType: " << std::dec << (unsigned) desc.desc.bDescriptorType
00491 << "\nbInterfaceNumber: " << std::dec << (unsigned) desc.desc.bInterfaceNumber
00492 << "\nbAlternateSetting: " << std::dec << (unsigned) desc.desc.bAlternateSetting
00493 << "\nbNumEndpoints: " << std::dec << (unsigned) desc.desc.bNumEndpoints
00494 << "\nbInterfaceClass: " << std::dec << (unsigned) desc.desc.bInterfaceClass
00495 << "\nbInterfaceSubClass: " << std::dec << (unsigned) desc.desc.bInterfaceSubClass
00496 << "\nbInterfaceProtocol: " << std::dec << (unsigned) desc.desc.bInterfaceProtocol
00497 << "\niInterface: " << std::dec << (unsigned) desc.desc.iInterface
00498 << "\n"
00499 );
00500
00501
00502 if( !desc.endpoints.Discover(&desc.desc, desc.desc.bNumEndpoints) ) {
00503 dout(" endpoint discovery failed for bInterfaceNumber: " << std::dec << (unsigned int)desc.desc.bInterfaceNumber << ", not added to map.");
00504 return false;
00505 }
00506
00507
00508 (*this)[desc.desc.bInterfaceNumber] = desc;
00509 dout(" interface added to map with bInterfaceNumber: " << std::dec << (unsigned int)desc.desc.bInterfaceNumber);
00510 }
00511 return true;
00512 }
00513
00514 bool InterfaceDiscovery::Discover(Usb::DeviceIDType devid, int cfgidx, int ifcount)
00515 {
00516
00517 clear();
00518 m_valid = false;
00519
00520 if( !devid || !devid->config || !devid->config[cfgidx].interface ) {
00521 dout("InterfaceDiscovery::Discover: empty devid/config/interface");
00522 return false;
00523 }
00524
00525 for( int i = 0; i < ifcount; i++ ) {
00526 if( !DiscoverInterface(&devid->config[cfgidx].interface[i]) )
00527 return false;
00528 }
00529
00530 return m_valid = true;
00531 }
00532
00533
00534
00535
00536
00537 bool ConfigDiscovery::Discover(Usb::DeviceIDType devid, int cfgcount)
00538 {
00539
00540 clear();
00541 m_valid = false;
00542
00543 for( int i = 0; i < cfgcount; i++ ) {
00544
00545 ConfigDesc desc;
00546 if( !devid || !devid->config ) {
00547 dout("ConfigDiscovery::Discover: empty devid or config");
00548 return false;
00549 }
00550 desc.desc = devid->config[i];
00551 dout(" config_desc #" << std::dec << i << " loaded"
00552 << "\nbLength: " << std::dec << (unsigned int) desc.desc.bLength
00553 << "\nbDescriptorType: " << std::dec << (unsigned int) desc.desc.bDescriptorType
00554 << "\nwTotalLength: " << std::dec << (unsigned int) desc.desc.wTotalLength
00555 << "\nbNumInterfaces: " << std::dec << (unsigned int) desc.desc.bNumInterfaces
00556 << "\nbConfigurationValue: " << std::dec << (unsigned int) desc.desc.bConfigurationValue
00557 << "\niConfiguration: " << std::dec << (unsigned int) desc.desc.iConfiguration
00558 << "\nbmAttributes: 0x" << std::hex << (unsigned int) desc.desc.bmAttributes
00559 << "\nMaxPower: " << std::dec << (unsigned int) desc.desc.MaxPower
00560 << "\n"
00561 );
00562
00563
00564
00565 if( desc.desc.extra ) {
00566 dout("while parsing config descriptor, found a block of extra descriptors:");
00567 Barry::Data data(desc.desc.extra, desc.desc.extralen);
00568 dout(data);
00569 }
00570
00571
00572 if( !desc.interfaces.Discover(devid, i, desc.desc.bNumInterfaces) ) {
00573 dout(" config discovery failed for bConfigurationValue: " << std::dec << (unsigned int)desc.desc.bConfigurationValue << ", not added to map.");
00574 return false;
00575 }
00576
00577
00578 (*this)[desc.desc.bConfigurationValue] = desc;
00579 dout(" config added to map with bConfigurationValue: " << std::dec << (unsigned int)desc.desc.bConfigurationValue);
00580 }
00581
00582 return m_valid = true;
00583 }
00584
00585
00586
00587
00588
00589 DeviceDiscovery::DeviceDiscovery(Usb::DeviceIDType devid)
00590 : m_valid(false)
00591 {
00592 Discover(devid);
00593 }
00594
00595 bool DeviceDiscovery::Discover(Usb::DeviceIDType devid)
00596 {
00597
00598 configs.clear();
00599 m_valid = false;
00600
00601
00602 if( !devid ) {
00603 dout("DeviceDiscovery::Discover: empty devid");
00604 return false;
00605 }
00606
00607 desc = devid->descriptor;
00608 dout("device_desc loaded"
00609 << "\nbLength: " << std::dec << (unsigned int) desc.bLength
00610 << "\nbDescriptorType: " << std::dec << (unsigned int) desc.bDescriptorType
00611 << "\nbcdUSB: 0x" << std::hex << (unsigned int) desc.bcdUSB
00612 << "\nbDeviceClass: " << std::dec << (unsigned int) desc.bDeviceClass
00613 << "\nbDeviceSubClass: " << std::dec << (unsigned int) desc.bDeviceSubClass
00614 << "\nbDeviceProtocol: " << std::dec << (unsigned int) desc.bDeviceProtocol
00615 << "\nbMaxPacketSize0: " << std::dec << (unsigned int) desc.bMaxPacketSize0
00616 << "\nidVendor: 0x" << std::hex << (unsigned int) desc.idVendor
00617 << "\nidProduct: 0x" << std::hex << (unsigned int) desc.idProduct
00618 << "\nbcdDevice: 0x" << std::hex << (unsigned int) desc.bcdDevice
00619 << "\niManufacturer: " << std::dec << (unsigned int) desc.iManufacturer
00620 << "\niProduct: " << std::dec << (unsigned int) desc.iProduct
00621 << "\niSerialNumber: " << std::dec << (unsigned int) desc.iSerialNumber
00622 << "\nbNumConfigurations: " << std::dec << (unsigned int) desc.bNumConfigurations
00623 << "\n"
00624 );
00625
00626 m_valid = configs.Discover(devid, desc.bNumConfigurations);
00627 return m_valid;
00628 }
00629
00630 }
00631