xref: /haiku/src/add-ons/kernel/bus_managers/usb/Device.cpp (revision 830f67ef991407f287dbc1238aa5f5906d90c991)
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_SS_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 	// Cancel transfers on the default pipe and put its USBID to prevent
330 	// further transfers from being queued.
331 	if (fDefaultPipe != NULL) {
332 		fDefaultPipe->PutUSBID(false);
333 		fDefaultPipe->CancelQueuedTransfers(true);
334 		fDefaultPipe->WaitForUnbusy();
335 	}
336 
337 	// Destroy open endpoints. Do not send a device request to unconfigure
338 	// though, since we may be deleted because the device was unplugged already.
339 	Unconfigure(false);
340 
341 	// Destroy all Interfaces in the Configurations hierarchy.
342 	for (int32 i = 0; fConfigurations != NULL
343 			&& i < fDeviceDescriptor.num_configurations; i++) {
344 		usb_configuration_info* configuration = &fConfigurations[i];
345 		if (configuration == NULL || configuration->interface == NULL)
346 			continue;
347 
348 		for (size_t j = 0; j < configuration->interface_count; j++) {
349 			usb_interface_list* interfaceList = &configuration->interface[j];
350 			if (interfaceList->alt == NULL)
351 				continue;
352 
353 			for (size_t k = 0; k < interfaceList->alt_count; k++) {
354 				usb_interface_info* interface = &interfaceList->alt[k];
355 				Interface* interfaceObject =
356 					(Interface*)GetStack()->GetObject(interface->handle);
357 				if (interfaceObject != NULL)
358 					interfaceObject->SetBusy(false);
359 				delete interfaceObject;
360 				interface->handle = 0;
361 			}
362 		}
363 	}
364 
365 	// Remove ourselves from the stack before deleting public structures.
366 	PutUSBID();
367 	delete fDefaultPipe;
368 
369 	if (fConfigurations == NULL) {
370 		// we didn't get far in device setup, so everything below is unneeded
371 		return;
372 	}
373 
374 	// Free the Configurations hierarchy.
375 	for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
376 		usb_configuration_info* configuration = &fConfigurations[i];
377 		if (configuration == NULL)
378 			continue;
379 
380 		free(configuration->descr);
381 		if (configuration->interface == NULL)
382 			continue;
383 
384 		for (size_t j = 0; j < configuration->interface_count; j++) {
385 			usb_interface_list* interfaceList = &configuration->interface[j];
386 			if (interfaceList->alt == NULL)
387 				continue;
388 
389 			for (size_t k = 0; k < interfaceList->alt_count; k++) {
390 				usb_interface_info* interface = &interfaceList->alt[k];
391 				free(interface->endpoint);
392 				free(interface->generic);
393 			}
394 
395 			free(interfaceList->alt);
396 		}
397 
398 		free(configuration->interface);
399 	}
400 
401 	free(fConfigurations);
402 }
403 
404 
405 status_t
406 Device::InitCheck()
407 {
408 	if (fInitOK)
409 		return B_OK;
410 
411 	return B_ERROR;
412 }
413 
414 
415 status_t
416 Device::Changed(change_item** changeList, bool added)
417 {
418 	fAvailable = added;
419 	change_item* changeItem = new(std::nothrow) change_item;
420 	if (changeItem == NULL)
421 		return B_NO_MEMORY;
422 
423 	changeItem->added = added;
424 	changeItem->device = this;
425 	changeItem->link = *changeList;
426 	*changeList = changeItem;
427 	return B_OK;
428 }
429 
430 
431 status_t
432 Device::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
433 	void* data, size_t dataLength, size_t* actualLength)
434 {
435 	if (!fAvailable)
436 		return B_ERROR;
437 
438 	return fDefaultPipe->SendRequest(
439 		USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD,
440 		USB_REQUEST_GET_DESCRIPTOR, (descriptorType << 8) | index,
441 		languageID, dataLength, data, dataLength, actualLength);
442 }
443 
444 
445 const usb_configuration_info*
446 Device::Configuration() const
447 {
448 	return fCurrentConfiguration;
449 }
450 
451 
452 const usb_configuration_info*
453 Device::ConfigurationAt(uint8 index) const
454 {
455 	if (index >= fDeviceDescriptor.num_configurations)
456 		return NULL;
457 
458 	return &fConfigurations[index];
459 }
460 
461 
462 status_t
463 Device::SetConfiguration(const usb_configuration_info* configuration)
464 {
465 	if (!configuration)
466 		return Unconfigure(true);
467 
468 	for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
469 		if (configuration->descr->configuration_value
470 				== fConfigurations[i].descr->configuration_value)
471 			return SetConfigurationAt(i);
472 	}
473 
474 	return B_BAD_VALUE;
475 }
476 
477 
478 status_t
479 Device::SetConfigurationAt(uint8 index)
480 {
481 	if (!fAvailable)
482 		return B_ERROR;
483 	if (index >= fDeviceDescriptor.num_configurations)
484 		return B_BAD_VALUE;
485 	if (&fConfigurations[index] == fCurrentConfiguration)
486 		return B_OK;
487 
488 	// Destroy our open endpoints
489 	Unconfigure(false);
490 
491 	// Tell the device to set the configuration
492 	status_t result = fDefaultPipe->SendRequest(
493 		USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD,
494 		USB_REQUEST_SET_CONFIGURATION,
495 		fConfigurations[index].descr->configuration_value, 0, 0, NULL, 0, NULL);
496 	if (result < B_OK)
497 		return result;
498 
499 	// Set current configuration
500 	fCurrentConfiguration = &fConfigurations[index];
501 
502 	// Initialize all the endpoints that are now active
503 	InitEndpoints(-1);
504 
505 	// Wait some for the configuration being finished
506 	if (!fIsRootHub)
507 		snooze(USB_DELAY_SET_CONFIGURATION);
508 	return B_OK;
509 }
510 
511 
512 void
513 Device::InitEndpoints(int32 interfaceIndex)
514 {
515 	for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
516 		if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
517 			continue;
518 
519 		usb_interface_info* interfaceInfo
520 			= fCurrentConfiguration->interface[j].active;
521 		if (interfaceInfo == NULL)
522 			continue;
523 
524 		for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
525 			usb_endpoint_info* endpoint = &interfaceInfo->endpoint[i];
526 			Pipe* pipe = NULL;
527 
528 			usb_endpoint_ss_companion_descriptor* comp_descr = NULL;
529 			if (fSpeed == USB_SPEED_SUPERSPEED) {
530 				// We should have a companion descriptor for this device.
531 				// Let's find it: it'll be the "i"th one.
532 				size_t k = 0;
533 				for (size_t j = 0; j < interfaceInfo->generic_count; j++) {
534 					usb_descriptor* desc = interfaceInfo->generic[j];
535 					if (desc->endpoint.descriptor_type
536 							!= USB_DESCRIPTOR_ENDPOINT_SS_COMPANION) {
537 						continue;
538 					}
539 					if (k == i) {
540 						comp_descr =
541 							(usb_endpoint_ss_companion_descriptor*)desc;
542 						break;
543 					}
544 					k++;
545 				}
546 				if (comp_descr == NULL) {
547 					TRACE_ERROR("SuperSpeed device without an endpoint companion "
548 						"descriptor!");
549 				}
550 			}
551 
552 			Pipe::pipeDirection direction = Pipe::Out;
553 			if ((endpoint->descr->endpoint_address & 0x80) != 0)
554 				direction = Pipe::In;
555 
556 			switch (endpoint->descr->attributes & 0x03) {
557 				case USB_ENDPOINT_ATTR_CONTROL:		// Control Endpoint
558 					pipe = new(std::nothrow) ControlPipe(this);
559 					direction = Pipe::Default;
560 					break;
561 
562 				case USB_ENDPOINT_ATTR_ISOCHRONOUS:	// Isochronous Endpoint
563 					pipe = new(std::nothrow) IsochronousPipe(this);
564 					break;
565 
566 				case USB_ENDPOINT_ATTR_BULK:		// Bulk Endpoint
567 					pipe = new(std::nothrow) BulkPipe(this);
568 					break;
569 
570 				case USB_ENDPOINT_ATTR_INTERRUPT:	// Interrupt Endpoint
571 					pipe = new(std::nothrow) InterruptPipe(this);
572 					break;
573 			}
574 
575 			if (pipe == NULL) {
576 				TRACE_ERROR("failed to allocate pipe\n");
577 				endpoint->handle = 0;
578 				continue;
579 			}
580 
581 			pipe->InitCommon(fDeviceAddress,
582 				endpoint->descr->endpoint_address & 0x0f,
583 				fSpeed, direction, endpoint->descr->max_packet_size,
584 				endpoint->descr->interval, fHubAddress, fHubPort);
585 			if (comp_descr != NULL) {
586 				pipe->InitSuperSpeed(comp_descr->max_burst,
587 					comp_descr->bytes_per_interval);
588 			}
589 			endpoint->handle = pipe->USBID();
590 		}
591 	}
592 }
593 
594 
595 status_t
596 Device::Unconfigure(bool atDeviceLevel)
597 {
598 	// If we only want to destroy our open pipes before setting
599 	// another configuration unconfigure will be called with
600 	// atDevice = false. otherwise we explicitly want to unconfigure
601 	// the device and have to send it the corresponding request.
602 	if (atDeviceLevel && fAvailable) {
603 		status_t result = fDefaultPipe->SendRequest(
604 			USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD,
605 			USB_REQUEST_SET_CONFIGURATION, 0, 0, 0, NULL, 0, NULL);
606 		if (result < B_OK)
607 			return result;
608 
609 		snooze(USB_DELAY_SET_CONFIGURATION);
610 	}
611 
612 	if (!fCurrentConfiguration)
613 		return B_OK;
614 
615 	ClearEndpoints(-1);
616 	fCurrentConfiguration = NULL;
617 	return B_OK;
618 }
619 
620 
621 void
622 Device::ClearEndpoints(int32 interfaceIndex)
623 {
624 	if (fCurrentConfiguration == NULL
625 		|| fCurrentConfiguration->interface == NULL)
626 		return;
627 
628 	for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
629 		if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
630 			continue;
631 
632 		usb_interface_info* interfaceInfo
633 			= fCurrentConfiguration->interface[j].active;
634 		if (interfaceInfo == NULL || interfaceInfo->endpoint == NULL)
635 			continue;
636 
637 		for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
638 			usb_endpoint_info* endpoint = &interfaceInfo->endpoint[i];
639 			Pipe* pipe = (Pipe*)GetStack()->GetObject(endpoint->handle);
640 			if (pipe != NULL)
641 				pipe->SetBusy(false);
642 			delete pipe;
643 			endpoint->handle = 0;
644 		}
645 	}
646 }
647 
648 
649 status_t
650 Device::SetAltInterface(const usb_interface_info* interface)
651 {
652 	uint8 interfaceNumber = interface->descr->interface_number;
653 	// Tell the device to set the alternate settings
654 	status_t result = fDefaultPipe->SendRequest(
655 		USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_STANDARD,
656 		USB_REQUEST_SET_INTERFACE,
657 		interface->descr->alternate_setting, interfaceNumber, 0, NULL, 0, NULL);
658 	if (result < B_OK)
659 		return result;
660 
661 	// Clear the no longer active endpoints
662 	ClearEndpoints(interfaceNumber);
663 
664 	// Update the active pointer of the interface list
665 	usb_interface_list* interfaceList
666 		= &fCurrentConfiguration->interface[interfaceNumber];
667 	interfaceList->active
668 		= &interfaceList->alt[interface->descr->alternate_setting];
669 
670 	// Initialize the new endpoints
671 	InitEndpoints(interfaceNumber);
672 	return result;
673 }
674 
675 
676 const usb_device_descriptor*
677 Device::DeviceDescriptor() const
678 {
679 	return &fDeviceDescriptor;
680 }
681 
682 
683 status_t
684 Device::ReportDevice(usb_support_descriptor* supportDescriptors,
685 	uint32 supportDescriptorCount, const usb_notify_hooks* hooks,
686 	usb_driver_cookie** cookies, bool added, bool recursive)
687 {
688 	TRACE("reporting device\n");
689 	bool supported = false;
690 	if (supportDescriptorCount == 0 || supportDescriptors == NULL)
691 		supported = true;
692 
693 	for (uint32 i = 0; !supported && i < supportDescriptorCount; i++) {
694 		if ((supportDescriptors[i].vendor != 0
695 				&& fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor)
696 			|| (supportDescriptors[i].product != 0
697 				&& fDeviceDescriptor.product_id
698 					!= supportDescriptors[i].product))
699 			continue;
700 
701 		if ((supportDescriptors[i].dev_class == 0
702 				|| fDeviceDescriptor.device_class
703 					== supportDescriptors[i].dev_class)
704 			&& (supportDescriptors[i].dev_subclass == 0
705 				|| fDeviceDescriptor.device_subclass
706 					== supportDescriptors[i].dev_subclass)
707 			&& (supportDescriptors[i].dev_protocol == 0
708 				|| fDeviceDescriptor.device_protocol
709 					== supportDescriptors[i].dev_protocol)) {
710 			supported = true;
711 		}
712 
713 		// we have to check all interfaces for matching class/subclass/protocol
714 		for (uint32 j = 0;
715 				!supported && j < fDeviceDescriptor.num_configurations; j++) {
716 			for (uint32 k = 0;
717 					!supported && k < fConfigurations[j].interface_count; k++) {
718 				for (uint32 l = 0; !supported
719 					&& l < fConfigurations[j].interface[k].alt_count; l++) {
720 					usb_interface_descriptor* descriptor
721 						= fConfigurations[j].interface[k].alt[l].descr;
722 					if ((supportDescriptors[i].dev_class == 0
723 							|| descriptor->interface_class
724 								== supportDescriptors[i].dev_class)
725 						&& (supportDescriptors[i].dev_subclass == 0
726 							|| descriptor->interface_subclass
727 								== supportDescriptors[i].dev_subclass)
728 						&& (supportDescriptors[i].dev_protocol == 0
729 							|| descriptor->interface_protocol
730 								== supportDescriptors[i].dev_protocol)) {
731 						supported = true;
732 					}
733 				}
734 			}
735 		}
736 	}
737 
738 	if (!supported)
739 		return B_UNSUPPORTED;
740 
741 	if ((added && hooks->device_added == NULL)
742 		|| (!added && hooks->device_removed == NULL)) {
743 		// hooks are not installed, but report success to indicate that
744 		// the driver supports the device
745 		return B_OK;
746 	}
747 
748 	usb_id id = USBID();
749 	if (added) {
750 		usb_driver_cookie* cookie = new(std::nothrow) usb_driver_cookie;
751 		if (hooks->device_added(id, &cookie->cookie) >= B_OK) {
752 			cookie->device = id;
753 			cookie->link = *cookies;
754 			*cookies = cookie;
755 		} else
756 			delete cookie;
757 	} else {
758 		usb_driver_cookie** pointer = cookies;
759 		usb_driver_cookie* cookie = *cookies;
760 		while (cookie != NULL) {
761 			if (cookie->device == id)
762 				break;
763 			pointer = &cookie->link;
764 			cookie = cookie->link;
765 		}
766 
767 		if (cookie == NULL) {
768 			// the device is supported, but there is no cookie. this most
769 			// probably means that the device_added hook above failed.
770 			return B_OK;
771 		}
772 
773 		hooks->device_removed(cookie->cookie);
774 		*pointer = cookie->link;
775 		delete cookie;
776 	}
777 
778 	return B_OK;
779 }
780 
781 
782 status_t
783 Device::BuildDeviceName(char* string, uint32* index, size_t bufferSize,
784 	Device* device)
785 {
786 	if (!Parent() || (Parent()->Type() & USB_OBJECT_HUB) == 0)
787 		return B_ERROR;
788 
789 	((Hub*)Parent())->BuildDeviceName(string, index, bufferSize, this);
790 	return B_OK;
791 }
792 
793 
794 status_t
795 Device::SetFeature(uint16 selector)
796 {
797 	if (!fAvailable)
798 		return B_ERROR;
799 
800 	TRACE("set feature %u\n", selector);
801 	return fDefaultPipe->SendRequest(
802 		USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
803 		USB_REQUEST_SET_FEATURE, selector, 0, 0, NULL, 0, NULL);
804 }
805 
806 
807 status_t
808 Device::ClearFeature(uint16 selector)
809 {
810 	if (!fAvailable)
811 		return B_ERROR;
812 
813 	TRACE("clear feature %u\n", selector);
814 	return fDefaultPipe->SendRequest(
815 		USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
816 		USB_REQUEST_CLEAR_FEATURE, selector, 0, 0, NULL, 0, NULL);
817 }
818 
819 
820 status_t
821 Device::GetStatus(uint16* status)
822 {
823 	if (!fAvailable)
824 		return B_ERROR;
825 
826 	TRACE("get status\n");
827 	return fDefaultPipe->SendRequest(
828 		USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_IN,
829 		USB_REQUEST_GET_STATUS, 0, 0, 2, (void*)status, 2, NULL);
830 }
831