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 #include <PCI.h> 12 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 { 117 26, // Descriptor length 118 USB_DESCRIPTOR_STRING, // Descriptor type 119 { 120 'U', 'H', 'C', 'I', ' ', // Characters 121 'R', 'o', 'o', 't', 'H', 122 'u', 'b' 123 } 124 } 125 }; 126 127 128 UHCIRootHub::UHCIRootHub(Object *rootObject, int8 deviceAddress) 129 : Hub(rootObject, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()), 130 sUHCIRootHubDevice, deviceAddress, USB_SPEED_FULLSPEED, true) 131 { 132 } 133 134 135 status_t 136 UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer) 137 { 138 if ((transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) == 0) 139 return B_ERROR; 140 141 usb_request_data *request = transfer->RequestData(); 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 the hub status -- everything as 0 means all-right 149 actualLength = MIN(sizeof(usb_port_status), 150 transfer->DataLength()); 151 memset(transfer->Data(), 0, actualLength); 152 status = B_OK; 153 break; 154 } 155 156 usb_port_status portStatus; 157 if (uhci->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 break; 163 } 164 165 case USB_REQUEST_SET_ADDRESS: 166 if (request->Value >= 128) { 167 status = B_TIMED_OUT; 168 break; 169 } 170 171 TRACE(("usb_uhci_roothub: set address: %d\n", request->Value)); 172 status = B_OK; 173 break; 174 175 case USB_REQUEST_GET_DESCRIPTOR: 176 TRACE(("usb_uhci_roothub: get descriptor: %d\n", request->Value >> 8)); 177 178 switch (request->Value >> 8) { 179 case USB_DESCRIPTOR_DEVICE: { 180 actualLength = MIN(sizeof(usb_device_descriptor), 181 transfer->DataLength()); 182 memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice, 183 actualLength); 184 status = B_OK; 185 break; 186 } 187 188 case USB_DESCRIPTOR_CONFIGURATION: { 189 actualLength = MIN(sizeof(uhci_root_hub_configuration_s), 190 transfer->DataLength()); 191 memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig, 192 actualLength); 193 status = B_OK; 194 break; 195 } 196 197 case USB_DESCRIPTOR_STRING: { 198 uint8 index = request->Value & 0x00ff; 199 if (index > 2) 200 break; 201 202 actualLength = MIN(sUHCIRootHubStrings[index].length, 203 transfer->DataLength()); 204 memcpy(transfer->Data(), (void *)&sUHCIRootHubStrings[index], 205 actualLength); 206 status = B_OK; 207 break; 208 } 209 210 case USB_DESCRIPTOR_HUB: { 211 actualLength = MIN(sizeof(usb_hub_descriptor), 212 transfer->DataLength()); 213 memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub, 214 actualLength); 215 status = B_OK; 216 break; 217 } 218 } 219 break; 220 221 case USB_REQUEST_SET_CONFIGURATION: 222 status = B_OK; 223 break; 224 225 case USB_REQUEST_CLEAR_FEATURE: { 226 if (request->Index == 0) { 227 // We don't support any hub changes 228 TRACE_ERROR(("usb_uhci_roothub: clear feature: no hub changes\n")); 229 break; 230 } 231 232 TRACE(("usb_uhci_roothub: clear feature: %d\n", request->Value)); 233 if (uhci->ClearPortFeature(request->Index - 1, request->Value) >= B_OK) 234 status = B_OK; 235 break; 236 } 237 238 case USB_REQUEST_SET_FEATURE: { 239 if (request->Index == 0) { 240 // we don't support any hub changes 241 TRACE_ERROR(("usb_uhci_roothub: set feature: no hub changes\n")); 242 break; 243 } 244 245 TRACE(("usb_uhci_roothub: set feature: %d!\n", request->Value)); 246 if (uhci->SetPortFeature(request->Index - 1, request->Value) >= B_OK) 247 status = B_OK; 248 break; 249 } 250 } 251 252 transfer->Finished(status, actualLength); 253 delete transfer; 254 return B_OK; 255 } 256