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" 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),
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;
69 UsbDevice::DeviceDescriptor::~DeviceDescriptor()
71 for (
size_t i = 0; i < configList.count(); i++)
75 UsbDevice::ConfigDescriptor::ConfigDescriptor(
76 void *pConfigBuffer,
size_t nConfigLength, UsbSpeed speed)
80 nConfig = pDescriptor->nConfig;
81 nString = pDescriptor->nString;
83 uint8_t *pBuffer =
static_cast<uint8_t *
>(pConfigBuffer);
84 size_t nOffset = pBuffer[0];
87 while (nOffset < nConfigLength)
89 size_t nLength = pBuffer[nOffset];
90 uint8_t nType = pBuffer[nOffset + 1];
91 if (nType == UsbDescriptor::Interface)
94 reinterpret_cast<UsbInterfaceDescriptor *>(&pBuffer[nOffset]));
95 interfaceList.pushBack(pCurrentInterface);
97 else if (pCurrentInterface)
99 if (nType == UsbDescriptor::Endpoint)
100 pCurrentInterface->endpointList.pushBack(
new Endpoint(
101 reinterpret_cast<UsbEndpointDescriptor *>(
105 pCurrentInterface->otherDescriptorList.pushBack(
109 otherDescriptorList.pushBack(
113 assert(interfaceList.count());
118 UsbDevice::ConfigDescriptor::~ConfigDescriptor()
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];
128 nInterface = pDescriptor->nInterface;
129 nAlternateSetting = pDescriptor->nAlternateSetting;
130 nClass = pDescriptor->nClass;
131 nSubclass = pDescriptor->nSubclass;
132 nProtocol = pDescriptor->nProtocol;
133 nString = pDescriptor->nString;
136 UsbDevice::Interface::~Interface()
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];
144 UsbDevice::Endpoint::Endpoint(
148 nEndpoint = pDescriptor->nEndpoint;
149 bIn = pDescriptor->bDirection;
151 nTransferType = pDescriptor->nTransferType;
152 nMaxPacketSize = pDescriptor->nMaxPacketSize;
160 ERROR(
"USB: UsbDevice::initialise called, but this device is already " 169 "Device (" << nAddress
170 <<
"): couldn't assign an address to the device.");
178 if (!nDescriptorLength)
182 "Device (" << nAddress
183 <<
"): address assignment worked, but couldn't get the " 184 "device descriptor length.");
188 void *pDeviceDescriptor =
190 if (!pDeviceDescriptor)
194 "Device (" << nAddress
195 <<
"): address assignment worked, but couldn't get a " 196 "device descriptor.");
200 static_cast<UsbDeviceDescriptor *>(pDeviceDescriptor));
204 #ifdef USB_VERBOSE_DEBUG 209 "Device class/subclass/protocol: " <<
m_pDescriptor->nClass <<
"/" 213 "Maximum control packet size is " 216 "Vendor and product IDs: " <<
m_pDescriptor->nVendorId <<
":" 223 "Number of configurations: " <<
m_pDescriptor->nConfigurations <<
".");
231 uint8_t nConfigDescriptor = UsbDescriptor::Configuration;
243 if(pQualifier && ((
m_Speed == LowSpeed) || (
m_Speed == FullSpeed)))
245 if(pQualifier->nVersion >= 0x200)
247 nConfigDescriptor = UsbDescriptor::OtherSpeedConfiguration;
266 WARNING(
"USB: Found a device with multiple configurations!");
271 uint16_t *pPartialConfig =
272 static_cast<uint16_t *
>(
getDescriptor(nConfigDescriptor, i, 4));
275 uint16_t configLength = pPartialConfig[1];
276 delete pPartialConfig;
280 getDescriptor(nConfigDescriptor, i, configLength), configLength,
284 pConfig->sString =
getString(pConfig->nString);
287 for (
size_t j = 0; j < pConfig->interfaceList.count(); j++)
290 Interface *pInterface = pConfig->interfaceList[j];
293 if (pConfig->interfaceList.count() == 1 &&
m_pDescriptor->nClass &&
302 pInterface->sString =
getString(pInterface->nString);
306 assert(pConfig->interfaceList.count());
318 ssize_t UsbDevice::doSync(
320 size_t nBytes,
size_t timeout)
324 ERROR(
"USB: UsbDevice::doSync called with invalid endpoint");
325 return -TransactionError;
331 ERROR(
"USB: Orphaned UsbDevice!");
332 return -TransactionError;
341 "USB: Input pointer wasn't properly aligned [" << pBuffer <<
", " 343 return -TransactionError;
348 pEndpoint->nMaxPacketSize);
350 if (nTransaction == static_cast<uintptr_t>(-1))
352 ERROR(
"UsbDevice: couldn't get a valid transaction to work with from " 354 return -TransactionError;
357 size_t byteOffset = 0;
360 size_t nBytesThisTransaction = nBytes > pEndpoint->nMaxPacketSize ?
361 pEndpoint->nMaxPacketSize :
365 nTransaction, pEndpoint->bDataToggle, pid, pBuffer + byteOffset,
366 nBytesThisTransaction);
367 byteOffset += nBytesThisTransaction;
368 nBytes -= nBytesThisTransaction;
370 pEndpoint->bDataToggle = !pEndpoint->bDataToggle;
373 return pParentHub->
doSync(nTransaction, timeout);
376 ssize_t UsbDevice::syncIn(
377 Endpoint *pEndpoint, uintptr_t pBuffer,
size_t nBytes,
size_t timeout)
379 return doSync(pEndpoint, UsbPidIn, pBuffer, nBytes, timeout);
382 ssize_t UsbDevice::syncOut(
383 Endpoint *pEndpoint, uintptr_t pBuffer,
size_t nBytes,
size_t timeout)
385 return doSync(pEndpoint, UsbPidOut, pBuffer, nBytes, timeout);
388 void UsbDevice::addInterruptInHandler(
389 Endpoint *pEndpoint, uintptr_t pBuffer, uint16_t nBytes,
390 void (*pCallback)(uintptr_t, ssize_t), uintptr_t pParam)
394 ERROR(
"USB: UsbDevice::addInterruptInHandler called with invalid " 402 ERROR(
"USB: Orphaned UsbDevice!");
412 "USB: Input pointer wasn't properly aligned [" << pBuffer <<
", " 419 pEndpoint->nMaxPacketSize);
421 endpointInfo, pBuffer, nBytes, pCallback, pParam);
425 uint8_t nRequestType, uint8_t nRequest, uint16_t nValue, uint16_t nIndex,
426 uint16_t nLength, uintptr_t pBuffer)
429 Setup *pSetup =
new Setup(nRequestType, nRequest, nValue, nIndex, nLength);
435 ERROR(
"USB: Orphaned UsbDevice!");
442 if (nTransaction == static_cast<uintptr_t>(-1))
444 ERROR(
"UsbDevice: couldn't get a valid transaction to work with from " 451 nTransaction,
false, UsbPidSetup, reinterpret_cast<uintptr_t>(pSetup),
476 size_t nTransferLength = nLength;
478 while (nTransferLength)
480 size_t sz = nTransferLength > nMaxSize ? nMaxSize : nTransferLength;
483 nTransaction, bToggle,
484 nRequestType & UsbRequestDirection::In ? UsbPidIn : UsbPidOut,
485 pBuffer + nOffset, sz);
488 nTransferLength -= sz;
497 nRequestType & UsbRequestDirection::In ? UsbPidOut : UsbPidIn, 0, 0);
500 ssize_t nResult = pParentHub->
doSync(nTransaction);
505 DEBUG_LOG(
"USB: Control request failure - status is " << nResult);
512 uint16_t *nStatus =
new uint16_t(0);
515 UsbRequestDirection::In, UsbRequest::GetStatus, 0, 0, 2,
516 reinterpret_cast<uintptr_t>(nStatus));
523 UsbRequestRecipient::Endpoint, UsbRequest::ClearFeature, 0,
524 pEndpoint->nEndpoint);
545 if (bWasAlternateSetting ||
m_pInterface->nAlternateSetting)
547 UsbRequestRecipient::Interface, UsbRequest::SetInterface,
557 uint8_t nDescriptor, uint8_t nSubDescriptor, uint16_t nBytes,
560 uint8_t *pBuffer =
new uint8_t[nBytes];
561 uint16_t nIndex = requestType & UsbRequestRecipient::Interface ?
566 if (nDescriptor == UsbDescriptor::String)
570 UsbRequestDirection::In | requestType, UsbRequest::GetDescriptor,
571 (nDescriptor << 8) | nSubDescriptor, nIndex, nBytes,
572 reinterpret_cast<uintptr_t>(pBuffer)))
581 uint8_t nDescriptor, uint8_t nSubDescriptor, uint8_t requestType)
583 uint8_t *length =
new uint8_t(0);
585 uint16_t nIndex = requestType & UsbRequestRecipient::Interface ?
590 if (nDescriptor == UsbDescriptor::String)
594 UsbRequestDirection::In | requestType, UsbRequest::GetDescriptor,
595 (nDescriptor << 8) | nSubDescriptor, nIndex, 1,
596 reinterpret_cast<uintptr_t>(length));
606 uint8_t descriptorLength =
608 if (!descriptorLength)
611 char *pBuffer =
static_cast<char *
>(
612 getDescriptor(UsbDescriptor::String, nString, descriptorLength));
618 size_t nStrLength = (descriptorLength - 2) / 2;
619 char *pString =
new char[nStrLength + 1];
623 for (
size_t i = 0; i < nStrLength; i++)
624 pString[i] = pBuffer[2 + i * 2];
628 pString[nStrLength] = 0;
633 UsbDeviceContainer::UsbDeviceContainer(
UsbDevice *pDev)
634 :
Device(), m_pUsbDevice(pDev)
649 UsbDeviceContainer::~UsbDeviceContainer()
653 UsbDevice *UsbDeviceContainer::getUsbDevice()
const 660 m_pUsbDevice->getUsbDeviceName(str);
670 str =
"Generic USB Device";
virtual void getName(String &str)
uint8_t m_nPort
The number of the port on which the device is connected.
ConfigDescriptor * m_pConfiguration
Configuration in use.
uint8_t getDescriptorLength(uint8_t nDescriptorType, uint8_t nDescriptorIndex, uint8_t requestType=0)
Gets a descriptor's length from the device.
virtual void dump(String &str)
void useConfiguration(uint8_t nConfig)
Switches to the given configuration.
virtual bool hasSubtree() const
Do we expose our own Device tree?
UsbDevice(UsbHub *pHub, uint8_t nPort, UsbSpeed speed)
Default constructor.
UsbHub * m_pHub
Parent USB hub.
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.
UsbSpeed m_Speed
The speed at which the device operates.
void initialise(uint8_t nAddress)
Initialises the device at the given address.
virtual Device * getDevice()
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.
UsbState m_UsbState
The current state of the device.
virtual ~UsbDevice()
Destructor.
uint16_t getStatus()
Gets device's current status.
uint8_t m_nAddress
The current address of the device.
DeviceDescriptor * m_pDescriptor
Device descriptor for this device.
bool clearEndpointHalt(Endpoint *pEndpoint)
Clears a halt on the given endpoint.
void setParent(Device *p)
DeviceDescriptor * getDescriptor()
Returns the device descriptor of the device.
ssize_t doSync(uintptr_t nTransaction, uint32_t timeout=5000)
Interface * m_pInterface
Interface in use.
UsbDeviceContainer * m_pContainer
Our current container.
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.