vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / busses / usb / ehci_rh.cpp
blob4b5ce959ba3bd4c13e791ac1f05832e2d3d3cfe9
1 /*
2 * Copyright 2006, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Michael Lotz <mmlr@mlotz.ch>
7 */
9 #include "ehci.h"
11 #define USB_MODULE_NAME "ehci roothub"
13 static usb_device_descriptor sEHCIRootHubDevice =
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
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;
40 static ehci_root_hub_configuration_s sEHCIRootHubConfig =
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)
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
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
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
89 struct ehci_root_hub_string_s {
90 uint8 length;
91 uint8 descriptor_type;
92 uint16 unicode_string[12];
93 } _PACKED;
96 static ehci_root_hub_string_s sEHCIRootHubStrings[3] = {
98 4, // Descriptor length
99 USB_DESCRIPTOR_STRING, // Descriptor type
101 0x0409 // Supported language IDs (English US)
106 22, // Descriptor length
107 USB_DESCRIPTOR_STRING, // Descriptor type
109 'H', 'A', 'I', 'K', 'U', // Characters
110 ' ', 'I', 'n', 'c', '.'
115 26, // Descriptor length
116 USB_DESCRIPTOR_STRING, // Descriptor type
118 'E', 'H', 'C', 'I', ' ', // Characters
119 'R', 'o', 'o', 't', 'H',
120 'u', 'b'
126 EHCIRootHub::EHCIRootHub(Object *rootObject, int8 deviceAddress)
127 : Hub(rootObject, 0, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()),
128 sEHCIRootHubDevice, deviceAddress, USB_SPEED_HIGHSPEED, true)
133 status_t
134 EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer)
136 if ((transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) == 0)
137 return B_ERROR;
139 usb_request_data *request = transfer->RequestData();
140 TRACE_MODULE("request: %d\n", request->Request);
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;
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;
165 break;
168 case USB_REQUEST_SET_ADDRESS:
169 if (request->Value >= 128) {
170 status = B_TIMED_OUT;
171 break;
174 TRACE_MODULE("set address: %d\n", request->Value);
175 status = B_OK;
176 break;
178 case USB_REQUEST_GET_DESCRIPTOR:
179 TRACE_MODULE("get descriptor: %d\n", request->Value >> 8);
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;
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;
201 case USB_DESCRIPTOR_STRING: {
202 uint8 index = request->Value & 0x00ff;
203 if (index > 2)
204 break;
206 actualLength = MIN(sEHCIRootHubStrings[index].length,
207 transfer->DataLength());
208 memcpy(transfer->Data(), (void *)&sEHCIRootHubStrings[index],
209 actualLength);
210 status = B_OK;
211 break;
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;
224 break;
226 case USB_REQUEST_SET_CONFIGURATION:
227 status = B_OK;
228 break;
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;
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;
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;
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;
257 transfer->Finished(status, actualLength);
258 delete transfer;
259 return B_OK;