Implemented most of the roothub.
There remains only one issue: reading the Port registers seem to return a bogus value (0). I need to find out what's causing it. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18918 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -108,9 +108,6 @@ ohci_add_to(Stack *stack)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
TRACE(("usb_ohci init_hardware(): Setting up hardware\n"));
|
TRACE(("usb_ohci init_hardware(): Setting up hardware\n"));
|
||||||
//
|
|
||||||
// TODO: in the future we might want to support multiple host controllers.
|
|
||||||
//
|
|
||||||
item = new pci_info;
|
item = new pci_info;
|
||||||
for ( i = 0 ; OHCI::pci_module->get_nth_pci_info( i , item ) == B_OK ; i++ ) {
|
for ( i = 0 ; OHCI::pci_module->get_nth_pci_info( i , item ) == B_OK ; i++ ) {
|
||||||
if ( ( item->class_base == PCI_serial_bus ) && ( item->class_sub == PCI_usb )
|
if ( ( item->class_base == PCI_serial_bus ) && ( item->class_sub == PCI_usb )
|
||||||
@@ -121,20 +118,28 @@ ohci_add_to(Stack *stack)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TRACE(("USB OHCI: init_hardware(): found at IRQ %u \n", item->u.h0.interrupt_line));
|
TRACE(("USB OHCI: init_hardware(): found at IRQ %u \n", item->u.h0.interrupt_line));
|
||||||
OHCI *bus = new OHCI( item , stack );
|
OHCI *bus = new(std::nothrow) OHCI(item, stack);
|
||||||
|
|
||||||
|
if (!bus) {
|
||||||
|
delete item;
|
||||||
|
OHCI::pci_module = NULL;
|
||||||
|
put_module(B_PCI_MODULE_NAME);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
if (bus->InitCheck() != B_OK) {
|
if (bus->InitCheck() != B_OK) {
|
||||||
|
TRACE(("usb_ohci: bus failed to initialize...\n"));
|
||||||
delete bus;
|
delete bus;
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack->AddBusManager( bus );
|
|
||||||
bus->Start();
|
bus->Start();
|
||||||
|
stack->AddBusManager( bus );
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( found == false ) {
|
if (!found) {
|
||||||
TRACE(("USB OHCI: init hardware(): no devices found\n"));
|
TRACE(("USB OHCI: init hardware(): no devices found\n"));
|
||||||
free( item );
|
free( item );
|
||||||
put_module( B_PCI_MODULE_NAME );
|
put_module( B_PCI_MODULE_NAME );
|
||||||
@@ -184,7 +189,10 @@ OHCI::OHCI(pci_info *info, Stack *stack)
|
|||||||
fHccaArea(-1),
|
fHccaArea(-1),
|
||||||
fDummyControl(0),
|
fDummyControl(0),
|
||||||
fDummyBulk(0),
|
fDummyBulk(0),
|
||||||
fDummyIsochronous(0)
|
fDummyIsochronous(0),
|
||||||
|
fRootHub(0),
|
||||||
|
fRootHubAddress(0),
|
||||||
|
fNumPorts(0)
|
||||||
{
|
{
|
||||||
fPcii = info;
|
fPcii = info;
|
||||||
fStack = stack;
|
fStack = stack;
|
||||||
@@ -321,9 +329,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
|
|||||||
uint32 interval = OHCI_GET_IVAL(frameinterval);
|
uint32 interval = OHCI_GET_IVAL(frameinterval);
|
||||||
WriteReg(OHCI_PERIODIC_START, OHCI_PERIODIC(interval));
|
WriteReg(OHCI_PERIODIC_START, OHCI_PERIODIC(interval));
|
||||||
|
|
||||||
|
fInitOK = true;
|
||||||
m_roothub_base = 255; //Invalidate the Root Hub address
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OHCI::~OHCI()
|
OHCI::~OHCI()
|
||||||
@@ -338,18 +344,140 @@ OHCI::~OHCI()
|
|||||||
FreeEndpoint(fDummyBulk);
|
FreeEndpoint(fDummyBulk);
|
||||||
if (fDummyIsochronous)
|
if (fDummyIsochronous)
|
||||||
FreeEndpoint(fDummyIsochronous);
|
FreeEndpoint(fDummyIsochronous);
|
||||||
|
if (fRootHub)
|
||||||
|
delete fRootHub;
|
||||||
for (int i = 0; i < OHCI_NO_EDS; i++)
|
for (int i = 0; i < OHCI_NO_EDS; i++)
|
||||||
if (fInterruptEndpoints[i])
|
if (fInterruptEndpoints[i])
|
||||||
FreeEndpoint(fInterruptEndpoints[i]);
|
FreeEndpoint(fInterruptEndpoints[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
OHCI::Start()
|
||||||
|
{
|
||||||
|
if (!(ReadReg(OHCI_CONTROL) & OHCI_HCFS_OPERATIONAL)) {
|
||||||
|
TRACE(("USB OHCI::Start(): Controller not started. TODO: find out what happens.\n"));
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
fRootHubAddress = AllocateAddress();
|
||||||
|
fNumPorts = OHCI_GET_PORT_COUNT(ReadReg(OHCI_RH_DESCRIPTOR_A));
|
||||||
|
|
||||||
|
fRootHub = new(std::nothrow) OHCIRootHub(this, fRootHubAddress);
|
||||||
|
if (!fRootHub) {
|
||||||
|
TRACE_ERROR(("USB OHCI::Start(): no memory to allocate root hub\n"));
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fRootHub->InitCheck() < B_OK) {
|
||||||
|
TRACE_ERROR(("USB OHCI::Start(): root hub failed init check\n"));
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetRootHub(fRootHub);
|
||||||
|
TRACE(("USB OHCI::Start(): Succesful start\n"));
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t OHCI::SubmitTransfer( Transfer *t )
|
||||||
|
{
|
||||||
|
TRACE(("usb OHCI::SubmitTransfer: called for device %d\n", t->TransferPipe()->DeviceAddress()));
|
||||||
|
|
||||||
|
if (t->TransferPipe()->DeviceAddress() == fRootHubAddress)
|
||||||
|
return fRootHub->ProcessTransfer(t, this);
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
OHCI::GetPortStatus(uint8 index, usb_port_status *status)
|
||||||
|
{
|
||||||
|
if (index > fNumPorts)
|
||||||
|
return B_BAD_INDEX;
|
||||||
|
|
||||||
|
status->status = status->change = 0;
|
||||||
|
uint32 portStatus = ReadReg(OHCI_RH_PORT_STATUS(index));
|
||||||
|
|
||||||
|
TRACE(("OHCIRootHub::GetPortStatus: Port %i Value 0x%lx\n", OHCI_RH_PORT_STATUS(index), portStatus));
|
||||||
|
|
||||||
|
// status
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_CCS)
|
||||||
|
status->status |= PORT_STATUS_CONNECTION;
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_PES)
|
||||||
|
status->status |= PORT_STATUS_ENABLE;
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_PRS)
|
||||||
|
status->status |= PORT_STATUS_RESET;
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_LSDA)
|
||||||
|
status->status |= PORT_STATUS_LOW_SPEED;
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_PSS)
|
||||||
|
status->status |= PORT_STATUS_SUSPEND;
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_POCI)
|
||||||
|
status->status |= PORT_STATUS_OVER_CURRENT;
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_PPS)
|
||||||
|
status->status |= PORT_STATUS_POWER;
|
||||||
|
|
||||||
|
|
||||||
|
// change
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_CSC)
|
||||||
|
status->change |= PORT_STATUS_CONNECTION;
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_PESC)
|
||||||
|
status->change |= PORT_STATUS_ENABLE;
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_PSSC)
|
||||||
|
status->change |= PORT_STATUS_SUSPEND;
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_OCIC)
|
||||||
|
status->change |= PORT_STATUS_OVER_CURRENT;
|
||||||
|
if (portStatus & OHCI_PORTSTATUS_PRSC)
|
||||||
|
status->change |= PORT_STATUS_RESET;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
OHCI::SetPortFeature(uint8 index, uint16 feature)
|
||||||
|
{
|
||||||
|
if (index > fNumPorts)
|
||||||
|
return B_BAD_INDEX;
|
||||||
|
|
||||||
|
switch (feature) {
|
||||||
|
case PORT_RESET:
|
||||||
|
WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_PORTSTATUS_PRS);
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
case PORT_POWER:
|
||||||
|
WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_PORTSTATUS_PPS);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
OHCI::ClearPortFeature(uint8 index, uint16 feature)
|
||||||
|
{
|
||||||
|
if (index > fNumPorts)
|
||||||
|
return B_BAD_INDEX;
|
||||||
|
|
||||||
|
switch (feature) {
|
||||||
|
case C_PORT_RESET:
|
||||||
|
WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_PORTSTATUS_CSC);
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
case C_PORT_CONNECTION:
|
||||||
|
WriteReg(OHCI_RH_PORT_STATUS(index), OHCI_PORTSTATUS_CSC);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
Endpoint *
|
Endpoint *
|
||||||
OHCI::AllocateEndpoint()
|
OHCI::AllocateEndpoint()
|
||||||
{
|
{
|
||||||
Endpoint *endpoint = new Endpoint;
|
Endpoint *endpoint = new Endpoint;
|
||||||
void *phy;
|
void *phy;
|
||||||
if (fStack->AllocateChunk((void **)&endpoint->ed, &phy, sizeof(ohci_endpoint_descriptor)) != B_OK)
|
if (fStack->AllocateChunk((void **)&endpoint->ed, &phy, sizeof(ohci_endpoint_descriptor)) != B_OK) {
|
||||||
|
TRACE(("OHCI::AllocateEndpoint(): Error Allocating Endpoint\n"));
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
endpoint->physicaladdress = (addr_t)phy;
|
endpoint->physicaladdress = (addr_t)phy;
|
||||||
|
|
||||||
memset((void *)endpoint->ed, 0, sizeof(ohci_endpoint_descriptor));
|
memset((void *)endpoint->ed, 0, sizeof(ohci_endpoint_descriptor));
|
||||||
@@ -364,17 +492,6 @@ OHCI::FreeEndpoint(Endpoint *end)
|
|||||||
delete end;
|
delete end;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// OHCI:: Submit a transfer
|
|
||||||
//
|
|
||||||
// parameters:
|
|
||||||
// - t: pointer to a transfer instance
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
|
|
||||||
status_t OHCI::SubmitTransfer( Transfer *t )
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
pci_module_info *OHCI::pci_module = 0;
|
pci_module_info *OHCI::pci_module = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -48,13 +48,20 @@ public:
|
|||||||
|
|
||||||
OHCI(pci_info *info, Stack *stack);
|
OHCI(pci_info *info, Stack *stack);
|
||||||
~OHCI();
|
~OHCI();
|
||||||
|
status_t Start();
|
||||||
status_t SubmitTransfer(Transfer *t); //Override from BusManager.
|
status_t SubmitTransfer(Transfer *t); //Override from BusManager.
|
||||||
static pci_module_info *pci_module; // Global data for the module.
|
static pci_module_info *pci_module; // Global data for the module.
|
||||||
|
|
||||||
|
status_t GetPortStatus(uint8 index, usb_port_status *status);
|
||||||
|
status_t ClearPortFeature(uint8 index, uint16 feature);
|
||||||
|
status_t SetPortFeature(uint8 index, uint16 feature);
|
||||||
|
|
||||||
|
uint8 PortCount() { return fNumPorts; };
|
||||||
|
|
||||||
|
private:
|
||||||
inline void WriteReg(uint32 reg, uint32 value);
|
inline void WriteReg(uint32 reg, uint32 value);
|
||||||
inline uint32 ReadReg(uint32 reg);
|
inline uint32 ReadReg(uint32 reg);
|
||||||
|
|
||||||
private:
|
|
||||||
// Global
|
// Global
|
||||||
pci_info *fPcii; // pci-info struct
|
pci_info *fPcii; // pci-info struct
|
||||||
Stack *fStack; // Pointer to the stack
|
Stack *fStack; // Pointer to the stack
|
||||||
@@ -69,8 +76,9 @@ private:
|
|||||||
Endpoint *fDummyBulk;
|
Endpoint *fDummyBulk;
|
||||||
Endpoint *fDummyIsochronous;
|
Endpoint *fDummyIsochronous;
|
||||||
// Root Hub
|
// Root Hub
|
||||||
OHCIRootHub *m_roothub; // the root hub
|
OHCIRootHub *fRootHub; // the root hub
|
||||||
addr_t m_roothub_base; // Base address of the root hub
|
uint8 fRootHubAddress; // the usb address of the roothub
|
||||||
|
uint8 fNumPorts; // the number of ports
|
||||||
// functions
|
// functions
|
||||||
Endpoint *AllocateEndpoint(); // allocate memory for an endpoint
|
Endpoint *AllocateEndpoint(); // allocate memory for an endpoint
|
||||||
void FreeEndpoint(Endpoint *end); //Free endpoint
|
void FreeEndpoint(Endpoint *end); //Free endpoint
|
||||||
@@ -85,12 +93,8 @@ private:
|
|||||||
class OHCIRootHub : public Hub
|
class OHCIRootHub : public Hub
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OHCIRootHub( OHCI *ohci , int8 devicenum );
|
OHCIRootHub(OHCI *ohci, int8 deviceAddress);
|
||||||
status_t SubmitTransfer( Transfer *t );
|
status_t ProcessTransfer(Transfer *t, OHCI *ohci);
|
||||||
void UpdatePortStatus();
|
|
||||||
private:
|
|
||||||
usb_port_status m_hw_port_status[2]; // the port status (maximum of two)
|
|
||||||
OHCI *m_ohci; // needed because of internal data
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -110,6 +114,4 @@ struct Endpoint
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#define OHCI_DEBUG
|
|
||||||
|
|
||||||
#endif // OHCI_H
|
#endif // OHCI_H
|
||||||
|
|||||||
@@ -189,7 +189,7 @@
|
|||||||
// --------------------------------
|
// --------------------------------
|
||||||
|
|
||||||
#define OHCI_RH_DESCRIPTOR_A 0x48
|
#define OHCI_RH_DESCRIPTOR_A 0x48
|
||||||
#define OHCI_GET_NDP(s) ((s) & 0xff)
|
#define OHCI_GET_PORT_COUNT(s) ((s) & 0xff)
|
||||||
#define OHCI_PSM 0x0100 // Power Switching Mode
|
#define OHCI_PSM 0x0100 // Power Switching Mode
|
||||||
#define OHCI_NPS 0x0200 // No Power Switching
|
#define OHCI_NPS 0x0200 // No Power Switching
|
||||||
#define OHCI_DT 0x0400 // Device Type
|
#define OHCI_DT 0x0400 // Device Type
|
||||||
@@ -220,6 +220,18 @@
|
|||||||
// --------------------------------
|
// --------------------------------
|
||||||
|
|
||||||
#define OHCI_RH_PORT_STATUS(n) (0x50 + (n)*4) // 1 based indexing
|
#define OHCI_RH_PORT_STATUS(n) (0x50 + (n)*4) // 1 based indexing
|
||||||
|
#define OHCI_PORTSTATUS_CCS 0x00000001 // Current Connection Status
|
||||||
|
#define OHCI_PORTSTATUS_PES 0x00000002 // Port Enable Status
|
||||||
|
#define OHCI_PORTSTATUS_PSS 0x00000004 // Port Suspend Status
|
||||||
|
#define OHCI_PORTSTATUS_POCI 0x00000008 // Port Overcurrent Indicator
|
||||||
|
#define OHCI_PORTSTATUS_PRS 0x00000010 // Port Reset Status
|
||||||
|
#define OHCI_PORTSTATUS_PPS 0x00000100 // Port Power Status
|
||||||
|
#define OHCI_PORTSTATUS_LSDA 0x00000200 // Low Speed Device Attached
|
||||||
|
#define OHCI_PORTSTATUS_CSC 0x00010000 // Connection Status Change
|
||||||
|
#define OHCI_PORTSTATUS_PESC 0x00020000 // Port Enable Status Change
|
||||||
|
#define OHCI_PORTSTATUS_PSSC 0x00040000 // Port Suspend Status change
|
||||||
|
#define OHCI_PORTSTATUS_OCIC 0x00080000 // Port Overcurrent Change
|
||||||
|
#define OHCI_PORTSTATUS_PRSC 0x00100000 // Port Reset Status Change
|
||||||
|
|
||||||
// --------------------------------
|
// --------------------------------
|
||||||
// ????
|
// ????
|
||||||
|
|||||||
@@ -22,9 +22,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "ohci.h"
|
#include "ohci.h"
|
||||||
#include <PCI.h>
|
|
||||||
|
|
||||||
usb_device_descriptor ohci_devd =
|
static usb_device_descriptor sOHCIRootHubDevice =
|
||||||
{
|
{
|
||||||
0x12, //Descriptor size
|
0x12, //Descriptor size
|
||||||
USB_DESCRIPTOR_DEVICE , //Type of descriptor
|
USB_DESCRIPTOR_DEVICE , //Type of descriptor
|
||||||
@@ -40,21 +39,27 @@ usb_device_descriptor ohci_devd =
|
|||||||
1 //Number of configurations
|
1 //Number of configurations
|
||||||
};
|
};
|
||||||
|
|
||||||
usb_configuration_descriptor ohci_confd =
|
struct ohci_root_hub_configuration_s {
|
||||||
{
|
usb_configuration_descriptor configuration;
|
||||||
0x09, //Size
|
usb_interface_descriptor interface;
|
||||||
|
usb_endpoint_descriptor endpoint;
|
||||||
|
usb_hub_descriptor hub;
|
||||||
|
} _PACKED;
|
||||||
|
|
||||||
|
static ohci_root_hub_configuration_s sOHCIRootHubConfig = {
|
||||||
|
{ // configuration descriptor
|
||||||
|
9, //Size
|
||||||
USB_DESCRIPTOR_CONFIGURATION,
|
USB_DESCRIPTOR_CONFIGURATION,
|
||||||
25 , //Total size (taken from BSD source)
|
34, //Total size of the configuration
|
||||||
1, //Number interfaces
|
1, //Number interfaces
|
||||||
1, //Value of configuration
|
1, //Value of configuration
|
||||||
0, //Number of configuration
|
0, //Number of configuration
|
||||||
0x40, //Self powered
|
0x40, //Self powered
|
||||||
0 //Max power (0, because of self power)
|
0 //Max power (0, because of self power)
|
||||||
};
|
},
|
||||||
|
|
||||||
usb_interface_descriptor ohci_intd =
|
{ // interface descriptor
|
||||||
{
|
9, //Size
|
||||||
0x09 , //Size
|
|
||||||
USB_DESCRIPTOR_INTERFACE,
|
USB_DESCRIPTOR_INTERFACE,
|
||||||
0, //Interface number
|
0, //Interface number
|
||||||
0, //Alternate setting
|
0, //Alternate setting
|
||||||
@@ -62,43 +67,203 @@ usb_interface_descriptor ohci_intd =
|
|||||||
0x09, //Interface class
|
0x09, //Interface class
|
||||||
0, //Interface subclass
|
0, //Interface subclass
|
||||||
0, //Interface protocol
|
0, //Interface protocol
|
||||||
0 , //Interface
|
0 //Interface
|
||||||
};
|
},
|
||||||
|
|
||||||
usb_endpoint_descriptor ohci_endd =
|
{ // endpoint descriptor
|
||||||
{
|
7, //Size
|
||||||
0x07 , //Size
|
|
||||||
USB_DESCRIPTOR_ENDPOINT,
|
USB_DESCRIPTOR_ENDPOINT,
|
||||||
USB_REQTYPE_DEVICE_IN | 1, //1 from freebsd driver
|
USB_REQTYPE_DEVICE_IN | 1, //1 from freebsd driver
|
||||||
0x3, // Interrupt
|
0x3, // Interrupt
|
||||||
8, // Max packet size
|
8, // Max packet size
|
||||||
0xFF // Interval 256
|
0xFF // Interval 256
|
||||||
};
|
},
|
||||||
|
|
||||||
usb_hub_descriptor ohci_hubd =
|
|
||||||
{
|
{
|
||||||
0x09 , //Including deprecated powerctrlmask
|
9, //Including deprecated powerctrlmask
|
||||||
USB_DESCRIPTOR_HUB,
|
USB_DESCRIPTOR_HUB,
|
||||||
1, //Number of ports
|
0, //Number of ports
|
||||||
0x02 | 0x01 , //Hub characteristics FIXME
|
0x0000, //Hub characteristics FIXME
|
||||||
50, //Power on to power good
|
50, //Power on to power good
|
||||||
0, // Current
|
0, // Current
|
||||||
0x00 //Both ports are removable
|
0x00, //Both ports are removable
|
||||||
|
0xff // Depricated power control mask
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//Implementation
|
struct ohci_root_hub_string_s {
|
||||||
OHCIRootHub::OHCIRootHub( OHCI *ohci , int8 devicenum )
|
uint8 length;
|
||||||
: Hub( ohci->RootObject() , ohci_devd , devicenum , USB_SPEED_FULLSPEED )
|
uint8 descriptor_type;
|
||||||
|
uint16 unicode_string[12];
|
||||||
|
} _PACKED;
|
||||||
|
|
||||||
|
|
||||||
|
static ohci_root_hub_string_s sOHCIRootHubStrings[3] = {
|
||||||
|
{
|
||||||
|
4, // Descriptor length
|
||||||
|
USB_DESCRIPTOR_STRING, // Descriptor type
|
||||||
|
{
|
||||||
|
0x0409 // Supported language IDs (English US)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
22, // Descriptor length
|
||||||
|
USB_DESCRIPTOR_STRING, // Descriptor type
|
||||||
|
{
|
||||||
|
'H', 'A', 'I', 'K', 'U', // Characters
|
||||||
|
' ', 'I', 'n', 'c', '.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
26, // Descriptor length
|
||||||
|
USB_DESCRIPTOR_STRING, // Descriptor type
|
||||||
|
{
|
||||||
|
'O', 'H', 'C', 'I', ' ', // Characters
|
||||||
|
'R', 'o', 'o', 't', 'H',
|
||||||
|
'u', 'b'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
OHCIRootHub::OHCIRootHub(OHCI *ohci, int8 deviceAddress)
|
||||||
|
: Hub(ohci->RootObject(), sOHCIRootHubDevice, deviceAddress , USB_SPEED_FULLSPEED )
|
||||||
{
|
{
|
||||||
m_ohci = ohci;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t OHCIRootHub::SubmitTransfer( Transfer *t )
|
status_t
|
||||||
|
OHCIRootHub::ProcessTransfer(Transfer *t, OHCI *ohci)
|
||||||
{
|
{
|
||||||
|
if ((t->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) == 0)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
usb_request_data *request = t->RequestData();
|
||||||
|
TRACE(("OHCIRootHub::ProcessTransfer(): request: %d\n", request->Request));
|
||||||
|
|
||||||
|
uint32 status = B_USB_STATUS_DEVICE_TIMEOUT;
|
||||||
|
size_t actualLength = 0;
|
||||||
|
switch (request->Request) {
|
||||||
|
case USB_REQUEST_GET_STATUS: {
|
||||||
|
if (request->Index == 0) {
|
||||||
|
// get hub status
|
||||||
|
actualLength = MIN(sizeof(usb_port_status),
|
||||||
|
t->DataLength());
|
||||||
|
// the hub reports whether the local power failed (bit 0)
|
||||||
|
// and if there is a over-current condition (bit 1).
|
||||||
|
// everything as 0 means all is ok.
|
||||||
|
// TODO (?) actually check for the value
|
||||||
|
memset(t->Data(), 0, actualLength);
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_port_status portStatus;
|
||||||
|
if (ohci->GetPortStatus(request->Index, &portStatus) >= B_OK) {
|
||||||
|
actualLength = MIN(sizeof(usb_port_status), t->DataLength());
|
||||||
|
memcpy(t->Data(), (void *)&portStatus, actualLength);
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case USB_REQUEST_SET_ADDRESS:
|
||||||
|
if (request->Value >= 128) {
|
||||||
|
status = B_USB_STATUS_DEVICE_TIMEOUT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE(("OHCIRootHub::ProcessTransfer(): set address: %d\n", request->Value));
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USB_REQUEST_GET_DESCRIPTOR:
|
||||||
|
TRACE(("OHCIRootHub::ProcessTransfer(): get descriptor: %d\n", request->Value >> 8));
|
||||||
|
|
||||||
|
switch (request->Value >> 8) {
|
||||||
|
case USB_DESCRIPTOR_DEVICE: {
|
||||||
|
actualLength = MIN(sizeof(usb_device_descriptor),
|
||||||
|
t->DataLength());
|
||||||
|
memcpy(t->Data(), (void *)&sOHCIRootHubDevice,
|
||||||
|
actualLength);
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case USB_DESCRIPTOR_CONFIGURATION: {
|
||||||
|
//Make sure we have the correct number of ports
|
||||||
|
sOHCIRootHubConfig.hub.num_ports = ohci->PortCount();
|
||||||
|
|
||||||
|
actualLength = MIN(sizeof(sOHCIRootHubConfig),
|
||||||
|
t->DataLength());
|
||||||
|
memcpy(t->Data(), (void *)&(sOHCIRootHubConfig),
|
||||||
|
actualLength);
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case USB_DESCRIPTOR_STRING: {
|
||||||
|
uint8 index = request->Value & 0x00ff;
|
||||||
|
if (index > 2)
|
||||||
|
break;
|
||||||
|
|
||||||
|
actualLength = MIN(sOHCIRootHubStrings[index].length,
|
||||||
|
t->DataLength());
|
||||||
|
memcpy(t->Data(), (void *)&sOHCIRootHubStrings[index],
|
||||||
|
actualLength);
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case USB_DESCRIPTOR_HUB: {
|
||||||
|
//Make sure we have the correct number of ports
|
||||||
|
sOHCIRootHubConfig.hub.num_ports = ohci->PortCount();
|
||||||
|
|
||||||
|
actualLength = MIN(sizeof(usb_hub_descriptor),
|
||||||
|
t->DataLength());
|
||||||
|
memcpy(t->Data(), (void *)&sOHCIRootHubConfig.hub,
|
||||||
|
actualLength);
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USB_REQUEST_SET_CONFIGURATION:
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USB_REQUEST_CLEAR_FEATURE: {
|
||||||
|
if (request->Index == 0) {
|
||||||
|
// we don't support any hub changes
|
||||||
|
TRACE_ERROR(("OHCIRootHub::ProcessTransfer(): clear feature: no hub changes\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE(("OHCIRootHub::ProcessTransfer(): clear feature: %d\n", request->Value));
|
||||||
|
if (ohci->ClearPortFeature(request->Index, request->Value) >= B_OK)
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case USB_REQUEST_SET_FEATURE: {
|
||||||
|
if (request->Index == 0) {
|
||||||
|
// we don't support any hub changes
|
||||||
|
TRACE_ERROR(("OHCIRootHub::ProcessTransfer(): set feature: no hub changes\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE(("OHCIRootHub::ProcessTransfer(): set feature: %d\n", request->Value));
|
||||||
|
if (ohci->SetPortFeature(request->Index, request->Value) >= B_OK)
|
||||||
|
status = B_USB_STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t->Finished(status, actualLength);
|
||||||
|
delete t;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OHCIRootHub::UpdatePortStatus(void)
|
|
||||||
{
|
|
||||||
// nothing yet
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user