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