Bumped copyright dates for 2013
[barry.git] / src / usbwrap_libusb.cc
blob1681288873dd5dcdbf893516d55f12352ef335fc
1 ///
2 /// \file usbwrap_libusb.cc
3 /// USB API wrapper for libusb version 0.1
4 ///
6 /*
7 Copyright (C) 2005-2013, Chris Frey
8 Portions Copyright (C) 2011, RealVNC Ltd.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License in the COPYING file at the
20 root directory of this project for more details.
23 #include "i18n.h"
25 #include "usbwrap_libusb.h"
27 #include "debug.h"
28 #include "data.h"
29 #include <errno.h>
30 #include <string.h>
31 #include <iostream>
32 #include <sstream>
33 #include <algorithm>
35 #ifndef __DEBUG_MODE__
36 #define __DEBUG_MODE__
37 #endif
38 #include "debug.h"
40 namespace Usb {
42 // helper function to make deleting pointers in maps and vectors easier
43 template<typename T> static void deletePtr(T* ptr) {
44 delete ptr;
47 template<typename K, typename T> static void deleteMapPtr(std::pair<K,T*> ptr) {
48 delete ptr.second;
51 ///////////////////////////////////////////////////////////////////////////////
52 // Static functions
54 std::string LibraryInterface::GetLastErrorString(int /*libusb_errcode*/)
56 // Errcode is unused by libusb, so just call the last error
57 return std::string(usb_strerror());
60 int LibraryInterface::TranslateErrcode(int libusb_errcode)
62 // libusb errcode == system errcode
63 return libusb_errcode;
66 bool LibraryInterface::Init(int *libusb_errno)
68 // if the environment variable USB_DEBUG is set, that
69 // level value will be used instead of our 9 below...
70 // if you need to *force* this to 9, call SetDataDump(true)
71 // after Init()
72 usb_init();
73 // Can never fail, so return success
74 return true;
77 void LibraryInterface::Uninit()
79 // Nothing to do
82 void LibraryInterface::SetDataDump(bool data_dump_mode)
84 if( data_dump_mode )
85 usb_set_debug(9);
86 else
87 usb_set_debug(0);
90 ///////////////////////////////////////////////////////////////////////////////
91 // DeviceID
93 DeviceID::DeviceID(DeviceIDImpl* impl)
94 : m_impl(impl)
98 DeviceID::~DeviceID()
102 const char* DeviceID::GetBusName() const
104 return m_impl->m_dev->bus->dirname;
107 uint16_t DeviceID::GetNumber() const
109 return m_impl->m_dev->devnum;
112 const char* DeviceID::GetFilename() const
114 return m_impl->m_dev->filename;
117 uint16_t DeviceID::GetIdProduct() const
119 return m_impl->m_dev->descriptor.idProduct;
122 std::string DeviceID::GetUsbName() const
124 // for libusb 0.1, we need both the bus name and the filename
125 // and we stay away from the product ID, since that requires
126 // communication with the device, which may not be possible
127 // in error conditions.
128 std::ostringstream oss;
129 oss << GetBusName() << ":" << GetFilename();
130 return oss.str();
133 ///////////////////////////////////////////////////////////////////////////////
134 // DeviceList
136 DeviceList::DeviceList()
137 : m_impl(new DeviceListImpl())
139 // Work out what devices are on the bus at the moment
140 usb_find_busses();
141 usb_find_devices();
142 struct usb_bus* busses = usb_get_busses();
143 for( ; busses; busses = busses->next ) {
144 struct usb_device* dev = busses->devices;
145 for( ; dev; dev = dev->next ) {
146 // Add the device to the list of devices
147 std::auto_ptr<DeviceIDImpl> impl( new DeviceIDImpl() );
148 impl->m_dev = dev;
149 DeviceID devID(impl.release());
150 m_impl->m_devices.push_back(devID);
155 DeviceList::~DeviceList()
160 static bool ToNum(const char *str, long &num)
162 char *end = 0;
163 num = strtol(str, &end, 10);
164 return num >= 0 && // no negative numbers
165 num != LONG_MIN && num != LONG_MAX && // no overflow
166 str != end && *end == '\0'; // whole string valid
170 // Linux treats bus and device path names as numbers, sometimes left
171 // padded with zeros. Other platforms, such as Windows, use strings,
172 // such as "bus-1" or similar.
174 // Here we try to convert each string to a number, and if successful,
175 // compare them. If unable to convert, then compare as strings.
176 // This way, "3" == "003" and "bus-foobar" == "bus-foobar".
178 static bool NameCompare(const char *n1, const char *n2)
180 long l1, l2;
181 if( ToNum(n1, l1) && ToNum(n2, l2) ) {
182 return l1 == l2;
184 else {
185 return strcmp(n1, n2) == 0;
189 std::vector<DeviceID> DeviceList::MatchDevices(int vendor, int product,
190 const char *busname, const char *devname)
192 std::vector<DeviceID> ret;
194 std::vector<DeviceID>::iterator iter = m_impl->m_devices.begin();
196 for( ; iter != m_impl->m_devices.end() ; ++iter ) {
197 struct usb_device* dev = iter->m_impl->m_dev;
199 // only search on given bus
200 if( busname && !NameCompare(busname, dev->bus->dirname) )
201 continue;
203 // search for specific device
204 if( devname && !NameCompare(devname, dev->filename) )
205 continue;
207 // is there a match?
208 if( dev->descriptor.idVendor == vendor &&
209 ( dev->descriptor.idProduct == product ||
210 product == PRODUCT_ANY )) {
211 ret.push_back(*iter);
215 return ret;
218 ///////////////////////////////////////////////////////////////////////////////
219 // Device
221 Device::Device(const Usb::DeviceID& id, int timeout)
222 : m_id(id),
223 m_handle(new DeviceHandle()),
224 m_timeout(timeout)
226 dout("usb_open(" << std::dec << id.m_impl.get() << ")");
227 if( !id.m_impl.get() )
228 throw Error(_("invalid USB device ID"));
229 m_handle->m_handle = usb_open(id.m_impl->m_dev);
230 if( !m_handle->m_handle )
231 throw Error(_("Failed to open USB device. Please check your system's USB device permissions."));
234 Device::~Device()
236 dout("usb_close(" << std::dec << m_handle->m_handle << ")");
237 usb_close(m_handle->m_handle);
240 bool Device::SetConfiguration(unsigned char cfg)
242 dout("usb_set_configuration(" << std::dec << m_handle->m_handle << ", 0x" << std::hex << (unsigned int) cfg << ")");
243 int ret = usb_set_configuration(m_handle->m_handle, cfg);
244 m_lasterror = ret;
245 return ret >= 0;
248 bool Device::ClearHalt(int ep)
250 dout("usb_clear_halt(" << std::dec << m_handle->m_handle << ", 0x" << std::hex << ep << ")");
251 int ret = usb_clear_halt(m_handle->m_handle, ep);
252 m_lasterror = ret;
253 return ret >= 0;
256 bool Device::Reset()
258 dout("usb_reset(" << std::dec << m_handle->m_handle << ")");
259 int ret = usb_reset(m_handle->m_handle);
260 m_lasterror = ret;
261 return ret == 0;
264 bool Device::BulkRead(int ep, Barry::Data &data, int timeout)
266 int ret;
267 do {
268 data.QuickZap();
269 ret = usb_bulk_read(m_handle->m_handle, ep,
270 (char*) data.GetBuffer(), data.GetBufSize(),
271 timeout == -1 ? m_timeout : timeout);
272 if( ret < 0 && ret != -EINTR && ret != -EAGAIN ) {
273 m_lasterror = ret;
274 if( ret == -ETIMEDOUT )
275 throw Timeout(ret, _("Timeout in usb_bulk_read"));
276 else {
277 std::ostringstream oss;
278 oss << _("Error in usb_bulk_read(")
279 << m_handle->m_handle << ", "
280 << ep << ", buf, "
281 << data.GetBufSize() << ")";
282 throw Error(ret, oss.str());
285 else if( ret > 0 )
286 data.ReleaseBuffer(ret);
287 } while( ret == -EINTR || ret == -EAGAIN );
289 return ret >= 0;
292 bool Device::BulkWrite(int ep, const Barry::Data &data, int timeout)
294 ddout("BulkWrite to endpoint 0x" << std::hex << ep << ":\n" << data);
295 int ret;
296 do {
297 ret = usb_bulk_write(m_handle->m_handle, ep,
298 (char*) data.GetData(), data.GetSize(),
299 timeout == -1 ? m_timeout : timeout);
300 if( ret < 0 && ret != -EINTR && ret != -EAGAIN ) {
301 m_lasterror = ret;
302 if( ret == -ETIMEDOUT )
303 throw Timeout(ret, _("Timeout in usb_bulk_write (1)"));
304 else
305 throw Error(ret, _("Error in usb_bulk_write (1)"));
307 } while( ret == -EINTR || ret == -EAGAIN );
309 return ret >= 0;
312 bool Device::BulkWrite(int ep, const void *data, size_t size, int timeout)
314 #ifdef __DEBUG_MODE__
315 Barry::Data dump(data, size);
316 ddout("BulkWrite to endpoint 0x" << std::hex << ep << ":\n" << dump);
317 #endif
319 int ret;
320 do {
321 ret = usb_bulk_write(m_handle->m_handle, ep,
322 (char*) data, size,
323 timeout == -1 ? m_timeout : timeout);
324 if( ret < 0 && ret != -EINTR && ret != -EAGAIN ) {
325 m_lasterror = ret;
326 if( ret == -ETIMEDOUT )
327 throw Timeout(ret, _("Timeout in usb_bulk_write (2)"));
328 else
329 throw Error(ret, _("Error in usb_bulk_write (2)"));
331 } while( ret == -EINTR || ret == -EAGAIN );
333 return ret >= 0;
336 bool Device::InterruptRead(int ep, Barry::Data &data, int timeout)
338 int ret;
339 do {
340 data.QuickZap();
341 ret = usb_interrupt_read(m_handle->m_handle, ep,
342 (char*) data.GetBuffer(), data.GetBufSize(),
343 timeout == -1 ? m_timeout : timeout);
344 if( ret < 0 && ret != -EINTR && ret != -EAGAIN ) {
345 m_lasterror = ret;
346 if( ret == -ETIMEDOUT )
347 throw Timeout(ret, _("Timeout in usb_interrupt_read"));
348 else
349 throw Error(ret, _("Error in usb_interrupt_read"));
351 else if( ret > 0 )
352 data.ReleaseBuffer(ret);
353 } while( ret == -EINTR || ret == -EAGAIN );
355 return ret >= 0;
358 bool Device::InterruptWrite(int ep, const Barry::Data &data, int timeout)
360 ddout("InterruptWrite to endpoint 0x" << std::hex << ep << ":\n" << data);
362 int ret;
363 do {
364 ret = usb_interrupt_write(m_handle->m_handle, ep,
365 (char*) data.GetData(), data.GetSize(),
366 timeout == -1 ? m_timeout : timeout);
367 if( ret < 0 && ret != -EINTR && ret != -EAGAIN ) {
368 m_lasterror = ret;
369 if( ret == -ETIMEDOUT )
370 throw Timeout(ret, _("Timeout in usb_interrupt_write"));
371 else
372 throw Error(ret, _("Error in usb_interrupt_write"));
374 } while( ret == -EINTR || ret == -EAGAIN );
376 return ret >= 0;
380 // BulkDrain
382 /// Reads anything available on the given endpoint, with a low timeout,
383 /// in order to clear any pending reads.
385 void Device::BulkDrain(int ep, int timeout)
387 try {
388 Barry::Data data;
389 while( BulkRead(ep, data, timeout) )
392 catch( Usb::Error & ) {}
396 // GetConfiguration
398 /// Uses the GET_CONFIGURATION control message to determine the currently
399 /// selected USB configuration, returning it in the cfg argument.
400 /// If unsuccessful, returns false.
402 bool Device::GetConfiguration(unsigned char &cfg)
404 int result = usb_control_msg(m_handle->m_handle, 0x80, USB_REQ_GET_CONFIGURATION, 0, 0,
405 (char*) &cfg, 1, m_timeout);
406 m_lasterror = result;
407 return result >= 0;
410 // Returns the current power level of the device, or 0 if unknown
411 int Device::GetPowerLevel()
413 if( !m_id.m_impl->m_dev->config ||
414 !m_id.m_impl->m_dev->descriptor.bNumConfigurations < 1 )
415 return 0;
417 return m_id.m_impl->m_dev->config[0].MaxPower;
420 std::string Device::GetSimpleSerialNumber()
422 std::string sn;
423 char buf[1024];
424 int ret = usb_get_string_simple(m_handle->m_handle,
425 m_id.m_impl->m_dev->descriptor.iSerialNumber, buf, sizeof(buf));
426 if( ret > 0 )
427 sn.assign(buf, ret);
428 return sn;
431 bool Device::IsAttachKernelDriver(int iface)
433 int ret;
434 char buffer[64];
436 #if LIBUSB_HAS_GET_DRIVER_NP
437 ret = usb_get_driver_np(m_handle->m_handle, iface, buffer, sizeof(buffer));
438 if (ret == 0) {
439 dout("interface (" << m_handle->m_handle << ", 0x" << std::hex << iface
440 << ") already claimed by driver \"" << buffer << "\"");
441 return true;
443 m_lasterror = ret;
444 #else
445 m_lasterror = -ENOSYS;
446 #endif
448 return false;
451 // Requests that the kernel driver is detached, returning false on failure
452 bool Device::DetachKernelDriver(int iface)
454 #if LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
455 int result = usb_detach_kernel_driver_np(m_handle->m_handle, iface);
456 m_lasterror = result;
457 return result >= 0;
458 #else
459 m_lasterror = -ENOSYS;
460 return false;
461 #endif
464 // Sends a control message to the device, returning false on failure
465 bool Device::ControlMsg(int requesttype, int request, int value,
466 int index, char *bytes, int size, int timeout)
468 int result = usb_control_msg(m_handle->m_handle,
469 requesttype, request, value, index,
470 bytes, size, timeout);
471 m_lasterror = result;
472 return result >= 0;
476 int Device::FindInterface(int ifaceClass)
478 struct usb_config_descriptor *cfg = m_id.m_impl->m_dev->config;
480 if( cfg ) {
482 for( unsigned i = 0; cfg->interface && i < cfg->bNumInterfaces; i++ ) {
483 struct usb_interface *iface = &cfg->interface[i];
484 for( int a = 0; iface->altsetting && a < iface->num_altsetting; a++ ) {
485 struct usb_interface_descriptor *id = &iface->altsetting[a];
486 if( id->bInterfaceClass == ifaceClass )
487 return id->bInterfaceNumber;
492 return -1;
496 ///////////////////////////////////////////////////////////////////////////////
497 // Interface
499 Interface::Interface(Device &dev, int iface)
500 : m_dev(dev), m_iface(iface)
502 dout("usb_claim_interface(" << dev.GetHandle()->m_handle << ", 0x" << std::hex << iface << ")");
503 int ret = usb_claim_interface(dev.GetHandle()->m_handle, iface);
504 if( ret < 0 )
505 throw Error(ret, _("claim interface failed"));
508 Interface::~Interface()
510 dout("usb_release_interface(" << m_dev.GetHandle()->m_handle << ", 0x" << std::hex << m_iface << ")");
511 usb_release_interface(m_dev.GetHandle()->m_handle, m_iface);
515 // SetAltInterface
517 /// Uses the usb_set_altinterface() function to set the currently
518 /// selected USB alternate setting of the current interface.
519 /// The iface parameter passed in should be a value specified
520 /// in the bAlternateSetting descriptor field.
521 /// If unsuccessful, returns false.
523 bool Interface::SetAltInterface(int altSetting)
525 int result = usb_set_altinterface(m_dev.GetHandle()->m_handle, altSetting);
526 m_dev.SetLastError(result);
527 return result >= 0;
530 //////////////////////////////////////////////////////////////////
531 // DeviceDescriptor
533 DeviceDescriptor::DeviceDescriptor(DeviceID& devid)
534 : m_impl(new DeviceDescriptorImpl())
536 if( !devid.m_impl.get() ) {
537 dout("DeviceDescriptor: empty devid");
538 return;
540 // Copy the descriptor over to our memory
541 m_impl->m_dev = devid.m_impl->m_dev;
542 m_impl->m_desc = devid.m_impl->m_dev->descriptor;
543 dout("device_desc loaded"
544 << "\nbLength: " << std::dec << (unsigned int) m_impl->m_desc.bLength
545 << "\nbDescriptorType: " << std::dec << (unsigned int) m_impl->m_desc.bDescriptorType
546 << "\nbcdUSB: 0x" << std::hex << (unsigned int) m_impl->m_desc.bcdUSB
547 << "\nbDeviceClass: " << std::dec << (unsigned int) m_impl->m_desc.bDeviceClass
548 << "\nbDeviceSubClass: " << std::dec << (unsigned int) m_impl->m_desc.bDeviceSubClass
549 << "\nbDeviceProtocol: " << std::dec << (unsigned int) m_impl->m_desc.bDeviceProtocol
550 << "\nbMaxPacketSize0: " << std::dec << (unsigned int) m_impl->m_desc.bMaxPacketSize0
551 << "\nidVendor: 0x" << std::hex << (unsigned int) m_impl->m_desc.idVendor
552 << "\nidProduct: 0x" << std::hex << (unsigned int) m_impl->m_desc.idProduct
553 << "\nbcdDevice: 0x" << std::hex << (unsigned int) m_impl->m_desc.bcdDevice
554 << "\niManufacturer: " << std::dec << (unsigned int) m_impl->m_desc.iManufacturer
555 << "\niProduct: " << std::dec << (unsigned int) m_impl->m_desc.iProduct
556 << "\niSerialNumber: " << std::dec << (unsigned int) m_impl->m_desc.iSerialNumber
557 << "\nbNumConfigurations: " << std::dec << (unsigned int) m_impl->m_desc.bNumConfigurations
558 << "\n"
561 // Create all the configs
562 for( int i = 0; i < m_impl->m_desc.bNumConfigurations; ++i ) {
563 std::auto_ptr<ConfigDescriptor> ptr(new ConfigDescriptor(*this, i));
564 (*this)[ptr->GetNumber()] = ptr.get();
565 ptr.release();
569 DeviceDescriptor::~DeviceDescriptor()
571 // Delete any pointers in the map
572 std::for_each(begin(),
573 end(),
574 deleteMapPtr<int, ConfigDescriptor>);
577 ///////////////////////////////////////////////////////////////////
578 // ConfigDescriptor
580 ConfigDescriptor::ConfigDescriptor(DeviceDescriptor& dev, int cfgnumber)
581 : m_impl(new ConfigDescriptorImpl())
583 // Copy the config descriptor locally
584 m_impl->m_desc = dev.m_impl->m_dev->config[cfgnumber];
585 dout(" config_desc #" << std::dec << cfgnumber << " loaded"
586 << "\nbLength: " << std::dec << (unsigned int) m_impl->m_desc.bLength
587 << "\nbDescriptorType: " << std::dec << (unsigned int) m_impl->m_desc.bDescriptorType
588 << "\nwTotalLength: " << std::dec << (unsigned int) m_impl->m_desc.wTotalLength
589 << "\nbNumInterfaces: " << std::dec << (unsigned int) m_impl->m_desc.bNumInterfaces
590 << "\nbConfigurationValue: " << std::dec << (unsigned int) m_impl->m_desc.bConfigurationValue
591 << "\niConfiguration: " << std::dec << (unsigned int) m_impl->m_desc.iConfiguration
592 << "\nbmAttributes: 0x" << std::hex << (unsigned int) m_impl->m_desc.bmAttributes
593 << "\nMaxPower: " << std::dec << (unsigned int) m_impl->m_desc.MaxPower
594 << "\n"
597 // just for debugging purposes, check for extra descriptors, and
598 // dump them to dout if they exist
599 if( m_impl->m_desc.extra ) {
600 dout("while parsing config descriptor, found a block of extra descriptors:");
601 Barry::Data data(m_impl->m_desc.extra, m_impl->m_desc.extralen);
602 dout(data);
605 // Create all the interfaces
606 for( int i = 0; i < m_impl->m_desc.bNumInterfaces; ++i ) {
607 struct usb_interface* interface = &(m_impl->m_desc.interface[i]);
608 if( !interface->altsetting ) {
609 dout("ConfigDescriptor: empty altsetting");
610 // some devices are buggy and return a higher bNumInterfaces
611 // than the number of interfaces available... in this case
612 // we just skip and continue
613 continue;
615 for( int j = 0; j < interface->num_altsetting; ++j ) {
616 std::auto_ptr<InterfaceDescriptor> ptr(
617 new InterfaceDescriptor(*this, i, j));
618 (*this)[ptr->GetNumber()] = ptr.get();
619 ptr.release();
624 ConfigDescriptor::~ConfigDescriptor()
626 // Delete any pointers in the map
627 std::for_each(begin(),
628 end(),
629 deleteMapPtr<int, InterfaceDescriptor>);
632 uint8_t ConfigDescriptor::GetNumber() const {
633 return m_impl->m_desc.bConfigurationValue;
636 /////////////////////////////////////////////////////////////////////////
637 // InterfaceDescriptor
639 InterfaceDescriptor::InterfaceDescriptor(ConfigDescriptor& cfg,
640 int interface, int altsetting)
641 : m_impl(new InterfaceDescriptorImpl())
643 // Copy the descriptor
644 m_impl->m_desc = cfg.m_impl->m_desc
645 .interface[interface]
646 .altsetting[altsetting];
647 dout(" interface_desc #" << std::dec << interface << " loaded"
648 << "\nbLength: " << std::dec << (unsigned) m_impl->m_desc.bLength
649 << "\nbDescriptorType: " << std::dec << (unsigned) m_impl->m_desc.bDescriptorType
650 << "\nbInterfaceNumber: " << std::dec << (unsigned) m_impl->m_desc.bInterfaceNumber
651 << "\nbAlternateSetting: " << std::dec << (unsigned) m_impl->m_desc.bAlternateSetting
652 << "\nbNumEndpoints: " << std::dec << (unsigned) m_impl->m_desc.bNumEndpoints
653 << "\nbInterfaceClass: " << std::dec << (unsigned) m_impl->m_desc.bInterfaceClass
654 << "\nbInterfaceSubClass: " << std::dec << (unsigned) m_impl->m_desc.bInterfaceSubClass
655 << "\nbInterfaceProtocol: " << std::dec << (unsigned) m_impl->m_desc.bInterfaceProtocol
656 << "\niInterface: " << std::dec << (unsigned) m_impl->m_desc.iInterface
657 << "\n"
660 if( !m_impl->m_desc.endpoint ) {
661 dout("InterfaceDescriptor: empty interface pointer");
662 return;
665 // Create all the endpoints
666 for( int i = 0; i < m_impl->m_desc.bNumEndpoints; ++i ) {
667 std::auto_ptr<EndpointDescriptor> ptr (
668 new EndpointDescriptor(*this, i));
669 this->push_back(ptr.get());
670 ptr.release();
673 // just for debugging purposes, check for extra descriptors, and
674 // dump them to dout if they exist
675 if( m_impl->m_desc.extra ) {
676 dout("while parsing interface descriptor, found a block of extra descriptors:");
677 Barry::Data data(m_impl->m_desc.extra, m_impl->m_desc.extralen);
678 dout(data);
682 InterfaceDescriptor::~InterfaceDescriptor()
684 // Delete any pointers in the vector
685 std::for_each(begin(),
686 end(),
687 deletePtr<EndpointDescriptor>);
690 uint8_t InterfaceDescriptor::GetClass() const
692 return m_impl->m_desc.bInterfaceClass;
695 uint8_t InterfaceDescriptor::GetNumber() const
697 return m_impl->m_desc.bInterfaceNumber;
700 uint8_t InterfaceDescriptor::GetAltSetting() const
702 return m_impl->m_desc.bAlternateSetting;
705 /////////////////////////////////////////////////////////////////////////////////
706 // EndpointDescriptor
708 EndpointDescriptor::EndpointDescriptor(InterfaceDescriptor& interface, int endpoint)
709 : m_impl(new EndpointDescriptorImpl()),
710 m_read(false),
711 m_addr(0),
712 m_type(InvalidType)
714 // Copy the descriptor
715 m_impl->m_desc = interface.m_impl->m_desc.endpoint[endpoint];
716 dout(" endpoint_desc #" << std::dec << endpoint << " loaded"
717 << "\nbLength: " << std::dec << (unsigned ) m_impl->m_desc.bLength
718 << "\nbDescriptorType: " << std::dec << (unsigned ) m_impl->m_desc.bDescriptorType
719 << "\nbEndpointAddress: 0x" << std::hex << (unsigned ) m_impl->m_desc.bEndpointAddress
720 << "\nbmAttributes: 0x" << std::hex << (unsigned ) m_impl->m_desc.bmAttributes
721 << "\nwMaxPacketSize: " << std::dec << (unsigned ) m_impl->m_desc.wMaxPacketSize
722 << "\nbInterval: " << std::dec << (unsigned ) m_impl->m_desc.bInterval
723 << "\nbRefresh: " << std::dec << (unsigned ) m_impl->m_desc.bRefresh
724 << "\nbSynchAddress: " << std::dec << (unsigned ) m_impl->m_desc.bSynchAddress
725 << "\n"
727 // Set up variables
728 m_read = ((m_impl->m_desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) != 0);
729 m_addr = (m_impl->m_desc.bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK);
730 int type = (m_impl->m_desc.bmAttributes & USB_ENDPOINT_TYPE_MASK);
731 m_type = static_cast<Usb::EndpointDescriptor::EpType>(type);
733 // just for debugging purposes, check for extra descriptors, and
734 // dump them to dout if they exist
735 if( m_impl->m_desc.extra ) {
736 dout("while parsing endpoint descriptor, found a block of extra descriptors:");
737 Barry::Data data(m_impl->m_desc.extra, m_impl->m_desc.extralen);
738 dout(data);
742 EndpointDescriptor::~EndpointDescriptor()
746 } // namespace Usb