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 */ 9 10 #include "ohci.h" 11 12 static usb_device_descriptor sOHCIRootHubDevice = 13 { 14 0x12, // Descriptor size 15 USB_DESCRIPTOR_DEVICE, // Type of descriptor 16 0x110, // USB 1.1 17 0x09, // Hub type 18 0, // Subclass 19 0, // Protocol 20 64, // Max packet size 21 0, // Vendor 22 0, // Product 23 0x110, // Version 24 1, // Index of manufacture string 25 2, // Index of product string 26 0, // Index of serial number string 27 1 // Number of configurations 28 }; 29 30 31 struct ohci_root_hub_configuration_s { 32 usb_configuration_descriptor configuration; 33 usb_interface_descriptor interface; 34 usb_endpoint_descriptor endpoint; 35 usb_hub_descriptor hub; 36 } _PACKED; 37 38 39 static ohci_root_hub_configuration_s sOHCIRootHubConfig = 40 { 41 { // configuration descriptor 42 9, // Descriptor length 43 USB_DESCRIPTOR_CONFIGURATION, // Descriptor type 44 34, // Total size of the configuration 45 1, // Number interfaces 46 1, // Value of configuration 47 0, // Number of configuration 48 0x40, // Self powered 49 0 // Max power (0, because of self power) 50 }, 51 52 { // interface descriptor 53 9, // Size 54 USB_DESCRIPTOR_INTERFACE, // Type 55 0, // Interface number 56 0, // Alternate setting 57 1, // Num endpoints 58 0x09, // Interface class 59 0, // Interface subclass 60 0, // Interface protocol 61 0 // Interface 62 }, 63 64 { // endpoint descriptor 65 7, // Size 66 USB_DESCRIPTOR_ENDPOINT, // 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 256 71 }, 72 73 { // hub descriptor 74 9, // Lenght (including deprecated power 75 // control mask) 76 USB_DESCRIPTOR_HUB, // Type 77 0, // Number of ports 78 0x0000, // Hub characteristics 79 50, // Power on to power good 80 0, // Current 81 0x00, // Both ports are removable 82 0xff // Depricated power control mask 83 } 84 }; 85 86 struct ohci_root_hub_string_s { 87 uint8 length; 88 uint8 descriptor_type; 89 uint16 unicode_string[12]; 90 } _PACKED; 91 92 93 static ohci_root_hub_string_s sOHCIRootHubStrings[3] = { 94 { 95 4, // Descriptor length 96 USB_DESCRIPTOR_STRING, // Descriptor type 97 { 98 0x0409 // Supported language IDs (English US) 99 } 100 }, 101 102 { 103 22, // Descriptor length 104 USB_DESCRIPTOR_STRING, // Descriptor type 105 { 106 'H', 'A', 'I', 'K', 'U', // Characters 107 ' ', 'I', 'n', 'c', '.' 108 } 109 }, 110 111 { 112 26, // Descriptor length 113 USB_DESCRIPTOR_STRING, // Descriptor type 114 { 115 'O', 'H', 'C', 'I', ' ', // Characters 116 'R', 'o', 'o', 't', 'H', 117 'u', 'b' 118 } 119 } 120 }; 121 122 123 OHCIRootHub::OHCIRootHub(Object *rootObject, int8 deviceAddress) 124 : Hub(rootObject, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()), 125 sOHCIRootHubDevice, deviceAddress, USB_SPEED_FULLSPEED) 126 { 127 } 128 129 status_t 130 OHCIRootHub::ProcessTransfer(OHCI *ohci, Transfer *transfer) 131 { 132 if ((transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) == 0) 133 return B_ERROR; 134 135 usb_request_data *request = transfer->RequestData(); 136 137 TRACE(("usb_ohci_roothub(): request: %d\n", request->Request)); 138 139 status_t status = B_TIMED_OUT; 140 size_t actualLength = 0; 141 switch (request->Request) { 142 case USB_REQUEST_GET_STATUS: { 143 if (request->Index == 0) { 144 // get hub status 145 actualLength = MIN(sizeof(usb_port_status), 146 transfer->DataLength()); 147 // the hub reports whether the local power failed (bit 0) 148 // and if there is a over-current condition (bit 1). 149 // everything as 0 means all is ok. 150 // TODO (?) actually check for the value 151 memset(transfer->Data(), 0, actualLength); 152 status = B_OK; 153 break; 154 } 155 156 usb_port_status portStatus; 157 if (ohci->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_ohci_roothub(): set address: %d\n", request->Value)); 172 status = B_OK; 173 break; 174 175 case USB_REQUEST_GET_DESCRIPTOR: 176 TRACE(("usb_ohci_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 *)&sOHCIRootHubDevice, 183 actualLength); 184 status = B_OK; 185 break; 186 } 187 188 case USB_DESCRIPTOR_CONFIGURATION: { 189 actualLength = MIN(sizeof(ohci_root_hub_configuration_s), 190 transfer->DataLength()); 191 sOHCIRootHubConfig.hub.num_ports = ohci->PortCount(); 192 memcpy(transfer->Data(), (void *)&sOHCIRootHubConfig, 193 actualLength); 194 status = B_OK; 195 break; 196 } 197 198 case USB_DESCRIPTOR_STRING: { 199 uint8 index = request->Value & 0x00ff; 200 if (index > 2) 201 break; 202 203 actualLength = MIN(sOHCIRootHubStrings[index].length, 204 transfer->DataLength()); 205 memcpy(transfer->Data(), (void *)&sOHCIRootHubStrings[index], 206 actualLength); 207 status = B_OK; 208 break; 209 } 210 211 case USB_DESCRIPTOR_HUB: { 212 actualLength = MIN(sizeof(usb_hub_descriptor), 213 transfer->DataLength()); 214 sOHCIRootHubConfig.hub.num_ports = ohci->PortCount(); 215 memcpy(transfer->Data(), (void *)&sOHCIRootHubConfig.hub, 216 actualLength); 217 status = B_OK; 218 break; 219 } 220 } 221 break; 222 223 case USB_REQUEST_SET_CONFIGURATION: 224 status = B_OK; 225 break; 226 227 case USB_REQUEST_CLEAR_FEATURE: { 228 if (request->Index == 0) { 229 // we don't support any hub changes 230 TRACE_ERROR(("usb_ohci_roothub(): clear feature: no hub changes\n")); 231 break; 232 } 233 234 TRACE(("usb_ohci_roothub(): clear feature: %d\n", request->Value)); 235 if (ohci->ClearPortFeature(request->Index - 1, request->Value) >= B_OK) 236 status = B_OK; 237 break; 238 } 239 240 case USB_REQUEST_SET_FEATURE: { 241 if (request->Index == 0) { 242 // we don't support any hub changes 243 TRACE_ERROR(("usb_ohci_roothub(): set feature: no hub changes\n")); 244 break; 245 } 246 247 TRACE(("usb_ohci_roothub(): set feature: %d\n", request->Value)); 248 if (ohci->SetPortFeature(request->Index - 1, request->Value) >= B_OK) 249 status = B_OK; 250 break; 251 } 252 } 253 254 transfer->Finished(status, actualLength); 255 delete transfer; 256 return B_OK; 257 } 258