The Pedigree Project  0.1
UsbDevice.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "modules/system/usb/UsbDevice.h"
21 #include "modules/system/usb/Usb.h"
22 #include "modules/system/usb/UsbConstants.h"
23 #include "modules/system/usb/UsbDescriptors.h"
24 #include "modules/system/usb/UsbHub.h"
25 #include "pedigree/kernel/Log.h"
26 #include "pedigree/kernel/utilities/PointerGuard.h"
27 #include "pedigree/kernel/utilities/assert.h"
28 #include "pedigree/kernel/utilities/new"
29 
30 UsbDevice::UsbDevice(UsbHub *pHub, uint8_t nPort, UsbSpeed speed)
31  : m_nAddress(0), m_nPort(nPort), m_Speed(speed), m_UsbState(Connected),
32  m_pDescriptor(0), m_pConfiguration(0), m_pInterface(0), m_pHub(pHub),
33  m_pContainer(0)
34 {
35 }
36 
38  : m_nAddress(pDev->m_nAddress), m_nPort(pDev->m_nPort),
39  m_Speed(pDev->m_Speed), m_UsbState(Connected),
42 {
43  // We have the same parent as pDev
44  m_pHub = pDev->m_pHub;
45 }
46 
48 {
49 }
50 
51 UsbDevice::DeviceDescriptor::DeviceDescriptor(UsbDeviceDescriptor *pDescriptor)
52 {
53  nBcdUsbRelease = pDescriptor->nBcdUsbRelease;
54  nClass = pDescriptor->nClass;
55  nSubclass = pDescriptor->nSubclass;
56  nProtocol = pDescriptor->nProtocol;
57  nMaxControlPacketSize = pDescriptor->nMaxControlPacketSize;
58  nVendorId = pDescriptor->nVendorId;
59  nProductId = pDescriptor->nProductId;
60  nBcdDeviceRelease = pDescriptor->nBcdDeviceRelease;
61  nVendorString = pDescriptor->nVendorString;
62  nProductString = pDescriptor->nProductString;
63  nSerialString = pDescriptor->nSerialString;
64  nConfigurations = pDescriptor->nConfigurations;
65 
66  delete pDescriptor;
67 }
68 
69 UsbDevice::DeviceDescriptor::~DeviceDescriptor()
70 {
71  for (size_t i = 0; i < configList.count(); i++)
72  delete configList[i];
73 }
74 
75 UsbDevice::ConfigDescriptor::ConfigDescriptor(
76  void *pConfigBuffer, size_t nConfigLength, UsbSpeed speed)
77 {
78  UsbConfigurationDescriptor *pDescriptor =
79  static_cast<UsbConfigurationDescriptor *>(pConfigBuffer);
80  nConfig = pDescriptor->nConfig;
81  nString = pDescriptor->nString;
82 
83  uint8_t *pBuffer = static_cast<uint8_t *>(pConfigBuffer);
84  size_t nOffset = pBuffer[0];
85  Interface *pCurrentInterface = 0;
86 
87  while (nOffset < nConfigLength)
88  {
89  size_t nLength = pBuffer[nOffset];
90  uint8_t nType = pBuffer[nOffset + 1];
91  if (nType == UsbDescriptor::Interface)
92  {
93  pCurrentInterface = new Interface(
94  reinterpret_cast<UsbInterfaceDescriptor *>(&pBuffer[nOffset]));
95  interfaceList.pushBack(pCurrentInterface);
96  }
97  else if (pCurrentInterface)
98  {
99  if (nType == UsbDescriptor::Endpoint)
100  pCurrentInterface->endpointList.pushBack(new Endpoint(
101  reinterpret_cast<UsbEndpointDescriptor *>(
102  &pBuffer[nOffset]),
103  speed));
104  else
105  pCurrentInterface->otherDescriptorList.pushBack(
106  new UnknownDescriptor(&pBuffer[nOffset], nType, nLength));
107  }
108  else
109  otherDescriptorList.pushBack(
110  new UnknownDescriptor(&pBuffer[nOffset], nType, nLength));
111  nOffset += nLength;
112  }
113  assert(interfaceList.count());
114 
115  delete pDescriptor;
116 }
117 
118 UsbDevice::ConfigDescriptor::~ConfigDescriptor()
119 {
120  for (size_t i = 0; i < interfaceList.count(); i++)
121  delete interfaceList[i];
122  for (size_t i = 0; i < otherDescriptorList.count(); i++)
123  delete otherDescriptorList[i];
124 }
125 
126 UsbDevice::Interface::Interface(UsbInterfaceDescriptor *pDescriptor)
127 {
128  nInterface = pDescriptor->nInterface;
129  nAlternateSetting = pDescriptor->nAlternateSetting;
130  nClass = pDescriptor->nClass;
131  nSubclass = pDescriptor->nSubclass;
132  nProtocol = pDescriptor->nProtocol;
133  nString = pDescriptor->nString;
134 }
135 
136 UsbDevice::Interface::~Interface()
137 {
138  for (size_t i = 0; i < endpointList.count(); i++)
139  delete endpointList[i];
140  for (size_t i = 0; i < otherDescriptorList.count(); i++)
141  delete otherDescriptorList[i];
142 }
143 
144 UsbDevice::Endpoint::Endpoint(
145  UsbEndpointDescriptor *pDescriptor, UsbSpeed speed)
146  : bDataToggle(false)
147 {
148  nEndpoint = pDescriptor->nEndpoint;
149  bIn = pDescriptor->bDirection;
150  bOut = !bIn;
151  nTransferType = pDescriptor->nTransferType;
152  nMaxPacketSize = pDescriptor->nMaxPacketSize;
153 }
154 
155 void UsbDevice::initialise(uint8_t nAddress)
156 {
157  // Check for late calls
158  if (m_UsbState > Connected)
159  {
160  ERROR("USB: UsbDevice::initialise called, but this device is already "
161  "initialised!");
162  return;
163  }
164 
165  // Assign the given address to this device
166  if (!controlRequest(0, UsbRequest::SetAddress, nAddress, 0))
167  {
168  WARNING(
169  "Device (" << nAddress
170  << "): couldn't assign an address to the device.");
171  return;
172  }
173  m_nAddress = nAddress;
174  m_UsbState = Addressed; // We now have an address
175 
176  // Get the device descriptor
177  size_t nDescriptorLength = getDescriptorLength(UsbDescriptor::Device, 0);
178  if (!nDescriptorLength)
179  {
180  m_UsbState = Connected;
181  WARNING(
182  "Device (" << nAddress
183  << "): address assignment worked, but couldn't get the "
184  "device descriptor length.");
185  return;
186  }
187 
188  void *pDeviceDescriptor =
189  getDescriptor(UsbDescriptor::Device, 0, nDescriptorLength);
190  if (!pDeviceDescriptor)
191  {
192  m_UsbState = Connected;
193  WARNING(
194  "Device (" << nAddress
195  << "): address assignment worked, but couldn't get a "
196  "device descriptor.");
197  return;
198  }
200  static_cast<UsbDeviceDescriptor *>(pDeviceDescriptor));
201  m_UsbState = HasDescriptors; // We now have the device descriptor
202 
203 // Debug dump of the device descriptor
204 #ifdef USB_VERBOSE_DEBUG
205  DEBUG_LOG(
206  "USB version: " << Dec << (m_pDescriptor->nBcdUsbRelease >> 8) << "."
207  << (m_pDescriptor->nBcdUsbRelease & 0xFF) << ".");
208  DEBUG_LOG(
209  "Device class/subclass/protocol: " << m_pDescriptor->nClass << "/"
210  << m_pDescriptor->nSubclass << "/"
211  << m_pDescriptor->nProtocol);
212  DEBUG_LOG(
213  "Maximum control packet size is "
214  << Dec << m_pDescriptor->nMaxControlPacketSize << Hex << " bytes.");
215  DEBUG_LOG(
216  "Vendor and product IDs: " << m_pDescriptor->nVendorId << ":"
217  << m_pDescriptor->nProductId << ".");
218  DEBUG_LOG(
219  "Device version: " << Dec << (m_pDescriptor->nBcdDeviceRelease >> 8)
220  << "." << (m_pDescriptor->nBcdDeviceRelease & 0xFF)
221  << Hex << ".");
222  DEBUG_LOG(
223  "Number of configurations: " << m_pDescriptor->nConfigurations << ".");
224  DEBUG_LOG(
225  "String indices: " << m_pDescriptor->nVendorString << ", "
226  << m_pDescriptor->nProductString << ", "
227  << m_pDescriptor->nSerialString);
228 #endif
229 
230  // Descriptor number for the configuration descriptor
231  uint8_t nConfigDescriptor = UsbDescriptor::Configuration;
232 
233 // Handle high-speed capable devices running at full-speed:
234 // If the device works at full-speed and it has a device qualifier descriptor,
235 // it means that the normal configuration descriptor is for high-speed,
236 // and we need to use the other speed configuration descriptor
239 #if 0
240  if(m_pDescriptor->nBcdUsbRelease >= 0x200)
241  {
242  DeviceQualifier *pQualifier = reinterpret_cast<DeviceQualifier*>(getDescriptor(UsbDescriptor::DeviceQualifier, 0, sizeof(DeviceQualifier)));
243  if(pQualifier && ((m_Speed == LowSpeed) || (m_Speed == FullSpeed)))
244  {
245  if(pQualifier->nVersion >= 0x200)
246  {
247  nConfigDescriptor = UsbDescriptor::OtherSpeedConfiguration;
248  }
249 
250  delete pQualifier;
251  }
252  }
253 #endif
254 
255  // Get the vendor, product and serial strings
256  m_pDescriptor->sVendor = getString(m_pDescriptor->nVendorString);
257  m_pDescriptor->sProduct = getString(m_pDescriptor->nProductString);
258  m_pDescriptor->sSerial = getString(m_pDescriptor->nSerialString);
259 
260  // Grab each configuration from the device
261  for (size_t i = 0; i < m_pDescriptor->nConfigurations; i++)
262  {
263  // Skip extra configurations
264  if (i)
265  {
266  WARNING("USB: Found a device with multiple configurations!");
267  break;
268  }
269 
270  // Get the total size of this configuration descriptor
271  uint16_t *pPartialConfig =
272  static_cast<uint16_t *>(getDescriptor(nConfigDescriptor, i, 4));
273  if (!pPartialConfig)
274  return;
275  uint16_t configLength = pPartialConfig[1];
276  delete pPartialConfig;
277 
278  // Get our configuration descriptor
279  ConfigDescriptor *pConfig = new ConfigDescriptor(
280  getDescriptor(nConfigDescriptor, i, configLength), configLength,
281  m_Speed);
282 
283  // Get the associated string
284  pConfig->sString = getString(pConfig->nString);
285 
286  // Go through the interface list
287  for (size_t j = 0; j < pConfig->interfaceList.count(); j++)
288  {
289  // Get this interface, for minor adjustments
290  Interface *pInterface = pConfig->interfaceList[j];
291 
292  // Just in case the class numbers are in the device descriptor
293  if (pConfig->interfaceList.count() == 1 && m_pDescriptor->nClass &&
294  !pInterface->nClass)
295  {
296  pInterface->nClass = m_pDescriptor->nClass;
297  pInterface->nSubclass = m_pDescriptor->nSubclass;
298  pInterface->nProtocol = m_pDescriptor->nProtocol;
299  }
300 
301  // Again, get the associated string
302  pInterface->sString = getString(pInterface->nString);
303  }
304 
305  // Make sure it's not empty, then add it to our list of configurations
306  assert(pConfig->interfaceList.count());
307  m_pDescriptor->configList.pushBack(pConfig);
308  }
309 
310  // Make sure we ended up with at least a configuration
311  assert(m_pDescriptor->configList.count());
312 
313  // Use the first configuration
315  useConfiguration(0);
316 }
317 
318 ssize_t UsbDevice::doSync(
319  UsbDevice::Endpoint *pEndpoint, UsbPid pid, uintptr_t pBuffer,
320  size_t nBytes, size_t timeout)
321 {
322  if (!pEndpoint)
323  {
324  ERROR("USB: UsbDevice::doSync called with invalid endpoint");
325  return -TransactionError;
326  }
327 
328  UsbHub *pParentHub = m_pHub;
329  if (!pParentHub)
330  {
331  ERROR("USB: Orphaned UsbDevice!");
332  return -TransactionError;
333  }
334 
335  if (!nBytes)
336  return 0;
337 
338  if (pBuffer & 0xF)
339  {
340  ERROR(
341  "USB: Input pointer wasn't properly aligned [" << pBuffer << ", "
342  << nBytes << "]");
343  return -TransactionError;
344  }
345 
346  UsbEndpoint endpointInfo(
347  m_nAddress, m_nPort, pEndpoint->nEndpoint, m_Speed,
348  pEndpoint->nMaxPacketSize);
349  uintptr_t nTransaction = pParentHub->createTransaction(endpointInfo);
350  if (nTransaction == static_cast<uintptr_t>(-1))
351  {
352  ERROR("UsbDevice: couldn't get a valid transaction to work with from "
353  "the parent hub");
354  return -TransactionError;
355  }
356 
357  size_t byteOffset = 0;
358  while (nBytes)
359  {
360  size_t nBytesThisTransaction = nBytes > pEndpoint->nMaxPacketSize ?
361  pEndpoint->nMaxPacketSize :
362  nBytes;
363 
364  pParentHub->addTransferToTransaction(
365  nTransaction, pEndpoint->bDataToggle, pid, pBuffer + byteOffset,
366  nBytesThisTransaction);
367  byteOffset += nBytesThisTransaction;
368  nBytes -= nBytesThisTransaction;
369 
370  pEndpoint->bDataToggle = !pEndpoint->bDataToggle;
371  }
372 
373  return pParentHub->doSync(nTransaction, timeout);
374 }
375 
376 ssize_t UsbDevice::syncIn(
377  Endpoint *pEndpoint, uintptr_t pBuffer, size_t nBytes, size_t timeout)
378 {
379  return doSync(pEndpoint, UsbPidIn, pBuffer, nBytes, timeout);
380 }
381 
382 ssize_t UsbDevice::syncOut(
383  Endpoint *pEndpoint, uintptr_t pBuffer, size_t nBytes, size_t timeout)
384 {
385  return doSync(pEndpoint, UsbPidOut, pBuffer, nBytes, timeout);
386 }
387 
388 void UsbDevice::addInterruptInHandler(
389  Endpoint *pEndpoint, uintptr_t pBuffer, uint16_t nBytes,
390  void (*pCallback)(uintptr_t, ssize_t), uintptr_t pParam)
391 {
392  if (!pEndpoint)
393  {
394  ERROR("USB: UsbDevice::addInterruptInHandler called with invalid "
395  "endpoint");
396  return;
397  }
398 
399  UsbHub *pParentHub = m_pHub;
400  if (!pParentHub)
401  {
402  ERROR("USB: Orphaned UsbDevice!");
403  return;
404  }
405 
406  if (!nBytes)
407  return;
408 
409  if (pBuffer & 0xF)
410  {
411  ERROR(
412  "USB: Input pointer wasn't properly aligned [" << pBuffer << ", "
413  << nBytes << "]");
414  return;
415  }
416 
417  UsbEndpoint endpointInfo(
418  m_nAddress, m_nPort, pEndpoint->nEndpoint, m_Speed,
419  pEndpoint->nMaxPacketSize);
420  pParentHub->addInterruptInHandler(
421  endpointInfo, pBuffer, nBytes, pCallback, pParam);
422 }
423 
425  uint8_t nRequestType, uint8_t nRequest, uint16_t nValue, uint16_t nIndex,
426  uint16_t nLength, uintptr_t pBuffer)
427 {
428  // Setup structure - holds request details
429  Setup *pSetup = new Setup(nRequestType, nRequest, nValue, nIndex, nLength);
430  PointerGuard<Setup> guard(pSetup);
431 
432  UsbHub *pParentHub = m_pHub;
433  if (!pParentHub)
434  {
435  ERROR("USB: Orphaned UsbDevice!");
436  return -1;
437  }
438 
439  UsbEndpoint endpointInfo(m_nAddress, m_nPort, 0, m_Speed, 64);
440 
441  uintptr_t nTransaction = pParentHub->createTransaction(endpointInfo);
442  if (nTransaction == static_cast<uintptr_t>(-1))
443  {
444  ERROR("UsbDevice: couldn't get a valid transaction to work with from "
445  "the parent hub");
446  return -1;
447  }
448 
449  // Setup Transfer - handles the SETUP phase of the transfer
450  pParentHub->addTransferToTransaction(
451  nTransaction, false, UsbPidSetup, reinterpret_cast<uintptr_t>(pSetup),
452  sizeof(Setup));
453 
454  // Handle the maximum size of control packets to this device. Needed for the
455  // cases where a read may breach this boundary.
456  size_t nMaxSize = 0;
457  if (m_pDescriptor)
458  {
459  if (m_pDescriptor->nMaxControlPacketSize)
460  {
461  nMaxSize = m_pDescriptor->nMaxControlPacketSize;
462  }
463  }
464  if (!nMaxSize)
465  {
466  if ((m_Speed == LowSpeed) || (m_Speed == FullSpeed))
467  nMaxSize = 8;
468  else
469  nMaxSize = 64;
470  }
471 
472  // Data Transfer - handles data transfer
473  if (nLength)
474  {
475  bool bToggle = true;
476  size_t nTransferLength = nLength;
477  size_t nOffset = 0;
478  while (nTransferLength)
479  {
480  size_t sz = nTransferLength > nMaxSize ? nMaxSize : nTransferLength;
481 
482  pParentHub->addTransferToTransaction(
483  nTransaction, bToggle,
484  nRequestType & UsbRequestDirection::In ? UsbPidIn : UsbPidOut,
485  pBuffer + nOffset, sz);
486  bToggle = !bToggle;
487 
488  nTransferLength -= sz;
489  nOffset += sz;
490  }
491  }
492 
493  // Handshake Transfer - IN when we send data to the device, OUT when we
494  // receive. Zero-length.
495  pParentHub->addTransferToTransaction(
496  nTransaction, true,
497  nRequestType & UsbRequestDirection::In ? UsbPidOut : UsbPidIn, 0, 0);
498 
499  // Wait for the transaction to complete
500  ssize_t nResult = pParentHub->doSync(nTransaction);
501 
502  // Return false if we had an error, true otherwise
503  if (nResult < 0)
504  {
505  DEBUG_LOG("USB: Control request failure - status is " << nResult);
506  }
507  return nResult >= 0; // >= sizeof(Setup) + nLength;
508 }
509 
511 {
512  uint16_t *nStatus = new uint16_t(0);
513  PointerGuard<uint16_t> guard(nStatus);
515  UsbRequestDirection::In, UsbRequest::GetStatus, 0, 0, 2,
516  reinterpret_cast<uintptr_t>(nStatus));
517  return *nStatus;
518 }
519 
521 {
522  return controlRequest(
523  UsbRequestRecipient::Endpoint, UsbRequest::ClearFeature, 0,
524  pEndpoint->nEndpoint);
525 }
526 
527 void UsbDevice::useConfiguration(uint8_t nConfig)
528 {
529  m_pConfiguration = m_pDescriptor->configList[nConfig];
530  if (!controlRequest(
531  0, UsbRequest::SetConfiguration, m_pConfiguration->nConfig, 0))
532  return;
533  m_UsbState = Configured; // We now are configured
534 }
535 
536 void UsbDevice::useInterface(uint8_t nInterface)
537 {
538  // First check if the previous interface was an alternate setting
539  bool bWasAlternateSetting = m_pInterface && m_pInterface->nAlternateSetting;
540 
541  // Set our interface to the new one
542  m_pInterface = m_pConfiguration->interfaceList[nInterface];
543 
544  // If needed, change the alternate setting
545  if (bWasAlternateSetting || m_pInterface->nAlternateSetting)
546  if (!controlRequest(
547  UsbRequestRecipient::Interface, UsbRequest::SetInterface,
548  m_pInterface->nAlternateSetting, 0))
549  return;
550 
551  // Set our state to HasInterface, if it's not higher
552  if (m_UsbState < HasInterface)
553  m_UsbState = HasInterface;
554 }
555 
557  uint8_t nDescriptor, uint8_t nSubDescriptor, uint16_t nBytes,
558  uint8_t requestType)
559 {
560  uint8_t *pBuffer = new uint8_t[nBytes];
561  uint16_t nIndex = requestType & UsbRequestRecipient::Interface ?
562  m_pInterface->nInterface :
563  0;
564 
566  if (nDescriptor == UsbDescriptor::String)
567  nIndex = 0x0409; // English (US)
568 
569  if (!controlRequest(
570  UsbRequestDirection::In | requestType, UsbRequest::GetDescriptor,
571  (nDescriptor << 8) | nSubDescriptor, nIndex, nBytes,
572  reinterpret_cast<uintptr_t>(pBuffer)))
573  {
574  delete[] pBuffer;
575  return 0;
576  }
577  return pBuffer;
578 }
579 
581  uint8_t nDescriptor, uint8_t nSubDescriptor, uint8_t requestType)
582 {
583  uint8_t *length = new uint8_t(0);
584  PointerGuard<uint8_t> guard(length);
585  uint16_t nIndex = requestType & UsbRequestRecipient::Interface ?
586  m_pInterface->nInterface :
587  0;
588 
590  if (nDescriptor == UsbDescriptor::String)
591  nIndex = 0x0409; // English (US)
592 
594  UsbRequestDirection::In | requestType, UsbRequest::GetDescriptor,
595  (nDescriptor << 8) | nSubDescriptor, nIndex, 1,
596  reinterpret_cast<uintptr_t>(length));
597  return *length;
598 }
599 
600 String UsbDevice::getString(uint8_t nString)
601 {
602  // A value of zero means there's no string
603  if (!nString)
604  return String("");
605 
606  uint8_t descriptorLength =
607  getDescriptorLength(UsbDescriptor::String, nString);
608  if (!descriptorLength)
609  return String("");
610 
611  char *pBuffer = static_cast<char *>(
612  getDescriptor(UsbDescriptor::String, nString, descriptorLength));
613  if (!pBuffer)
614  return String("");
615 
616  // Get the number of characters in the string and allocate a new buffer for
617  // the string
618  size_t nStrLength = (descriptorLength - 2) / 2;
619  char *pString = new char[nStrLength + 1];
620 
621  // For each character, get the lower part of the UTF-16 value
623  for (size_t i = 0; i < nStrLength; i++)
624  pString[i] = pBuffer[2 + i * 2];
625 
626  // Set the last byte of the string to 0, delete the old buffer and return
627  // the string
628  pString[nStrLength] = 0;
629  delete pBuffer;
630  return String(pString);
631 }
632 
633 UsbDeviceContainer::UsbDeviceContainer(UsbDevice *pDev)
634  : Device(), m_pUsbDevice(pDev)
635 {
636  pDev->m_pContainer = this;
637 
638  // Classes that expose a subtree can be converted to Device.
639  // But, we need to do this so children will continue to have
640  // the correct parents.
641  if (pDev->hasSubtree())
642  {
643  Device *pChild = pDev->getDevice();
644  addChild(pChild);
645  pChild->setParent(this);
646  }
647 }
648 
649 UsbDeviceContainer::~UsbDeviceContainer()
650 {
651 }
652 
653 UsbDevice *UsbDeviceContainer::getUsbDevice() const
654 {
655  return m_pUsbDevice;
656 }
657 
659 {
660  m_pUsbDevice->getUsbDeviceName(str);
661 }
662 
664 {
665  return Device::UsbContainer;
666 }
667 
669 {
670  str = "Generic USB Device";
671 }
virtual void getName(String &str)
Definition: UsbDevice.cc:658
uint8_t m_nPort
The number of the port on which the device is connected.
Definition: UsbDevice.h:304
ConfigDescriptor * m_pConfiguration
Configuration in use.
Definition: UsbDevice.h:316
uint8_t getDescriptorLength(uint8_t nDescriptorType, uint8_t nDescriptorIndex, uint8_t requestType=0)
Gets a descriptor&#39;s length from the device.
Definition: UsbDevice.cc:580
virtual void dump(String &str)
Definition: UsbDevice.cc:668
void useConfiguration(uint8_t nConfig)
Switches to the given configuration.
Definition: UsbDevice.cc:527
virtual bool hasSubtree() const
Do we expose our own Device tree?
Definition: UsbDevice.h:248
Definition: String.h:49
UsbDevice(UsbHub *pHub, uint8_t nPort, UsbSpeed speed)
Default constructor.
Definition: UsbDevice.cc:30
UsbHub * m_pHub
Parent USB hub.
Definition: UsbDevice.h:322
Definition: Device.h:43
bool controlRequest(uint8_t nRequestType, uint8_t nRequest, uint16_t nValue, uint16_t nIndex, uint16_t nLength=0, uintptr_t pBuffer=0)
Performs an USB control request.
Definition: UsbDevice.cc:424
UsbSpeed m_Speed
The speed at which the device operates.
Definition: UsbDevice.h:307
void initialise(uint8_t nAddress)
Initialises the device at the given address.
Definition: UsbDevice.cc:155
#define WARNING(text)
Definition: Log.h:78
virtual Device * getDevice()
Definition: UsbDevice.h:255
virtual void addInterruptInHandler(UsbEndpoint endpointInfo, uintptr_t pBuffer, uint16_t nBytes, void(*pCallback)(uintptr_t, ssize_t), uintptr_t pParam=0)=0
Adds a new handler for an interrupt IN transaction.
String getString(uint8_t nString)
Gets a string.
Definition: UsbDevice.cc:600
UsbState m_UsbState
The current state of the device.
Definition: UsbDevice.h:310
virtual ~UsbDevice()
Destructor.
Definition: UsbDevice.cc:47
uint16_t getStatus()
Gets device&#39;s current status.
Definition: UsbDevice.cc:510
uint8_t m_nAddress
The current address of the device.
Definition: UsbDevice.h:301
DeviceDescriptor * m_pDescriptor
Device descriptor for this device.
Definition: UsbDevice.h:313
Definition: Log.h:136
#define assert(x)
Definition: assert.h:37
bool clearEndpointHalt(Endpoint *pEndpoint)
Clears a halt on the given endpoint.
Definition: UsbDevice.cc:520
Definition: UsbHub.h:30
void setParent(Device *p)
Definition: Device.h:154
DeviceDescriptor * getDescriptor()
Returns the device descriptor of the device.
Definition: UsbDevice.h:218
ssize_t doSync(uintptr_t nTransaction, uint32_t timeout=5000)
Definition: UsbHub.cc:234
#define ERROR(text)
Definition: Log.h:82
Definition: Log.h:138
virtual Type getType()
Definition: UsbDevice.cc:663
#define DEBUG_LOG(text)
Definition: Log.h:69
Type
Definition: Device.h:50
Interface * m_pInterface
Interface in use.
Definition: UsbDevice.h:319
UsbDeviceContainer * m_pContainer
Our current container.
Definition: UsbDevice.h:325
virtual void addTransferToTransaction(uintptr_t pTransaction, bool bToggle, UsbPid pid, uintptr_t pBuffer, size_t nBytes)=0
Adds a new transfer to an existent transaction.
virtual uintptr_t createTransaction(UsbEndpoint endpointInfo)=0
Creates a new transaction with the given endpoint data.
void useInterface(uint8_t nInterface)
Switches to the given interface.
Definition: UsbDevice.cc:536