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