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