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