1 /* 2 * Copyright 2004-2006, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 * Niels S. Reedijk 8 */ 9 10 #include "uhci.h" 11 12 static usb_device_descriptor sUHCIRootHubDevice = 13 { 14 18, // Descriptor length 15 USB_DESCRIPTOR_DEVICE, // Descriptor type 16 0x110, // USB 1.1 17 0x09, // Class (9 = Hub) 18 0, // Subclass 19 0, // Protocol 20 64, // Max packet size on endpoint 0 21 0, // Vendor ID 22 0, // Product ID 23 0x110, // Version 24 1, // Index of manufacturer string 25 2, // Index of product string 26 0, // Index of serial number string 27 1 // Number of configurations 28 }; 29 30 31 struct uhci_root_hub_configuration_s { 32 usb_configuration_descriptor configuration; 33 usb_interface_descriptor interface; 34 usb_endpoint_descriptor endpoint; 35 usb_hub_descriptor hub; 36 } _PACKED; 37 38 39 static uhci_root_hub_configuration_s sUHCIRootHubConfig = 40 { 41 { // configuration descriptor 42 9, // Descriptor length 43 USB_DESCRIPTOR_CONFIGURATION, // Descriptor type 44 34, // Total length of configuration (including 45 // interface, endpoint and hub descriptors) 46 1, // Number of interfaces 47 1, // Value of this configuration 48 0, // Index of configuration string 49 0x40, // Attributes (0x40 = self powered) 50 0 // Max power (0, since self powered) 51 }, 52 53 { // interface descriptor 54 9, // Descriptor length 55 USB_DESCRIPTOR_INTERFACE, // Descriptor type 56 0, // Interface number 57 0, // Alternate setting 58 1, // Number of endpoints 59 0x09, // Interface class (9 = Hub) 60 0, // Interface subclass 61 0, // Interface protocol 62 0 // Index of interface string 63 }, 64 65 { // endpoint descriptor 66 7, // Descriptor length 67 USB_DESCRIPTOR_ENDPOINT, // Descriptor type 68 USB_REQTYPE_DEVICE_IN | 1, // Endpoint address (first in IN endpoint) 69 0x03, // Attributes (0x03 = interrupt endpoint) 70 8, // Max packet size 71 0xff // Interval 72 }, 73 74 { // hub descriptor 75 9, // Descriptor length (including 76 // deprecated power control mask) 77 USB_DESCRIPTOR_HUB, // Descriptor type 78 2, // Number of ports 79 0x0000, // Hub characteristics 80 0, // Power on to power good (in 2ms units) 81 0, // Maximum current (in mA) 82 0x00, // Both ports are removable 83 0xff // Depricated power control mask 84 } 85 }; 86 87 88 struct uhci_root_hub_string_s { 89 uint8 length; 90 uint8 descriptor_type; 91 uint16 unicode_string[12]; 92 } _PACKED; 93 94 95 static uhci_root_hub_string_s sUHCIRootHubStrings[3] = { 96 { 97 4, // Descriptor length 98 USB_DESCRIPTOR_STRING, // Descriptor type 99 { 100 0x0409 // Supported language IDs (English US) 101 } 102 }, 103 104 { 105 22, // Descriptor length 106 USB_DESCRIPTOR_STRING, // Descriptor type 107 { 108 'H', 'A', 'I', 'K', 'U', // Characters 109 ' ', 'I', 'n', 'c', '.' 110 } 111 }, 112 113 { 114 26, // Descriptor length 115 USB_DESCRIPTOR_STRING, // Descriptor type 116 { 117 'U', 'H', 'C', 'I', ' ', // Characters 118 'R', 'o', 'o', 't', 'H', 119 'u', 'b' 120 } 121 } 122 }; 123 124 125 UHCIRootHub::UHCIRootHub(Object *rootObject, int8 deviceAddress) 126 : Hub(rootObject, 0, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()), 127 sUHCIRootHubDevice, deviceAddress, USB_SPEED_FULLSPEED, true) 128 { 129 } 130 131 132 status_t 133 UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer) 134 { 135 if ((transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) == 0) 136 return B_ERROR; 137 138 usb_request_data *request = transfer->RequestData(); 139 TRACE(("usb_uhci_roothub: request: %d\n", request->Request)); 140 141 status_t status = B_TIMED_OUT; 142 size_t actualLength = 0; 143 switch (request->Request) { 144 case USB_REQUEST_GET_STATUS: { 145 if (request->Index == 0) { 146 // get hub status 147 actualLength = MIN(sizeof(usb_port_status), 148 transfer->DataLength()); 149 // the hub reports whether the local power failed (bit 0) 150 // and if there is a over-current condition (bit 1). 151 // everything as 0 means all is ok. 152 memset(transfer->Data(), 0, actualLength); 153 status = B_OK; 154 break; 155 } 156 157 usb_port_status portStatus; 158 if (uhci->GetPortStatus(request->Index - 1, &portStatus) >= B_OK) { 159 actualLength = MIN(sizeof(usb_port_status), transfer->DataLength()); 160 memcpy(transfer->Data(), (void *)&portStatus, actualLength); 161 status = B_OK; 162 } 163 164 break; 165 } 166 167 case USB_REQUEST_SET_ADDRESS: 168 if (request->Value >= 128) { 169 status = B_TIMED_OUT; 170 break; 171 } 172 173 TRACE(("usb_uhci_roothub: set address: %d\n", request->Value)); 174 status = B_OK; 175 break; 176 177 case USB_REQUEST_GET_DESCRIPTOR: 178 TRACE(("usb_uhci_roothub: get descriptor: %d\n", request->Value >> 8)); 179 180 switch (request->Value >> 8) { 181 case USB_DESCRIPTOR_DEVICE: { 182 actualLength = MIN(sizeof(usb_device_descriptor), 183 transfer->DataLength()); 184 memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice, 185 actualLength); 186 status = B_OK; 187 break; 188 } 189 190 case USB_DESCRIPTOR_CONFIGURATION: { 191 actualLength = MIN(sizeof(uhci_root_hub_configuration_s), 192 transfer->DataLength()); 193 memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig, 194 actualLength); 195 status = B_OK; 196 break; 197 } 198 199 case USB_DESCRIPTOR_STRING: { 200 uint8 index = request->Value & 0x00ff; 201 if (index > 2) 202 break; 203 204 actualLength = MIN(sUHCIRootHubStrings[index].length, 205 transfer->DataLength()); 206 memcpy(transfer->Data(), (void *)&sUHCIRootHubStrings[index], 207 actualLength); 208 status = B_OK; 209 break; 210 } 211 212 case USB_DESCRIPTOR_HUB: { 213 actualLength = MIN(sizeof(usb_hub_descriptor), 214 transfer->DataLength()); 215 memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub, 216 actualLength); 217 status = B_OK; 218 break; 219 } 220 } 221 break; 222 223 case USB_REQUEST_SET_CONFIGURATION: 224 status = B_OK; 225 break; 226 227 case USB_REQUEST_CLEAR_FEATURE: { 228 if (request->Index == 0) { 229 // we don't support any hub changes 230 TRACE_ERROR(("usb_uhci_roothub: clear feature: no hub changes\n")); 231 break; 232 } 233 234 TRACE(("usb_uhci_roothub: clear feature: %d\n", request->Value)); 235 if (uhci->ClearPortFeature(request->Index - 1, request->Value) >= B_OK) 236 status = B_OK; 237 break; 238 } 239 240 case USB_REQUEST_SET_FEATURE: { 241 if (request->Index == 0) { 242 // we don't support any hub changes 243 TRACE_ERROR(("usb_uhci_roothub: set feature: no hub changes\n")); 244 break; 245 } 246 247 TRACE(("usb_uhci_roothub: set feature: %d!\n", request->Value)); 248 if (uhci->SetPortFeature(request->Index - 1, request->Value) >= B_OK) 249 status = B_OK; 250 break; 251 } 252 } 253 254 transfer->Finished(status, actualLength); 255 delete transfer; 256 return B_OK; 257 } 258