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