xref: /haiku/src/add-ons/kernel/bus_managers/usb/Device.cpp (revision 1f52c921e27aa442370e1bd4adc021acf2b78b64)
1 /*
2  * Copyright 2003-2014, 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 
11 #include "usb_private.h"
12 
13 
14 Device::Device(Object* parent, int8 hubAddress, uint8 hubPort,
15 	usb_device_descriptor& desc, int8 deviceAddress, usb_speed speed,
16 	bool isRootHub, void* controllerCookie)
17 	:
18 	Object(parent),
19 	fDeviceDescriptor(desc),
20 	fInitOK(false),
21 	fAvailable(true),
22 	fIsRootHub(isRootHub),
23 	fConfigurations(NULL),
24 	fCurrentConfiguration(NULL),
25 	fSpeed(speed),
26 	fDeviceAddress(deviceAddress),
27 	fHubAddress(hubAddress),
28 	fHubPort(hubPort),
29 	fControllerCookie(controllerCookie)
30 {
31 	TRACE("creating device\n");
32 
33 	fDefaultPipe = new(std::nothrow) ControlPipe(this);
34 	if (fDefaultPipe == NULL) {
35 		TRACE_ERROR("could not allocate default pipe\n");
36 		return;
37 	}
38 
39 	fDefaultPipe->InitCommon(fDeviceAddress, 0, fSpeed, Pipe::Default,
40 		fDeviceDescriptor.max_packet_size_0, 0, fHubAddress, fHubPort);
41 
42 	// Get the device descriptor
43 	// We already have a part of it, but we want it all
44 	size_t actualLength;
45 	status_t status = GetDescriptor(USB_DESCRIPTOR_DEVICE, 0, 0,
46 		(void*)&fDeviceDescriptor, sizeof(fDeviceDescriptor), &actualLength);
47 
48 	if (status < B_OK || actualLength != sizeof(fDeviceDescriptor)) {
49 		TRACE_ERROR("error while getting the device descriptor\n");
50 		return;
51 	}
52 
53 	TRACE("full device descriptor for device %d:\n", fDeviceAddress);
54 	TRACE("\tlength:..............%d\n", fDeviceDescriptor.length);
55 	TRACE("\tdescriptor_type:.....0x%04x\n", fDeviceDescriptor.descriptor_type);
56 	TRACE("\tusb_version:.........0x%04x\n", fDeviceDescriptor.usb_version);
57 	TRACE("\tdevice_class:........0x%02x\n", fDeviceDescriptor.device_class);
58 	TRACE("\tdevice_subclass:.....0x%02x\n", fDeviceDescriptor.device_subclass);
59 	TRACE("\tdevice_protocol:.....0x%02x\n", fDeviceDescriptor.device_protocol);
60 	TRACE("\tmax_packet_size_0:...%d\n", fDeviceDescriptor.max_packet_size_0);
61 	TRACE("\tvendor_id:...........0x%04x\n", fDeviceDescriptor.vendor_id);
62 	TRACE("\tproduct_id:..........0x%04x\n", fDeviceDescriptor.product_id);
63 	TRACE("\tdevice_version:......0x%04x\n", fDeviceDescriptor.device_version);
64 	TRACE("\tmanufacturer:........0x%02x\n", fDeviceDescriptor.manufacturer);
65 	TRACE("\tproduct:.............0x%02x\n", fDeviceDescriptor.product);
66 	TRACE("\tserial_number:.......0x%02x\n", fDeviceDescriptor.serial_number);
67 	TRACE("\tnum_configurations:..%d\n", fDeviceDescriptor.num_configurations);
68 
69 	// Get the configurations
70 	fConfigurations = (usb_configuration_info*)malloc(
71 		fDeviceDescriptor.num_configurations * sizeof(usb_configuration_info));
72 	if (fConfigurations == NULL) {
73 		TRACE_ERROR("out of memory during config creations!\n");
74 		return;
75 	}
76 
77 	memset(fConfigurations, 0, fDeviceDescriptor.num_configurations
78 		* sizeof(usb_configuration_info));
79 	for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
80 		usb_configuration_descriptor configDescriptor;
81 		status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
82 			(void*)&configDescriptor, sizeof(usb_configuration_descriptor),
83 			&actualLength);
84 
85 		if (status < B_OK
86 			|| actualLength != sizeof(usb_configuration_descriptor)) {
87 			TRACE_ERROR("error fetching configuration %" B_PRId32 "\n", i);
88 			return;
89 		}
90 
91 		TRACE("configuration %" B_PRId32 "\n", i);
92 		TRACE("\tlength:..............%d\n", configDescriptor.length);
93 		TRACE("\tdescriptor_type:.....0x%02x\n",
94 			configDescriptor.descriptor_type);
95 		TRACE("\ttotal_length:........%d\n", configDescriptor.total_length);
96 		TRACE("\tnumber_interfaces:...%d\n",
97 			configDescriptor.number_interfaces);
98 		TRACE("\tconfiguration_value:.0x%02x\n",
99 			configDescriptor.configuration_value);
100 		TRACE("\tconfiguration:.......0x%02x\n",
101 			configDescriptor.configuration);
102 		TRACE("\tattributes:..........0x%02x\n", configDescriptor.attributes);
103 		TRACE("\tmax_power:...........%d\n", configDescriptor.max_power);
104 
105 		uint8* configData = (uint8*)malloc(configDescriptor.total_length);
106 		if (configData == NULL) {
107 			TRACE_ERROR("out of memory when reading config\n");
108 			return;
109 		}
110 
111 		status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
112 			(void*)configData, configDescriptor.total_length, &actualLength);
113 
114 		if (status < B_OK || actualLength != configDescriptor.total_length) {
115 			TRACE_ERROR("error fetching full configuration"
116 				" descriptor %" B_PRId32 " got %" B_PRIuSIZE " expected %"
117 				B_PRIu16 "\n", i, actualLength, configDescriptor.total_length);
118 			free(configData);
119 			return;
120 		}
121 
122 		usb_configuration_descriptor* configuration
123 			= (usb_configuration_descriptor*)configData;
124 		fConfigurations[i].descr = configuration;
125 		fConfigurations[i].interface_count = configuration->number_interfaces;
126 		fConfigurations[i].interface = (usb_interface_list*)malloc(
127 			configuration->number_interfaces * sizeof(usb_interface_list));
128 		if (fConfigurations[i].interface == NULL) {
129 			TRACE_ERROR("out of memory when creating interfaces\n");
130 			return;
131 		}
132 
133 		memset(fConfigurations[i].interface, 0,
134 			configuration->number_interfaces * sizeof(usb_interface_list));
135 
136 		usb_interface_info* currentInterface = NULL;
137 		uint32 descriptorStart = sizeof(usb_configuration_descriptor);
138 		while (descriptorStart < actualLength) {
139 			switch (configData[descriptorStart + 1]) {
140 				case USB_DESCRIPTOR_INTERFACE:
141 				{
142 					TRACE("got interface descriptor\n");
143 					usb_interface_descriptor* interfaceDescriptor
144 						= (usb_interface_descriptor*)&configData[
145 							descriptorStart];
146 					TRACE("\tlength:.............%d\n",
147 						interfaceDescriptor->length);
148 					TRACE("\tdescriptor_type:....0x%02x\n",
149 						interfaceDescriptor->descriptor_type);
150 					TRACE("\tinterface_number:...%d\n",
151 						interfaceDescriptor->interface_number);
152 					TRACE("\talternate_setting:..%d\n",
153 						interfaceDescriptor->alternate_setting);
154 					TRACE("\tnum_endpoints:......%d\n",
155 						interfaceDescriptor->num_endpoints);
156 					TRACE("\tinterface_class:....0x%02x\n",
157 						interfaceDescriptor->interface_class);
158 					TRACE("\tinterface_subclass:.0x%02x\n",
159 						interfaceDescriptor->interface_subclass);
160 					TRACE("\tinterface_protocol:.0x%02x\n",
161 						interfaceDescriptor->interface_protocol);
162 					TRACE("\tinterface:..........%d\n",
163 						interfaceDescriptor->interface);
164 
165 					if (interfaceDescriptor->interface_number
166 							>= fConfigurations[i].interface_count) {
167 						interfaceDescriptor->interface_number
168 							= fConfigurations[i].interface_count - 1;
169 						TRACE_ERROR("Corrected invalid interface_number!\n");
170 					}
171 
172 					usb_interface_list* interfaceList = &fConfigurations[i]
173 						.interface[interfaceDescriptor->interface_number];
174 
175 					// Allocate this alternate
176 					interfaceList->alt_count++;
177 					usb_interface_info* newAlternates
178 						= (usb_interface_info*)realloc(interfaceList->alt,
179 						interfaceList->alt_count * sizeof(usb_interface_info));
180 					if (newAlternates == NULL) {
181 						TRACE_ERROR("out of memory allocating"
182 							" alternate interface\n");
183 						interfaceList->alt_count--;
184 						return;
185 					}
186 
187 					interfaceList->alt = newAlternates;
188 
189 					// Set active interface always to the first one
190 					interfaceList->active = interfaceList->alt;
191 
192 					// Setup this alternate
193 					usb_interface_info* interfaceInfo
194 						= &interfaceList->alt[interfaceList->alt_count - 1];
195 					interfaceInfo->descr = interfaceDescriptor;
196 					interfaceInfo->endpoint_count = 0;
197 					interfaceInfo->endpoint = NULL;
198 					interfaceInfo->generic_count = 0;
199 					interfaceInfo->generic = NULL;
200 
201 					Interface* interface = new(std::nothrow) Interface(this,
202 						interfaceDescriptor->interface_number);
203 					if (interface == NULL) {
204 						TRACE_ERROR("failed to allocate"
205 							" interface object\n");
206 						return;
207 					}
208 
209 					interfaceInfo->handle = interface->USBID();
210 					currentInterface = interfaceInfo;
211 					break;
212 				}
213 
214 				case USB_DESCRIPTOR_ENDPOINT:
215 				{
216 					TRACE("got endpoint descriptor\n");
217 					usb_endpoint_descriptor* endpointDescriptor
218 						= (usb_endpoint_descriptor*)&configData[descriptorStart];
219 					TRACE("\tlength:.............%d\n",
220 						endpointDescriptor->length);
221 					TRACE("\tdescriptor_type:....0x%02x\n",
222 						endpointDescriptor->descriptor_type);
223 					TRACE("\tendpoint_address:...0x%02x\n",
224 						endpointDescriptor->endpoint_address);
225 					TRACE("\tattributes:.........0x%02x\n",
226 						endpointDescriptor->attributes);
227 					TRACE("\tmax_packet_size:....%d\n",
228 						endpointDescriptor->max_packet_size);
229 					TRACE("\tinterval:...........%d\n",
230 						endpointDescriptor->interval);
231 
232 					if (currentInterface == NULL)
233 						break;
234 
235 					// Allocate this endpoint
236 					currentInterface->endpoint_count++;
237 					usb_endpoint_info* newEndpoints = (usb_endpoint_info*)
238 						realloc(currentInterface->endpoint,
239 							currentInterface->endpoint_count
240 								* sizeof(usb_endpoint_info));
241 					if (newEndpoints == NULL) {
242 						TRACE_ERROR("out of memory allocating new endpoint\n");
243 						currentInterface->endpoint_count--;
244 						return;
245 					}
246 
247 					currentInterface->endpoint = newEndpoints;
248 
249 					// Setup this endpoint
250 					usb_endpoint_info* endpointInfo = &currentInterface
251 						->endpoint[currentInterface->endpoint_count - 1];
252 					endpointInfo->descr = endpointDescriptor;
253 					endpointInfo->handle = 0;
254 					break;
255 				}
256 
257 				case USB_DESCRIPTOR_ENDPOINT_COMPANION: {
258 					if (currentInterface != NULL) {
259 						usb_endpoint_descriptor* desc
260 							= currentInterface->endpoint[
261 								currentInterface->endpoint_count - 1].descr;
262 						if ((uint8*)desc != (&configData[descriptorStart
263 								- desc->length])) {
264 							TRACE_ERROR("found endpoint companion descriptor "
265 								"not immediately following endpoint "
266 								"descriptor, ignoring!\n");
267 							break;
268 						}
269 						// TODO: It'd be nicer if we could store the endpoint
270 						// companion descriptor along with the endpoint
271 						// descriptor, but as the interface struct is public
272 						// API, that would be an ABI break.
273 					}
274 
275 					// fall through
276 				}
277 
278 				default:
279 					TRACE("got generic descriptor\n");
280 					usb_generic_descriptor* genericDescriptor
281 						= (usb_generic_descriptor*)&configData[descriptorStart];
282 					TRACE("\tlength:.............%d\n",
283 						genericDescriptor->length);
284 					TRACE("\tdescriptor_type:....0x%02x\n",
285 						genericDescriptor->descriptor_type);
286 
287 					if (currentInterface == NULL)
288 						break;
289 
290 					// Allocate this descriptor
291 					currentInterface->generic_count++;
292 					usb_descriptor** newGenerics = (usb_descriptor**)realloc(
293 						currentInterface->generic,
294 						currentInterface->generic_count
295 							* sizeof(usb_descriptor*));
296 					if (newGenerics == NULL) {
297 						TRACE_ERROR("out of memory allocating"
298 							" generic descriptor\n");
299 						currentInterface->generic_count--;
300 						return;
301 					}
302 
303 					currentInterface->generic = newGenerics;
304 
305 					// Add this descriptor
306 					currentInterface->generic[
307 						currentInterface->generic_count - 1]
308 							= (usb_descriptor*)genericDescriptor;
309 					break;
310 			}
311 
312 			descriptorStart += configData[descriptorStart];
313 		}
314 	}
315 
316 	// Set default configuration
317 	TRACE("setting default configuration\n");
318 	if (SetConfigurationAt(0) != B_OK) {
319 		TRACE_ERROR("failed to set default configuration\n");
320 		return;
321 	}
322 
323 	fInitOK = true;
324 }
325 
326 
327 Device::~Device()
328 {
329 	// Unset fInitOK to indicate we are tearing down.
330 	fInitOK = false;
331 
332 	delete fDefaultPipe;
333 
334 	if (fConfigurations == NULL) {
335 		// we didn't get far in device setup, so everything below is unneeded
336 		return;
337 	}
338 
339 	// Destroy open endpoints. Do not send a device request to unconfigure
340 	// though, since we may be deleted because the device was unplugged
341 	// already.
342 	Unconfigure(false);
343 
344 	// Free all allocated resources
345 	for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
346 		usb_configuration_info* configuration = &fConfigurations[i];
347 		if (configuration == NULL)
348 			continue;
349 
350 		free(configuration->descr);
351 		if (configuration->interface == NULL)
352 			continue;
353 
354 		for (size_t j = 0; j < configuration->interface_count; j++) {
355 			usb_interface_list* interfaceList = &configuration->interface[j];
356 			if (interfaceList->alt == NULL)
357 				continue;
358 
359 			for (size_t k = 0; k < interfaceList->alt_count; k++) {
360 				usb_interface_info* interface = &interfaceList->alt[k];
361 				delete (Interface*)GetStack()->GetObject(interface->handle);
362 				free(interface->endpoint);
363 				free(interface->generic);
364 			}
365 
366 			free(interfaceList->alt);
367 		}
368 
369 		free(configuration->interface);
370 	}
371 
372 	free(fConfigurations);
373 }
374 
375 
376 status_t
377 Device::InitCheck()
378 {
379 	if (fInitOK)
380 		return B_OK;
381 
382 	return B_ERROR;
383 }
384 
385 
386 status_t
387 Device::Changed(change_item** changeList, bool added)
388 {
389 	fAvailable = added;
390 	change_item* changeItem = new(std::nothrow) change_item;
391 	if (changeItem == NULL)
392 		return B_NO_MEMORY;
393 
394 	changeItem->added = added;
395 	changeItem->device = this;
396 	changeItem->link = *changeList;
397 	*changeList = changeItem;
398 	return B_OK;
399 }
400 
401 
402 status_t
403 Device::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
404 	void* data, size_t dataLength, size_t* actualLength)
405 {
406 	if (!fAvailable)
407 		return B_ERROR;
408 
409 	return fDefaultPipe->SendRequest(
410 		USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD,
411 		USB_REQUEST_GET_DESCRIPTOR, (descriptorType << 8) | index,
412 		languageID, dataLength, data, dataLength, actualLength);
413 }
414 
415 
416 const usb_configuration_info*
417 Device::Configuration() const
418 {
419 	return fCurrentConfiguration;
420 }
421 
422 
423 const usb_configuration_info*
424 Device::ConfigurationAt(uint8 index) const
425 {
426 	if (index >= fDeviceDescriptor.num_configurations)
427 		return NULL;
428 
429 	return &fConfigurations[index];
430 }
431 
432 
433 status_t
434 Device::SetConfiguration(const usb_configuration_info* configuration)
435 {
436 	if (!configuration)
437 		return Unconfigure(true);
438 
439 	for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
440 		if (configuration->descr->configuration_value
441 				== fConfigurations[i].descr->configuration_value)
442 			return SetConfigurationAt(i);
443 	}
444 
445 	return B_BAD_VALUE;
446 }
447 
448 
449 status_t
450 Device::SetConfigurationAt(uint8 index)
451 {
452 	if (!fAvailable)
453 		return B_ERROR;
454 	if (index >= fDeviceDescriptor.num_configurations)
455 		return B_BAD_VALUE;
456 	if (&fConfigurations[index] == fCurrentConfiguration)
457 		return B_OK;
458 
459 	// Destroy our open endpoints
460 	Unconfigure(false);
461 
462 	// Tell the device to set the configuration
463 	status_t result = fDefaultPipe->SendRequest(
464 		USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD,
465 		USB_REQUEST_SET_CONFIGURATION,
466 		fConfigurations[index].descr->configuration_value, 0, 0, NULL, 0, NULL);
467 	if (result < B_OK)
468 		return result;
469 
470 	// Set current configuration
471 	fCurrentConfiguration = &fConfigurations[index];
472 
473 	// Initialize all the endpoints that are now active
474 	InitEndpoints(-1);
475 
476 	// Wait some for the configuration being finished
477 	if (!fIsRootHub)
478 		snooze(USB_DELAY_SET_CONFIGURATION);
479 	return B_OK;
480 }
481 
482 
483 void
484 Device::InitEndpoints(int32 interfaceIndex)
485 {
486 	for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
487 		if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
488 			continue;
489 
490 		usb_interface_info* interfaceInfo
491 			= fCurrentConfiguration->interface[j].active;
492 		if (interfaceInfo == NULL)
493 			continue;
494 
495 		for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
496 			usb_endpoint_info* endpoint = &interfaceInfo->endpoint[i];
497 			Pipe* pipe = NULL;
498 
499 			usb_endpoint_companion_descriptor* comp_descr = NULL;
500 			if (fSpeed == USB_SPEED_SUPERSPEED) {
501 				// We should have a companion descriptor for this device.
502 				// Let's find it: it'll be the "i"th one.
503 				size_t k = 0;
504 				for (size_t j = 0; j < interfaceInfo->generic_count; j++) {
505 					usb_descriptor* desc = interfaceInfo->generic[j];
506 					if (desc->endpoint.descriptor_type
507 							!= USB_DESCRIPTOR_ENDPOINT_COMPANION) {
508 						continue;
509 					}
510 					if (k == i) {
511 						comp_descr = (usb_endpoint_companion_descriptor*)desc;
512 						break;
513 					}
514 					k++;
515 				}
516 				if (comp_descr == NULL) {
517 					TRACE_ERROR("SuperSpeed device without an endpoint companion "
518 						"descriptor!");
519 				}
520 			}
521 
522 			Pipe::pipeDirection direction = Pipe::Out;
523 			if ((endpoint->descr->endpoint_address & 0x80) != 0)
524 				direction = Pipe::In;
525 
526 			switch (endpoint->descr->attributes & 0x03) {
527 				case USB_ENDPOINT_ATTR_CONTROL:		// Control Endpoint
528 					pipe = new(std::nothrow) ControlPipe(this);
529 					direction = Pipe::Default;
530 					break;
531 
532 				case USB_ENDPOINT_ATTR_ISOCHRONOUS:	// Isochronous Endpoint
533 					pipe = new(std::nothrow) IsochronousPipe(this);
534 					break;
535 
536 				case USB_ENDPOINT_ATTR_BULK:		// Bulk Endpoint
537 					pipe = new(std::nothrow) BulkPipe(this);
538 					break;
539 
540 				case USB_ENDPOINT_ATTR_INTERRUPT:	// Interrupt Endpoint
541 					pipe = new(std::nothrow) InterruptPipe(this);
542 					break;
543 			}
544 
545 			if (pipe == NULL) {
546 				TRACE_ERROR("failed to allocate pipe\n");
547 				endpoint->handle = 0;
548 				continue;
549 			}
550 
551 			pipe->InitCommon(fDeviceAddress,
552 				endpoint->descr->endpoint_address & 0x0f,
553 				fSpeed, direction, endpoint->descr->max_packet_size,
554 				endpoint->descr->interval, fHubAddress, fHubPort);
555 			if (comp_descr != NULL) {
556 				pipe->InitSuperSpeed(comp_descr->max_burst,
557 					comp_descr->bytes_per_interval);
558 			}
559 			endpoint->handle = pipe->USBID();
560 		}
561 	}
562 }
563 
564 
565 status_t
566 Device::Unconfigure(bool atDeviceLevel)
567 {
568 	// If we only want to destroy our open pipes before setting
569 	// another configuration unconfigure will be called with
570 	// atDevice = false. otherwise we explicitly want to unconfigure
571 	// the device and have to send it the corresponding request.
572 	if (atDeviceLevel && fAvailable) {
573 		status_t result = fDefaultPipe->SendRequest(
574 			USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD,
575 			USB_REQUEST_SET_CONFIGURATION, 0, 0, 0, NULL, 0, NULL);
576 		if (result < B_OK)
577 			return result;
578 
579 		snooze(USB_DELAY_SET_CONFIGURATION);
580 	}
581 
582 	if (!fCurrentConfiguration)
583 		return B_OK;
584 
585 	ClearEndpoints(-1);
586 	fCurrentConfiguration = NULL;
587 	return B_OK;
588 }
589 
590 
591 void
592 Device::ClearEndpoints(int32 interfaceIndex)
593 {
594 	if (fCurrentConfiguration == NULL
595 		|| fCurrentConfiguration->interface == NULL)
596 		return;
597 
598 	for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
599 		if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
600 			continue;
601 
602 		usb_interface_info* interfaceInfo
603 			= fCurrentConfiguration->interface[j].active;
604 		if (interfaceInfo == NULL || interfaceInfo->endpoint == NULL)
605 			continue;
606 
607 		for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
608 			usb_endpoint_info* endpoint = &interfaceInfo->endpoint[i];
609 			delete (Pipe*)GetStack()->GetObject(endpoint->handle);
610 			endpoint->handle = 0;
611 		}
612 	}
613 }
614 
615 
616 status_t
617 Device::SetAltInterface(const usb_interface_info* interface)
618 {
619 	uint8 interfaceNumber = interface->descr->interface_number;
620 	// Tell the device to set the alternate settings
621 	status_t result = fDefaultPipe->SendRequest(
622 		USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_STANDARD,
623 		USB_REQUEST_SET_INTERFACE,
624 		interface->descr->alternate_setting, interfaceNumber, 0, NULL, 0, NULL);
625 	if (result < B_OK)
626 		return result;
627 
628 	// Clear the no longer active endpoints
629 	ClearEndpoints(interfaceNumber);
630 
631 	// Update the active pointer of the interface list
632 	usb_interface_list* interfaceList
633 		= &fCurrentConfiguration->interface[interfaceNumber];
634 	interfaceList->active
635 		= &interfaceList->alt[interface->descr->alternate_setting];
636 
637 	// Initialize the new endpoints
638 	InitEndpoints(interfaceNumber);
639 	return result;
640 }
641 
642 
643 const usb_device_descriptor*
644 Device::DeviceDescriptor() const
645 {
646 	return &fDeviceDescriptor;
647 }
648 
649 
650 status_t
651 Device::ReportDevice(usb_support_descriptor* supportDescriptors,
652 	uint32 supportDescriptorCount, const usb_notify_hooks* hooks,
653 	usb_driver_cookie** cookies, bool added, bool recursive)
654 {
655 	TRACE("reporting device\n");
656 	bool supported = false;
657 	if (supportDescriptorCount == 0 || supportDescriptors == NULL)
658 		supported = true;
659 
660 	for (uint32 i = 0; !supported && i < supportDescriptorCount; i++) {
661 		if ((supportDescriptors[i].vendor != 0
662 				&& fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor)
663 			|| (supportDescriptors[i].product != 0
664 				&& fDeviceDescriptor.product_id
665 					!= supportDescriptors[i].product))
666 			continue;
667 
668 		if ((supportDescriptors[i].dev_class == 0
669 				|| fDeviceDescriptor.device_class
670 					== supportDescriptors[i].dev_class)
671 			&& (supportDescriptors[i].dev_subclass == 0
672 				|| fDeviceDescriptor.device_subclass
673 					== supportDescriptors[i].dev_subclass)
674 			&& (supportDescriptors[i].dev_protocol == 0
675 				|| fDeviceDescriptor.device_protocol
676 					== supportDescriptors[i].dev_protocol)) {
677 			supported = true;
678 		}
679 
680 		// we have to check all interfaces for matching class/subclass/protocol
681 		for (uint32 j = 0;
682 				!supported && j < fDeviceDescriptor.num_configurations; j++) {
683 			for (uint32 k = 0;
684 					!supported && k < fConfigurations[j].interface_count; k++) {
685 				for (uint32 l = 0; !supported
686 					&& l < fConfigurations[j].interface[k].alt_count; l++) {
687 					usb_interface_descriptor* descriptor
688 						= fConfigurations[j].interface[k].alt[l].descr;
689 					if ((supportDescriptors[i].dev_class == 0
690 							|| descriptor->interface_class
691 								== supportDescriptors[i].dev_class)
692 						&& (supportDescriptors[i].dev_subclass == 0
693 							|| descriptor->interface_subclass
694 								== supportDescriptors[i].dev_subclass)
695 						&& (supportDescriptors[i].dev_protocol == 0
696 							|| descriptor->interface_protocol
697 								== supportDescriptors[i].dev_protocol)) {
698 						supported = true;
699 					}
700 				}
701 			}
702 		}
703 	}
704 
705 	if (!supported)
706 		return B_UNSUPPORTED;
707 
708 	if ((added && hooks->device_added == NULL)
709 		|| (!added && hooks->device_removed == NULL)) {
710 		// hooks are not installed, but report success to indicate that
711 		// the driver supports the device
712 		return B_OK;
713 	}
714 
715 	usb_id id = USBID();
716 	if (added) {
717 		usb_driver_cookie* cookie = new(std::nothrow) usb_driver_cookie;
718 		if (hooks->device_added(id, &cookie->cookie) >= B_OK) {
719 			cookie->device = id;
720 			cookie->link = *cookies;
721 			*cookies = cookie;
722 		} else
723 			delete cookie;
724 	} else {
725 		usb_driver_cookie** pointer = cookies;
726 		usb_driver_cookie* cookie = *cookies;
727 		while (cookie != NULL) {
728 			if (cookie->device == id)
729 				break;
730 			pointer = &cookie->link;
731 			cookie = cookie->link;
732 		}
733 
734 		if (cookie == NULL) {
735 			// the device is supported, but there is no cookie. this most
736 			// probably means that the device_added hook above failed.
737 			return B_OK;
738 		}
739 
740 		hooks->device_removed(cookie->cookie);
741 		*pointer = cookie->link;
742 		delete cookie;
743 	}
744 
745 	return B_OK;
746 }
747 
748 
749 status_t
750 Device::BuildDeviceName(char* string, uint32* index, size_t bufferSize,
751 	Device* device)
752 {
753 	if (!Parent() || (Parent()->Type() & USB_OBJECT_HUB) == 0)
754 		return B_ERROR;
755 
756 	((Hub*)Parent())->BuildDeviceName(string, index, bufferSize, this);
757 	return B_OK;
758 }
759 
760 
761 status_t
762 Device::SetFeature(uint16 selector)
763 {
764 	if (!fAvailable)
765 		return B_ERROR;
766 
767 	TRACE("set feature %u\n", selector);
768 	return fDefaultPipe->SendRequest(
769 		USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
770 		USB_REQUEST_SET_FEATURE, selector, 0, 0, NULL, 0, NULL);
771 }
772 
773 
774 status_t
775 Device::ClearFeature(uint16 selector)
776 {
777 	if (!fAvailable)
778 		return B_ERROR;
779 
780 	TRACE("clear feature %u\n", selector);
781 	return fDefaultPipe->SendRequest(
782 		USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
783 		USB_REQUEST_CLEAR_FEATURE, selector, 0, 0, NULL, 0, NULL);
784 }
785 
786 
787 status_t
788 Device::GetStatus(uint16* status)
789 {
790 	if (!fAvailable)
791 		return B_ERROR;
792 
793 	TRACE("get status\n");
794 	return fDefaultPipe->SendRequest(
795 		USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_IN,
796 		USB_REQUEST_GET_STATUS, 0, 0, 2, (void*)status, 2, NULL);
797 }
798