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