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