#include "uhci.h"
#define USB_MODULE_NAME "uhci roothub"
static usb_device_descriptor sUHCIRootHubDevice =
{
18,
USB_DESCRIPTOR_DEVICE,
0x110,
0x09,
0,
0,
64,
0,
0,
0x110,
1,
2,
0,
1
};
struct uhci_root_hub_configuration_s {
usb_configuration_descriptor configuration;
usb_interface_descriptor interface;
usb_endpoint_descriptor endpoint;
usb_hub_descriptor hub;
} _PACKED;
static uhci_root_hub_configuration_s sUHCIRootHubConfig =
{
{
9,
USB_DESCRIPTOR_CONFIGURATION,
34,
1,
1,
0,
0x40,
0
},
{
9,
USB_DESCRIPTOR_INTERFACE,
0,
0,
1,
0x09,
0,
0,
0
},
{
7,
USB_DESCRIPTOR_ENDPOINT,
USB_REQTYPE_DEVICE_IN | 1,
0x03,
8,
0xff
},
{
9,
USB_DESCRIPTOR_HUB,
2,
0x0000,
0,
0,
0x00,
0xff
}
};
struct uhci_root_hub_string_s {
uint8 length;
uint8 descriptor_type;
uint16 unicode_string[12];
} _PACKED;
static uhci_root_hub_string_s sUHCIRootHubStrings[3] = {
{
4,
USB_DESCRIPTOR_STRING,
{
0x0409
}
},
{
22,
USB_DESCRIPTOR_STRING,
{
'H', 'A', 'I', 'K', 'U',
' ', 'I', 'n', 'c', '.'
}
},
{
26,
USB_DESCRIPTOR_STRING,
{
'U', 'H', 'C', 'I', ' ',
'R', 'o', 'o', 't', 'H',
'u', 'b'
}
}
};
UHCIRootHub::UHCIRootHub(Object *rootObject, int8 deviceAddress)
: Hub(rootObject, 0, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()),
sUHCIRootHubDevice, deviceAddress, USB_SPEED_FULLSPEED, true)
{
}
status_t
UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer)
{
if ((transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) == 0)
return B_ERROR;
usb_request_data *request = transfer->RequestData();
TRACE_MODULE("request: %d\n", request->Request);
status_t status = B_TIMED_OUT;
size_t actualLength = 0;
switch (request->Request) {
case USB_REQUEST_GET_STATUS: {
if (request->Index == 0) {
actualLength = MIN(sizeof(usb_port_status),
transfer->DataLength());
memset(transfer->Data(), 0, actualLength);
status = B_OK;
break;
}
usb_port_status portStatus;
if (uhci->GetPortStatus(request->Index - 1, &portStatus) >= B_OK) {
actualLength = MIN(sizeof(usb_port_status), transfer->DataLength());
memcpy(transfer->Data(), (void *)&portStatus, actualLength);
status = B_OK;
}
break;
}
case USB_REQUEST_SET_ADDRESS:
if (request->Value >= 128) {
status = B_TIMED_OUT;
break;
}
TRACE_MODULE("set address: %d\n", request->Value);
status = B_OK;
break;
case USB_REQUEST_GET_DESCRIPTOR:
TRACE_MODULE("get descriptor: %d\n", request->Value >> 8);
switch (request->Value >> 8) {
case USB_DESCRIPTOR_DEVICE: {
actualLength = MIN(sizeof(usb_device_descriptor),
transfer->DataLength());
memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice,
actualLength);
status = B_OK;
break;
}
case USB_DESCRIPTOR_CONFIGURATION: {
actualLength = MIN(sizeof(uhci_root_hub_configuration_s),
transfer->DataLength());
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig,
actualLength);
status = B_OK;
break;
}
case USB_DESCRIPTOR_STRING: {
uint8 index = request->Value & 0x00ff;
if (index > 2)
break;
actualLength = MIN(sUHCIRootHubStrings[index].length,
transfer->DataLength());
memcpy(transfer->Data(), (void *)&sUHCIRootHubStrings[index],
actualLength);
status = B_OK;
break;
}
case USB_DESCRIPTOR_HUB: {
actualLength = MIN(sizeof(usb_hub_descriptor),
transfer->DataLength());
memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub,
actualLength);
status = B_OK;
break;
}
}
break;
case USB_REQUEST_SET_CONFIGURATION:
status = B_OK;
break;
case USB_REQUEST_CLEAR_FEATURE: {
if (request->Index == 0) {
TRACE_MODULE_ERROR("clear feature: no hub changes\n");
break;
}
TRACE_MODULE("clear feature: %d\n", request->Value);
if (uhci->ClearPortFeature(request->Index - 1, request->Value) >= B_OK)
status = B_OK;
break;
}
case USB_REQUEST_SET_FEATURE: {
if (request->Index == 0) {
TRACE_MODULE_ERROR("set feature: no hub changes\n");
break;
}
TRACE_MODULE("set feature: %d\n", request->Value);
if (uhci->SetPortFeature(request->Index - 1, request->Value) >= B_OK)
status = B_OK;
break;
}
}
transfer->Finished(status, actualLength);
delete transfer;
return B_OK;
}