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