vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / busses / usb / xhci_rh.cpp
blob5556c8c08cd44b211d4e13e5cc6a3878b6a0c0b9
1 /*
2 * Copyright 2011, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Michael Lotz <mmlr@mlotz.ch>
7 * Jian Chiang <j.jian.chiang@gmail.com>
8 */
11 #include "xhci.h"
13 #define USB_MODULE_NAME "xhci roothub"
15 static usb_device_descriptor sXHCIRootHubDevice =
17 18, // Descriptor length
18 USB_DESCRIPTOR_DEVICE, // Descriptor type
19 0x300, // USB 3.0
20 0x09, // Class (9 = Hub)
21 0, // Subclass
22 3, // Protocol
23 9, // Max packet size on endpoint 0
24 0, // Vendor ID
25 0, // Product ID
26 0x300, // 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
34 struct usb_endpoint_ss_comp_descriptor {
35 uint8 length;
36 uint8 descriptor_type;
37 uint16 burst;
38 uint8 attributes;
39 uint16 internal;
40 } _PACKED;
43 struct xhci_root_hub_configuration_s {
44 usb_configuration_descriptor configuration;
45 usb_interface_descriptor interface;
46 usb_endpoint_descriptor endpoint;
47 usb_endpoint_ss_comp_descriptor endpc;
48 usb_hub_descriptor hub;
49 } _PACKED;
52 static xhci_root_hub_configuration_s sXHCIRootHubConfig =
54 { // configuration descriptor
55 9, // Descriptor length
56 USB_DESCRIPTOR_CONFIGURATION, // Descriptor type
57 sizeof(sXHCIRootHubConfig), // Total length of configuration (including
58 // interface, endpoint and hub descriptors)
59 1, // Number of interfaces
60 1, // Value of this configuration
61 0, // Index of configuration string
62 0x40, // Attributes (0x40 = self powered)
63 0 // Max power (0, since self powered)
66 { // interface descriptor
67 9, // Descriptor length
68 USB_DESCRIPTOR_INTERFACE, // Descriptor type
69 0, // Interface number
70 0, // Alternate setting
71 1, // Number of endpoints
72 0x09, // Interface class (9 = Hub)
73 0, // Interface subclass
74 0, // Interface protocol
75 0 // Index of interface string
78 { // endpoint descriptor
79 7, // Descriptor length
80 USB_DESCRIPTOR_ENDPOINT, // Descriptor type
81 USB_REQTYPE_DEVICE_IN | 1, // Endpoint address (first in IN endpoint)
82 0x03, // Attributes (0x03 = interrupt endpoint)
83 2, // Max packet size
84 0xff // Interval
87 { // endpoint companion descriptor
89 0x30,
95 { // hub descriptor
96 9, // Descriptor length (including
97 // deprecated power control mask)
98 USB_DESCRIPTOR_HUB, // Descriptor type
99 0x0f, // Number of ports
100 0x0000, // Hub characteristics
101 10, // Power on to power good (in 2ms units)
102 0, // Maximum current (in mA)
103 0x00, // All ports are removable
104 0xff // Deprecated power control mask
109 struct xhci_root_hub_string_s {
110 uint8 length;
111 uint8 descriptor_type;
112 uint16 unicode_string[12];
113 } _PACKED;
116 static xhci_root_hub_string_s sXHCIRootHubStrings[3] = {
118 4, // Descriptor length
119 USB_DESCRIPTOR_STRING, // Descriptor type
121 0x0409 // Supported language IDs (English US)
126 22, // Descriptor length
127 USB_DESCRIPTOR_STRING, // Descriptor type
129 'H', 'A', 'I', 'K', 'U', // Characters
130 ' ', 'I', 'n', 'c', '.'
135 26, // Descriptor length
136 USB_DESCRIPTOR_STRING, // Descriptor type
138 'X', 'H', 'C', 'I', ' ', // Characters
139 'R', 'o', 'o', 't', 'H',
140 'u', 'b'
146 XHCIRootHub::XHCIRootHub(Object *rootObject, int8 deviceAddress)
147 : Hub(rootObject, 0, rootObject->GetStack()->IndexOfBusManager(rootObject->GetBusManager()),
148 sXHCIRootHubDevice, deviceAddress, USB_SPEED_SUPER, true)
153 status_t
154 XHCIRootHub::ProcessTransfer(XHCI *xhci, Transfer *transfer)
156 if ((transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) == 0)
157 return B_ERROR;
159 usb_request_data *request = transfer->RequestData();
160 TRACE_MODULE("request: %d\n", request->Request);
162 status_t status = B_TIMED_OUT;
163 size_t actualLength = 0;
164 switch (request->Request) {
165 case USB_REQUEST_GET_STATUS: {
166 if (request->Index == 0) {
167 // get hub status
168 actualLength = MIN(sizeof(usb_port_status),
169 transfer->DataLength());
170 // the hub reports whether the local power failed (bit 0)
171 // and if there is a over-current condition (bit 1).
172 // everything as 0 means all is ok.
173 memset(transfer->Data(), 0, actualLength);
174 status = B_OK;
175 break;
178 usb_port_status portStatus;
179 if (xhci->GetPortStatus(request->Index - 1, &portStatus) >= B_OK) {
180 actualLength = MIN(sizeof(usb_port_status), transfer->DataLength());
181 memcpy(transfer->Data(), (void *)&portStatus, actualLength);
182 status = B_OK;
185 break;
188 case USB_REQUEST_SET_ADDRESS:
189 if (request->Value >= 128) {
190 status = B_TIMED_OUT;
191 break;
194 TRACE_MODULE("set address: %d\n", request->Value);
195 status = B_OK;
196 break;
198 case USB_REQUEST_GET_DESCRIPTOR:
199 TRACE_MODULE("get descriptor: %d\n", request->Value >> 8);
201 switch (request->Value >> 8) {
202 case USB_DESCRIPTOR_DEVICE: {
203 actualLength = MIN(sizeof(usb_device_descriptor),
204 transfer->DataLength());
205 memcpy(transfer->Data(), (void *)&sXHCIRootHubDevice,
206 actualLength);
207 status = B_OK;
208 break;
211 case USB_DESCRIPTOR_CONFIGURATION: {
212 actualLength = MIN(sizeof(xhci_root_hub_configuration_s),
213 transfer->DataLength());
214 sXHCIRootHubConfig.hub.num_ports = xhci->PortCount();
215 memcpy(transfer->Data(), (void *)&sXHCIRootHubConfig,
216 actualLength);
217 status = B_OK;
218 break;
221 case USB_DESCRIPTOR_STRING: {
222 uint8 index = request->Value & 0x00ff;
223 if (index > 2)
224 break;
226 actualLength = MIN(sXHCIRootHubStrings[index].length,
227 transfer->DataLength());
228 memcpy(transfer->Data(), (void *)&sXHCIRootHubStrings[index],
229 actualLength);
230 status = B_OK;
231 break;
234 case USB_DESCRIPTOR_HUB: {
235 actualLength = MIN(sizeof(usb_hub_descriptor),
236 transfer->DataLength());
237 sXHCIRootHubConfig.hub.num_ports = xhci->PortCount();
238 memcpy(transfer->Data(), (void *)&sXHCIRootHubConfig.hub,
239 actualLength);
240 status = B_OK;
241 break;
244 break;
246 case USB_REQUEST_SET_CONFIGURATION:
247 status = B_OK;
248 break;
250 case USB_REQUEST_CLEAR_FEATURE: {
251 if (request->Index == 0) {
252 // we don't support any hub changes
253 TRACE_MODULE_ERROR("clear feature: no hub changes\n");
254 break;
257 TRACE_MODULE("clear feature: %d\n", request->Value);
258 if (xhci->ClearPortFeature(request->Index - 1, request->Value) >= B_OK)
259 status = B_OK;
260 break;
263 case USB_REQUEST_SET_FEATURE: {
264 if (request->Index == 0) {
265 // we don't support any hub changes
266 TRACE_MODULE_ERROR("set feature: no hub changes\n");
267 break;
270 TRACE_MODULE("set feature: %d\n", request->Value);
271 if (xhci->SetPortFeature(request->Index - 1, request->Value) >= B_OK)
272 status = B_OK;
273 break;
277 transfer->Finished(status, actualLength);
278 delete transfer;
279 return B_OK;