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