2 * Copyright 2005-2008, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
7 * Salvatore Benedetto <salvatore.benedetto@gmail.com>
8 * Michael Lotz <mmlr@mlotz.ch>
13 #define USB_MODULE_NAME "ohci roothub"
15 static usb_device_descriptor sOHCIRootHubDevice
=
17 18, // Descriptor length
18 USB_DESCRIPTOR_DEVICE
, // Descriptor type
20 0x09, // Class (9 = Hub)
23 64, // Max packet size on endpoint 0
27 1, // Index of manufacturer string
28 2, // Index of product string
29 0, // Index of serial number string
30 1 // Number of configurations
34 struct ohci_root_hub_configuration_s
{
35 usb_configuration_descriptor configuration
;
36 usb_interface_descriptor interface
;
37 usb_endpoint_descriptor endpoint
;
38 usb_hub_descriptor hub
;
42 static ohci_root_hub_configuration_s sOHCIRootHubConfig
=
44 { // configuration descriptor
45 9, // Descriptor length
46 USB_DESCRIPTOR_CONFIGURATION
, // Descriptor type
47 34, // Total length of configuration (including
48 // interface, endpoint and hub descriptors)
49 1, // Number of interfaces
50 1, // Value of this configuration
51 0, // Index of configuration string
52 0x40, // Attributes (0x40 = self powered)
53 0 // Max power (0, since self powered)
56 { // interface descriptor
57 9, // Descriptor length
58 USB_DESCRIPTOR_INTERFACE
, // Descriptor type
59 0, // Interface number
60 0, // Alternate setting
61 1, // Number of endpoints
62 0x09, // Interface class (9 = Hub)
63 0, // Interface subclass
64 0, // Interface protocol
65 0 // Index of interface string
68 { // endpoint descriptor
69 7, // Descriptor length
70 USB_DESCRIPTOR_ENDPOINT
, // Descriptor type
71 USB_REQTYPE_DEVICE_IN
| 1, // Endpoint address (first in IN endpoint)
72 0x03, // Attributes (0x03 = interrupt endpoint)
78 9, // Descriptor length (including
79 // deprecated power control mask)
80 USB_DESCRIPTOR_HUB
, // Descriptor type
82 0x0000, // Hub characteristics
83 0, // Power on to power good (in 2ms units)
84 0, // Maximum current (in mA)
85 0x00, // Both ports are removable
86 0xff // Depricated power control mask
91 struct ohci_root_hub_string_s
{
93 uint8 descriptor_type
;
94 uint16 unicode_string
[12];
98 static ohci_root_hub_string_s sOHCIRootHubStrings
[3] = {
100 4, // Descriptor length
101 USB_DESCRIPTOR_STRING
, // Descriptor type
103 0x0409 // Supported language IDs (English US)
108 22, // Descriptor length
109 USB_DESCRIPTOR_STRING
, // Descriptor type
111 'H', 'A', 'I', 'K', 'U', // Characters
112 ' ', 'I', 'n', 'c', '.'
117 26, // Descriptor length
118 USB_DESCRIPTOR_STRING
, // Descriptor type
120 'O', 'H', 'C', 'I', ' ', // Characters
121 'R', 'o', 'o', 't', 'H',
128 OHCIRootHub::OHCIRootHub(Object
*rootObject
, int8 deviceAddress
)
129 : Hub(rootObject
, 0, rootObject
->GetStack()->IndexOfBusManager(rootObject
->GetBusManager()),
130 sOHCIRootHubDevice
, deviceAddress
, USB_SPEED_FULLSPEED
, true)
136 OHCIRootHub::ProcessTransfer(OHCI
*ohci
, Transfer
*transfer
)
138 if ((transfer
->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE
) == 0)
141 usb_request_data
*request
= transfer
->RequestData();
142 TRACE_MODULE("request: %d\n", request
->Request
);
144 status_t status
= B_TIMED_OUT
;
145 size_t actualLength
= 0;
146 switch (request
->Request
) {
147 case USB_REQUEST_GET_STATUS
: {
148 if (request
->Index
== 0) {
150 actualLength
= MIN(sizeof(usb_port_status
),
151 transfer
->DataLength());
152 // the hub reports whether the local power failed (bit 0)
153 // and if there is a over-current condition (bit 1).
154 // everything as 0 means all is ok.
155 memset(transfer
->Data(), 0, actualLength
);
160 usb_port_status portStatus
;
161 if (ohci
->GetPortStatus(request
->Index
- 1, &portStatus
) >= B_OK
) {
162 actualLength
= MIN(sizeof(usb_port_status
), transfer
->DataLength());
163 memcpy(transfer
->Data(), (void *)&portStatus
, actualLength
);
170 case USB_REQUEST_SET_ADDRESS
:
171 if (request
->Value
>= 128) {
172 status
= B_TIMED_OUT
;
176 TRACE_MODULE("set address: %d\n", request
->Value
);
180 case USB_REQUEST_GET_DESCRIPTOR
:
181 TRACE_MODULE("get descriptor: %d\n", request
->Value
>> 8);
183 switch (request
->Value
>> 8) {
184 case USB_DESCRIPTOR_DEVICE
: {
185 actualLength
= MIN(sizeof(usb_device_descriptor
),
186 transfer
->DataLength());
187 memcpy(transfer
->Data(), (void *)&sOHCIRootHubDevice
,
193 case USB_DESCRIPTOR_CONFIGURATION
: {
194 actualLength
= MIN(sizeof(ohci_root_hub_configuration_s
),
195 transfer
->DataLength());
196 sOHCIRootHubConfig
.hub
.num_ports
= ohci
->PortCount();
197 memcpy(transfer
->Data(), (void *)&sOHCIRootHubConfig
,
203 case USB_DESCRIPTOR_STRING
: {
204 uint8 index
= request
->Value
& 0x00ff;
208 actualLength
= MIN(sOHCIRootHubStrings
[index
].length
,
209 transfer
->DataLength());
210 memcpy(transfer
->Data(), (void *)&sOHCIRootHubStrings
[index
],
216 case USB_DESCRIPTOR_HUB
: {
217 actualLength
= MIN(sizeof(usb_hub_descriptor
),
218 transfer
->DataLength());
219 sOHCIRootHubConfig
.hub
.num_ports
= ohci
->PortCount();
220 memcpy(transfer
->Data(), (void *)&sOHCIRootHubConfig
.hub
,
228 case USB_REQUEST_SET_CONFIGURATION
:
232 case USB_REQUEST_CLEAR_FEATURE
: {
233 if (request
->Index
== 0) {
234 // we don't support any hub changes
235 TRACE_MODULE_ERROR("clear feature: no hub changes\n");
239 TRACE_MODULE("clear feature: %d\n", request
->Value
);
240 if (ohci
->ClearPortFeature(request
->Index
- 1, request
->Value
) >= B_OK
)
245 case USB_REQUEST_SET_FEATURE
: {
246 if (request
->Index
== 0) {
247 // we don't support any hub changes
248 TRACE_MODULE_ERROR("set feature: no hub changes\n");
252 TRACE_MODULE("set feature: %d\n", request
->Value
);
253 if (ohci
->SetPortFeature(request
->Index
- 1, request
->Value
) >= B_OK
)
259 transfer
->Finished(status
, actualLength
);