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