xref: /haiku/src/add-ons/kernel/bus_managers/usb/Device.cpp (revision 9ecf9d1c1d4888d341a6eac72112c72d1ae3a4cb)
1 /*
2  * Copyright 2003-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 "usb_p.h"
11 
12 
13 Device::Device(BusManager *bus, Device *parent, usb_device_descriptor &desc,
14 	int8 deviceAddress, bool lowSpeed)
15 	:	ControlPipe(bus, deviceAddress,
16 			lowSpeed ? Pipe::LowSpeed : Pipe::NormalSpeed,
17 			desc.max_packet_size_0),
18 		fDeviceDescriptor(desc),
19 		fConfigurations(NULL),
20 		fCurrentConfiguration(NULL),
21 		fInitOK(false),
22 		fLowSpeed(lowSpeed),
23 		fBus(bus),
24 		fParent(parent),
25 		fDeviceAddress(deviceAddress),
26 		fLock(-1),
27 		fNotifyCookie(NULL)
28 {
29 	TRACE(("USB Device: new device\n"));
30 
31 	fLock = create_sem(1, "USB Device Lock");
32 	if (fLock < B_OK) {
33 		TRACE_ERROR(("USB Device: could not create locking semaphore\n"));
34 		return;
35 	}
36 
37 	set_sem_owner(fLock, B_SYSTEM_TEAM);
38 
39 	fMaxPacketIn[0] = fMaxPacketOut[0] = fDeviceDescriptor.max_packet_size_0;
40 
41 	// Get the device descriptor
42 	// We already have a part of it, but we want it all
43 	size_t actualLength;
44 	status_t status = GetDescriptor(USB_DESCRIPTOR_DEVICE, 0, 0,
45 		(void *)&fDeviceDescriptor, sizeof(fDeviceDescriptor), &actualLength);
46 
47 	if (status < B_OK || actualLength != sizeof(fDeviceDescriptor)) {
48 		TRACE_ERROR(("USB Device: error while getting the device descriptor\n"));
49 		return;
50 	}
51 
52 	TRACE(("full device descriptor for device %d:\n", fDeviceAddress));
53 	TRACE(("\tlength:..............%d\n", fDeviceDescriptor.length));
54 	TRACE(("\tdescriptor_type:.....0x%04x\n", fDeviceDescriptor.descriptor_type));
55 	TRACE(("\tusb_version:.........0x%04x\n", fDeviceDescriptor.usb_version));
56 	TRACE(("\tdevice_class:........0x%02x\n", fDeviceDescriptor.device_class));
57 	TRACE(("\tdevice_subclass:.....0x%02x\n", fDeviceDescriptor.device_subclass));
58 	TRACE(("\tdevice_protocol:.....0x%02x\n", fDeviceDescriptor.device_protocol));
59 	TRACE(("\tmax_packet_size_0:...%d\n", fDeviceDescriptor.max_packet_size_0));
60 	TRACE(("\tvendor_id:...........0x%04x\n", fDeviceDescriptor.vendor_id));
61 	TRACE(("\tproduct_id:..........0x%04x\n", fDeviceDescriptor.product_id));
62 	TRACE(("\tdevice_version:......0x%04x\n", fDeviceDescriptor.device_version));
63 	TRACE(("\tmanufacturer:........0x%04x\n", fDeviceDescriptor.manufacturer));
64 	TRACE(("\tproduct:.............0x%02x\n", fDeviceDescriptor.product));
65 	TRACE(("\tserial_number:.......0x%02x\n", fDeviceDescriptor.serial_number));
66 	TRACE(("\tnum_configurations:..%d\n", fDeviceDescriptor.num_configurations));
67 
68 	// Get the configurations
69 	fConfigurations = (usb_configuration_info *)malloc(
70 		fDeviceDescriptor.num_configurations * sizeof(usb_configuration_info));
71 	if (fConfigurations == NULL) {
72 		TRACE_ERROR(("USB Device: out of memory during config creations!\n"));
73 		return;
74 	}
75 
76 	for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
77 		usb_configuration_descriptor configDescriptor;
78 		status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
79 			(void *)&configDescriptor, sizeof(usb_configuration_descriptor),
80 			&actualLength);
81 
82 		if (status < B_OK || actualLength != sizeof(usb_configuration_descriptor)) {
83 			TRACE_ERROR(("USB Device %d: error fetching configuration %ld\n", fDeviceAddress, i));
84 			return;
85 		}
86 
87 		TRACE(("USB Device %d: configuration %d\n", fDeviceAddress, i));
88 		TRACE(("\tlength:..............%d\n", configDescriptor.length));
89 		TRACE(("\tdescriptor_type:.....0x%02x\n", configDescriptor.descriptor_type));
90 		TRACE(("\ttotal_length:........%d\n", configDescriptor.total_length));
91 		TRACE(("\tnumber_interfaces:...%d\n", configDescriptor.number_interfaces));
92 		TRACE(("\tconfiguration_value:.0x%02x\n", configDescriptor.configuration_value));
93 		TRACE(("\tconfiguration:.......0x%02x\n", configDescriptor.configuration));
94 		TRACE(("\tattributes:..........0x%02x\n", configDescriptor.attributes));
95 		TRACE(("\tmax_power:...........%d\n", configDescriptor.max_power));
96 
97 		uint8 *configData = (uint8 *)malloc(configDescriptor.total_length);
98 		status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
99 			(void *)configData, configDescriptor.total_length, &actualLength);
100 
101 		if (status < B_OK || actualLength != configDescriptor.total_length) {
102 			TRACE_ERROR(("USB Device %d: error fetching full configuration descriptor %ld\n", fDeviceAddress, i));
103 			return;
104 		}
105 
106 		usb_configuration_descriptor *configuration = (usb_configuration_descriptor *)configData;
107 		fConfigurations[i].descr = configuration;
108 		fConfigurations[i].interface_count = configuration->number_interfaces;
109 		fConfigurations[i].interface = (usb_interface_list *)malloc(
110 			configuration->number_interfaces * sizeof(usb_interface_list));
111 		memset(fConfigurations[i].interface, 0,
112 			configuration->number_interfaces * sizeof(usb_interface_list));
113 
114 		usb_interface_info *currentInterface = NULL;
115 		uint32 descriptorStart = sizeof(usb_configuration_descriptor);
116 		while (descriptorStart < actualLength) {
117 			switch (configData[descriptorStart + 1]) {
118 				case USB_DESCRIPTOR_INTERFACE: {
119 					TRACE(("USB Device %d: got interface descriptor\n", fDeviceAddress));
120 					usb_interface_descriptor *interfaceDescriptor = (usb_interface_descriptor *)&configData[descriptorStart];
121 					TRACE(("\tlength:.............%d\n", interfaceDescriptor->length));
122 					TRACE(("\tdescriptor_type:....0x%02x\n", interfaceDescriptor->descriptor_type));
123 					TRACE(("\tinterface_number:...%d\n", interfaceDescriptor->interface_number));
124 					TRACE(("\talternate_setting:..%d\n", interfaceDescriptor->alternate_setting));
125 					TRACE(("\tnum_endpoints:......%d\n", interfaceDescriptor->num_endpoints));
126 					TRACE(("\tinterface_class:....0x%02x\n", interfaceDescriptor->interface_class));
127 					TRACE(("\tinterface_subclass:.0x%02x\n", interfaceDescriptor->interface_subclass));
128 					TRACE(("\tinterface_protocol:.0x%02x\n", interfaceDescriptor->interface_protocol));
129 					TRACE(("\tinterface:..........%d\n", interfaceDescriptor->interface));
130 
131 					usb_interface_list *interfaceList =
132 						&fConfigurations[i].interface[interfaceDescriptor->interface_number];
133 
134 					/* allocate this alternate */
135 					interfaceList->alt_count++;
136 					interfaceList->alt = (usb_interface_info *)realloc(
137 						interfaceList->alt, interfaceList->alt_count
138 						* sizeof(usb_interface_info));
139 					interfaceList->active = interfaceList->alt;
140 
141 					/* setup this alternate */
142 					usb_interface_info *interfaceInfo =
143 						&interfaceList->alt[interfaceList->alt_count - 1];
144 					interfaceInfo->descr = interfaceDescriptor;
145 					interfaceInfo->endpoint_count = 0;
146 					interfaceInfo->endpoint = NULL;
147 					interfaceInfo->generic_count = 0;
148 					interfaceInfo->generic = NULL;
149 
150 					Interface *interface = new(std::nothrow) Interface(this);
151 					interfaceInfo->handle = interface->USBID();
152 
153 					currentInterface = interfaceInfo;
154 					break;
155 				}
156 
157 				case USB_DESCRIPTOR_ENDPOINT: {
158 					TRACE(("USB Device %d: got endpoint descriptor\n", fDeviceAddress));
159 					usb_endpoint_descriptor *endpointDescriptor = (usb_endpoint_descriptor *)&configData[descriptorStart];
160 					TRACE(("\tlength:.............%d\n", endpointDescriptor->length));
161 					TRACE(("\tdescriptor_type:....0x%02x\n", endpointDescriptor->descriptor_type));
162 					TRACE(("\tendpoint_address:...0x%02x\n", endpointDescriptor->endpoint_address));
163 					TRACE(("\tattributes:.........0x%02x\n", endpointDescriptor->attributes));
164 					TRACE(("\tmax_packet_size:....%d\n", endpointDescriptor->max_packet_size));
165 					TRACE(("\tinterval:...........%d\n", endpointDescriptor->interval));
166 
167 					if (!currentInterface)
168 						break;
169 
170 					/* allocate this endpoint */
171 					currentInterface->endpoint_count++;
172 					currentInterface->endpoint = (usb_endpoint_info *)realloc(
173 						currentInterface->endpoint,
174 						currentInterface->endpoint_count
175 						* sizeof(usb_endpoint_info));
176 
177 					/* setup this endpoint */
178 					usb_endpoint_info *endpointInfo =
179 						&currentInterface->endpoint[currentInterface->endpoint_count - 1];
180 					endpointInfo->descr = endpointDescriptor;
181 
182 					Pipe *endpoint = NULL;
183 					switch (endpointDescriptor->attributes & 0x03) {
184 						case 0x00: /* Control Endpoint */
185 							endpoint = new(std::nothrow) ControlPipe(this,
186 								Speed(),
187 								endpointDescriptor->endpoint_address & 0x0f,
188 								endpointDescriptor->max_packet_size);
189 							break;
190 
191 						case 0x01: /* Isochronous Endpoint */
192 							endpoint = new(std::nothrow) IsochronousPipe(this,
193 								endpointDescriptor->endpoint_address & 0x80 > 0 ? Pipe::In : Pipe::Out,
194 								Speed(),
195 								endpointDescriptor->endpoint_address & 0x0f,
196 								endpointDescriptor->max_packet_size);
197 							break;
198 
199 						case 0x02: /* Bulk Endpoint */
200 							endpoint = new(std::nothrow) BulkPipe(this,
201 								endpointDescriptor->endpoint_address & 0x80 > 0 ? Pipe::In : Pipe::Out,
202 								Speed(),
203 								endpointDescriptor->endpoint_address & 0x0f,
204 								endpointDescriptor->max_packet_size);
205 							break;
206 
207 						case 0x03: /* Interrupt Endpoint */
208 							endpoint = new(std::nothrow) InterruptPipe(this,
209 								endpointDescriptor->endpoint_address & 0x80 > 0 ? Pipe::In : Pipe::Out,
210 								Speed(),
211 								endpointDescriptor->endpoint_address & 0x0f,
212 								endpointDescriptor->max_packet_size);
213 							break;
214 					}
215 
216 					endpointInfo->handle = endpoint->USBID();
217 					break;
218 				}
219 
220 				default:
221 					TRACE(("USB Device %d: got generic descriptor\n", fDeviceAddress));
222 					usb_generic_descriptor *genericDescriptor = (usb_generic_descriptor *)&configData[descriptorStart];
223 					TRACE(("\tlength:.............%d\n", genericDescriptor->length));
224 					TRACE(("\tdescriptor_type:....0x%02x\n", genericDescriptor->descriptor_type));
225 
226 					if (!currentInterface)
227 						break;
228 
229 					/* allocate this descriptor */
230 					currentInterface->generic_count++;
231 					currentInterface->generic = (usb_descriptor **)realloc(
232 						currentInterface->generic,
233 						currentInterface->generic_count
234 						* sizeof(usb_descriptor *));
235 
236 					/* add this descriptor */
237 					currentInterface->generic[currentInterface->generic_count] =
238 						(usb_descriptor *)genericDescriptor;
239 					break;
240 			}
241 
242 			descriptorStart += configData[descriptorStart];
243 		}
244 	}
245 
246 	// Set default configuration
247 	TRACE(("USB Device %d: setting default configuration\n", fDeviceAddress));
248 	if (SetConfigurationAt(0) < B_OK) {
249 		TRACE_ERROR(("USB Device %d: failed to set default configuration\n", fDeviceAddress));
250 		return;
251 	}
252 
253 	fInitOK = true;
254 }
255 
256 
257 status_t
258 Device::InitCheck()
259 {
260 	if (fInitOK)
261 		return B_OK;
262 
263 	return B_ERROR;
264 }
265 
266 
267 status_t
268 Device::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
269 	void *data, size_t dataLength, size_t *actualLength)
270 {
271 	return SendRequest(
272 		USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD,		// type
273 		USB_REQUEST_GET_DESCRIPTOR,							// request
274 		(descriptorType << 8) | index,						// value
275 		languageID,											// index
276 		dataLength,											// length
277 		data,												// buffer
278 		dataLength,											// buffer length
279 		actualLength);										// actual length
280 }
281 
282 
283 const usb_configuration_info *
284 Device::Configuration() const
285 {
286 	return fCurrentConfiguration;
287 }
288 
289 
290 const usb_configuration_info *
291 Device::ConfigurationAt(uint8 index) const
292 {
293 	if (index >= fDeviceDescriptor.num_configurations)
294 		return NULL;
295 
296 	return &fConfigurations[index];
297 }
298 
299 
300 status_t
301 Device::SetConfiguration(const usb_configuration_info *configuration)
302 {
303 	for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
304 		if (configuration == &fConfigurations[i])
305 			return SetConfigurationAt(i);
306 	}
307 
308 	return B_BAD_VALUE;
309 }
310 
311 
312 status_t
313 Device::SetConfigurationAt(uint8 index)
314 {
315 	if (index >= fDeviceDescriptor.num_configurations)
316 		return B_BAD_VALUE;
317 
318 	status_t result = SendRequest(
319 		USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD,		// type
320 		USB_REQUEST_SET_CONFIGURATION,						// request
321 		fConfigurations[index].descr->configuration_value,	// value
322 		0,													// index
323 		0,													// length
324 		NULL,												// buffer
325 		0,													// buffer length
326 		NULL);												// actual length
327 
328 	if (result < B_OK)
329 		return result;
330 
331 	// Set current configuration
332 	fCurrentConfiguration = &fConfigurations[index];
333 
334 	// Wait some for the configuration being finished
335 	snooze(USB_DELAY_SET_CONFIGURATION);
336 	return B_OK;
337 }
338 
339 
340 const usb_device_descriptor *
341 Device::DeviceDescriptor() const
342 {
343 	return &fDeviceDescriptor;
344 }
345 
346 
347 void
348 Device::ReportDevice(usb_support_descriptor *supportDescriptors,
349 	uint32 supportDescriptorCount, const usb_notify_hooks *hooks, bool added)
350 {
351 	TRACE(("USB Device ReportDevice\n"));
352 	if (supportDescriptorCount == 0 || supportDescriptors == NULL) {
353 		if (added && hooks->device_added != NULL)
354 			hooks->device_added(USBID(), &fNotifyCookie);
355 		else if (!added && hooks->device_removed != NULL)
356 			hooks->device_removed(fNotifyCookie);
357 		return;
358 	}
359 
360 	for (uint32 i = 0; i < supportDescriptorCount; i++) {
361 		if ((supportDescriptors[i].vendor != 0
362 			&& fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor)
363 			|| (supportDescriptors[i].product != 0
364 			&& fDeviceDescriptor.product_id != supportDescriptors[i].product))
365 			continue;
366 
367 		if ((supportDescriptors[i].dev_class == 0
368 			|| fDeviceDescriptor.device_class == supportDescriptors[i].dev_class)
369 			&& (supportDescriptors[i].dev_subclass == 0
370 			|| fDeviceDescriptor.device_subclass == supportDescriptors[i].dev_subclass)
371 			&& (supportDescriptors[i].dev_protocol == 0
372 			|| fDeviceDescriptor.device_protocol == supportDescriptors[i].dev_protocol)) {
373 
374 			if (added && hooks->device_added != NULL)
375 				hooks->device_added(USBID(), &fNotifyCookie);
376 			else if (!added && hooks->device_removed != NULL)
377 				hooks->device_removed(fNotifyCookie);
378 			return;
379 		}
380 
381 		// we have to check all interfaces for matching class/subclass/protocol
382 		for (uint32 j = 0; j < fDeviceDescriptor.num_configurations; j++) {
383 			for (uint32 k = 0; k < fConfigurations[j].interface_count; k++) {
384 				for (uint32 l = 0; l < fConfigurations[j].interface[k].alt_count; l++) {
385 					usb_interface_descriptor *descriptor = fConfigurations[j].interface[k].alt[l].descr;
386 					if ((supportDescriptors[i].dev_class == 0
387 						|| descriptor->interface_class == supportDescriptors[i].dev_class)
388 						&& (supportDescriptors[i].dev_subclass == 0
389 						|| descriptor->interface_subclass == supportDescriptors[i].dev_subclass)
390 						&& (supportDescriptors[i].dev_protocol == 0
391 						|| descriptor->interface_protocol == supportDescriptors[i].dev_protocol)) {
392 
393 						if (added && hooks->device_added != NULL)
394 							hooks->device_added(USBID(), &fNotifyCookie);
395 						else if (!added && hooks->device_removed != NULL)
396 							hooks->device_removed(fNotifyCookie);
397 						return;
398 					}
399 				}
400 			}
401 		}
402 	}
403 }
404 
405 
406 status_t
407 Device::BuildDeviceName(char *string, uint32 *index, size_t bufferSize,
408 	Device *device)
409 {
410 	if (!fParent)
411 		return B_ERROR;
412 
413 	fParent->BuildDeviceName(string, index, bufferSize, this);
414 	return B_OK;
415 }
416 
417 
418 status_t
419 Device::SetFeature(uint16 selector)
420 {
421 	return SendRequest(
422 		USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
423 		USB_REQUEST_SET_FEATURE,
424 		selector,
425 		0,
426 		0,
427 		NULL,
428 		0,
429 		NULL);
430 }
431 
432 
433 status_t
434 Device::ClearFeature(uint16 selector)
435 {
436 	return SendRequest(
437 		USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
438 		USB_REQUEST_CLEAR_FEATURE,
439 		selector,
440 		0,
441 		0,
442 		NULL,
443 		0,
444 		NULL);
445 }
446 
447 
448 status_t
449 Device::GetStatus(uint16 *status)
450 {
451 	return SendRequest(
452 		USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_IN,
453 		USB_REQUEST_GET_STATUS,
454 		0,
455 		0,
456 		2,
457 		(void *)status,
458 		2,
459 		NULL);
460 }
461