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