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