vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / bus_managers / usb / Device.cpp
blobf15b52216d7cb2b8632d55d2cce45905a01f2fe1
1 /*
2 * Copyright 2003-2014, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Michael Lotz <mmlr@mlotz.ch>
7 * Niels S. Reedijk
8 */
11 #include "usb_private.h"
14 Device::Device(Object* parent, int8 hubAddress, uint8 hubPort,
15 usb_device_descriptor& desc, int8 deviceAddress, usb_speed speed,
16 bool isRootHub, void* controllerCookie)
18 Object(parent),
19 fDeviceDescriptor(desc),
20 fInitOK(false),
21 fAvailable(true),
22 fIsRootHub(isRootHub),
23 fConfigurations(NULL),
24 fCurrentConfiguration(NULL),
25 fSpeed(speed),
26 fDeviceAddress(deviceAddress),
27 fHubAddress(hubAddress),
28 fHubPort(hubPort),
29 fControllerCookie(controllerCookie)
31 TRACE("creating device\n");
33 fDefaultPipe = new(std::nothrow) ControlPipe(this);
34 if (fDefaultPipe == NULL) {
35 TRACE_ERROR("could not allocate default pipe\n");
36 return;
39 fDefaultPipe->InitCommon(fDeviceAddress, 0, fSpeed, Pipe::Default,
40 fDeviceDescriptor.max_packet_size_0, 0, fHubAddress, fHubPort);
42 // Get the device descriptor
43 // We already have a part of it, but we want it all
44 size_t actualLength;
45 status_t status = GetDescriptor(USB_DESCRIPTOR_DEVICE, 0, 0,
46 (void*)&fDeviceDescriptor, sizeof(fDeviceDescriptor), &actualLength);
48 if (status < B_OK || actualLength != sizeof(fDeviceDescriptor)) {
49 TRACE_ERROR("error while getting the device descriptor\n");
50 return;
53 TRACE("full device descriptor for device %d:\n", fDeviceAddress);
54 TRACE("\tlength:..............%d\n", fDeviceDescriptor.length);
55 TRACE("\tdescriptor_type:.....0x%04x\n", fDeviceDescriptor.descriptor_type);
56 TRACE("\tusb_version:.........0x%04x\n", fDeviceDescriptor.usb_version);
57 TRACE("\tdevice_class:........0x%02x\n", fDeviceDescriptor.device_class);
58 TRACE("\tdevice_subclass:.....0x%02x\n", fDeviceDescriptor.device_subclass);
59 TRACE("\tdevice_protocol:.....0x%02x\n", fDeviceDescriptor.device_protocol);
60 TRACE("\tmax_packet_size_0:...%d\n", fDeviceDescriptor.max_packet_size_0);
61 TRACE("\tvendor_id:...........0x%04x\n", fDeviceDescriptor.vendor_id);
62 TRACE("\tproduct_id:..........0x%04x\n", fDeviceDescriptor.product_id);
63 TRACE("\tdevice_version:......0x%04x\n", fDeviceDescriptor.device_version);
64 TRACE("\tmanufacturer:........0x%02x\n", fDeviceDescriptor.manufacturer);
65 TRACE("\tproduct:.............0x%02x\n", fDeviceDescriptor.product);
66 TRACE("\tserial_number:.......0x%02x\n", fDeviceDescriptor.serial_number);
67 TRACE("\tnum_configurations:..%d\n", fDeviceDescriptor.num_configurations);
69 // Get the configurations
70 fConfigurations = (usb_configuration_info*)malloc(
71 fDeviceDescriptor.num_configurations * sizeof(usb_configuration_info));
72 if (fConfigurations == NULL) {
73 TRACE_ERROR("out of memory during config creations!\n");
74 return;
77 memset(fConfigurations, 0, fDeviceDescriptor.num_configurations
78 * sizeof(usb_configuration_info));
79 for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
80 usb_configuration_descriptor configDescriptor;
81 status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
82 (void*)&configDescriptor, sizeof(usb_configuration_descriptor),
83 &actualLength);
85 if (status < B_OK
86 || actualLength != sizeof(usb_configuration_descriptor)) {
87 TRACE_ERROR("error fetching configuration %" B_PRId32 "\n", i);
88 return;
91 TRACE("configuration %" B_PRId32 "\n", i);
92 TRACE("\tlength:..............%d\n", configDescriptor.length);
93 TRACE("\tdescriptor_type:.....0x%02x\n",
94 configDescriptor.descriptor_type);
95 TRACE("\ttotal_length:........%d\n", configDescriptor.total_length);
96 TRACE("\tnumber_interfaces:...%d\n",
97 configDescriptor.number_interfaces);
98 TRACE("\tconfiguration_value:.0x%02x\n",
99 configDescriptor.configuration_value);
100 TRACE("\tconfiguration:.......0x%02x\n",
101 configDescriptor.configuration);
102 TRACE("\tattributes:..........0x%02x\n", configDescriptor.attributes);
103 TRACE("\tmax_power:...........%d\n", configDescriptor.max_power);
105 uint8* configData = (uint8*)malloc(configDescriptor.total_length);
106 if (configData == NULL) {
107 TRACE_ERROR("out of memory when reading config\n");
108 return;
111 status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
112 (void*)configData, configDescriptor.total_length, &actualLength);
114 if (status < B_OK || actualLength != configDescriptor.total_length) {
115 TRACE_ERROR("error fetching full configuration"
116 " descriptor %" B_PRId32 " got %" B_PRIuSIZE " expected %"
117 B_PRIu16 "\n", i, actualLength, configDescriptor.total_length);
118 free(configData);
119 return;
122 usb_configuration_descriptor* configuration
123 = (usb_configuration_descriptor*)configData;
124 fConfigurations[i].descr = configuration;
125 fConfigurations[i].interface_count = configuration->number_interfaces;
126 fConfigurations[i].interface = (usb_interface_list*)malloc(
127 configuration->number_interfaces * sizeof(usb_interface_list));
128 if (fConfigurations[i].interface == NULL) {
129 TRACE_ERROR("out of memory when creating interfaces\n");
130 return;
133 memset(fConfigurations[i].interface, 0,
134 configuration->number_interfaces * sizeof(usb_interface_list));
136 usb_interface_info* currentInterface = NULL;
137 uint32 descriptorStart = sizeof(usb_configuration_descriptor);
138 while (descriptorStart < actualLength) {
139 switch (configData[descriptorStart + 1]) {
140 case USB_DESCRIPTOR_INTERFACE:
142 TRACE("got interface descriptor\n");
143 usb_interface_descriptor* interfaceDescriptor
144 = (usb_interface_descriptor*)&configData[
145 descriptorStart];
146 TRACE("\tlength:.............%d\n",
147 interfaceDescriptor->length);
148 TRACE("\tdescriptor_type:....0x%02x\n",
149 interfaceDescriptor->descriptor_type);
150 TRACE("\tinterface_number:...%d\n",
151 interfaceDescriptor->interface_number);
152 TRACE("\talternate_setting:..%d\n",
153 interfaceDescriptor->alternate_setting);
154 TRACE("\tnum_endpoints:......%d\n",
155 interfaceDescriptor->num_endpoints);
156 TRACE("\tinterface_class:....0x%02x\n",
157 interfaceDescriptor->interface_class);
158 TRACE("\tinterface_subclass:.0x%02x\n",
159 interfaceDescriptor->interface_subclass);
160 TRACE("\tinterface_protocol:.0x%02x\n",
161 interfaceDescriptor->interface_protocol);
162 TRACE("\tinterface:..........%d\n",
163 interfaceDescriptor->interface);
165 if (interfaceDescriptor->interface_number
166 >= fConfigurations[i].interface_count) {
167 interfaceDescriptor->interface_number
168 = fConfigurations[i].interface_count - 1;
169 TRACE_ERROR("Corrected invalid interface_number!\n");
172 usb_interface_list* interfaceList = &fConfigurations[i]
173 .interface[interfaceDescriptor->interface_number];
175 // Allocate this alternate
176 interfaceList->alt_count++;
177 usb_interface_info* newAlternates
178 = (usb_interface_info*)realloc(interfaceList->alt,
179 interfaceList->alt_count * sizeof(usb_interface_info));
180 if (newAlternates == NULL) {
181 TRACE_ERROR("out of memory allocating"
182 " alternate interface\n");
183 interfaceList->alt_count--;
184 return;
187 interfaceList->alt = newAlternates;
189 // Set active interface always to the first one
190 interfaceList->active = interfaceList->alt;
192 // Setup this alternate
193 usb_interface_info* interfaceInfo
194 = &interfaceList->alt[interfaceList->alt_count - 1];
195 interfaceInfo->descr = interfaceDescriptor;
196 interfaceInfo->endpoint_count = 0;
197 interfaceInfo->endpoint = NULL;
198 interfaceInfo->generic_count = 0;
199 interfaceInfo->generic = NULL;
201 Interface* interface = new(std::nothrow) Interface(this,
202 interfaceDescriptor->interface_number);
203 if (interface == NULL) {
204 TRACE_ERROR("failed to allocate"
205 " interface object\n");
206 return;
209 interfaceInfo->handle = interface->USBID();
210 currentInterface = interfaceInfo;
211 break;
214 case USB_DESCRIPTOR_ENDPOINT:
216 TRACE("got endpoint descriptor\n");
217 usb_endpoint_descriptor* endpointDescriptor
218 = (usb_endpoint_descriptor*)&configData[descriptorStart];
219 TRACE("\tlength:.............%d\n",
220 endpointDescriptor->length);
221 TRACE("\tdescriptor_type:....0x%02x\n",
222 endpointDescriptor->descriptor_type);
223 TRACE("\tendpoint_address:...0x%02x\n",
224 endpointDescriptor->endpoint_address);
225 TRACE("\tattributes:.........0x%02x\n",
226 endpointDescriptor->attributes);
227 TRACE("\tmax_packet_size:....%d\n",
228 endpointDescriptor->max_packet_size);
229 TRACE("\tinterval:...........%d\n",
230 endpointDescriptor->interval);
232 if (currentInterface == NULL)
233 break;
235 // Allocate this endpoint
236 currentInterface->endpoint_count++;
237 usb_endpoint_info* newEndpoints = (usb_endpoint_info*)
238 realloc(currentInterface->endpoint,
239 currentInterface->endpoint_count
240 * sizeof(usb_endpoint_info));
241 if (newEndpoints == NULL) {
242 TRACE_ERROR("out of memory allocating new endpoint\n");
243 currentInterface->endpoint_count--;
244 return;
247 currentInterface->endpoint = newEndpoints;
249 // Setup this endpoint
250 usb_endpoint_info* endpointInfo = &currentInterface
251 ->endpoint[currentInterface->endpoint_count - 1];
252 endpointInfo->descr = endpointDescriptor;
253 endpointInfo->handle = 0;
254 break;
257 default:
258 TRACE("got generic descriptor\n");
259 usb_generic_descriptor* genericDescriptor
260 = (usb_generic_descriptor*)&configData[descriptorStart];
261 TRACE("\tlength:.............%d\n",
262 genericDescriptor->length);
263 TRACE("\tdescriptor_type:....0x%02x\n",
264 genericDescriptor->descriptor_type);
266 if (currentInterface == NULL)
267 break;
269 // Allocate this descriptor
270 currentInterface->generic_count++;
271 usb_descriptor** newGenerics = (usb_descriptor**)realloc(
272 currentInterface->generic,
273 currentInterface->generic_count
274 * sizeof(usb_descriptor*));
275 if (newGenerics == NULL) {
276 TRACE_ERROR("out of memory allocating"
277 " generic descriptor\n");
278 currentInterface->generic_count--;
279 return;
282 currentInterface->generic = newGenerics;
284 // Add this descriptor
285 currentInterface->generic[
286 currentInterface->generic_count - 1]
287 = (usb_descriptor*)genericDescriptor;
288 break;
291 descriptorStart += configData[descriptorStart];
295 // Set default configuration
296 TRACE("setting default configuration\n");
297 if (SetConfigurationAt(0) != B_OK) {
298 TRACE_ERROR("failed to set default configuration\n");
299 return;
302 fInitOK = true;
306 Device::~Device()
308 delete fDefaultPipe;
310 if (fConfigurations == NULL) {
311 // we didn't get far in device setup, so everything below is unneeded
312 return;
315 // Destroy open endpoints. Do not send a device request to unconfigure
316 // though, since we may be deleted because the device was unplugged
317 // already.
318 Unconfigure(false);
320 // Free all allocated resources
321 for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
322 usb_configuration_info* configuration = &fConfigurations[i];
323 if (configuration == NULL)
324 continue;
326 free(configuration->descr);
327 if (configuration->interface == NULL)
328 continue;
330 for (size_t j = 0; j < configuration->interface_count; j++) {
331 usb_interface_list* interfaceList = &configuration->interface[j];
332 if (interfaceList->alt == NULL)
333 continue;
335 for (size_t k = 0; k < interfaceList->alt_count; k++) {
336 usb_interface_info* interface = &interfaceList->alt[k];
337 delete (Interface*)GetStack()->GetObject(interface->handle);
338 free(interface->endpoint);
339 free(interface->generic);
342 free(interfaceList->alt);
345 free(configuration->interface);
348 free(fConfigurations);
352 status_t
353 Device::InitCheck()
355 if (fInitOK)
356 return B_OK;
358 return B_ERROR;
362 status_t
363 Device::Changed(change_item** changeList, bool added)
365 fAvailable = added;
366 change_item* changeItem = new(std::nothrow) change_item;
367 if (changeItem == NULL)
368 return B_NO_MEMORY;
370 changeItem->added = added;
371 changeItem->device = this;
372 changeItem->link = *changeList;
373 *changeList = changeItem;
374 return B_OK;
378 status_t
379 Device::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
380 void* data, size_t dataLength, size_t* actualLength)
382 if (!fAvailable)
383 return B_ERROR;
385 return fDefaultPipe->SendRequest(
386 USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD,
387 USB_REQUEST_GET_DESCRIPTOR, (descriptorType << 8) | index,
388 languageID, dataLength, data, dataLength, actualLength);
392 const usb_configuration_info*
393 Device::Configuration() const
395 return fCurrentConfiguration;
399 const usb_configuration_info*
400 Device::ConfigurationAt(uint8 index) const
402 if (index >= fDeviceDescriptor.num_configurations)
403 return NULL;
405 return &fConfigurations[index];
409 status_t
410 Device::SetConfiguration(const usb_configuration_info* configuration)
412 if (!configuration)
413 return Unconfigure(true);
415 for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
416 if (configuration->descr->configuration_value
417 == fConfigurations[i].descr->configuration_value)
418 return SetConfigurationAt(i);
421 return B_BAD_VALUE;
425 status_t
426 Device::SetConfigurationAt(uint8 index)
428 if (!fAvailable)
429 return B_ERROR;
430 if (index >= fDeviceDescriptor.num_configurations)
431 return B_BAD_VALUE;
432 if (&fConfigurations[index] == fCurrentConfiguration)
433 return B_OK;
435 // Destroy our open endpoints
436 Unconfigure(false);
438 // Tell the device to set the configuration
439 status_t result = fDefaultPipe->SendRequest(
440 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD,
441 USB_REQUEST_SET_CONFIGURATION,
442 fConfigurations[index].descr->configuration_value, 0, 0, NULL, 0, NULL);
443 if (result < B_OK)
444 return result;
446 // Set current configuration
447 fCurrentConfiguration = &fConfigurations[index];
449 // Initialize all the endpoints that are now active
450 InitEndpoints(-1);
452 // Wait some for the configuration being finished
453 if (!fIsRootHub)
454 snooze(USB_DELAY_SET_CONFIGURATION);
455 return B_OK;
459 void
460 Device::InitEndpoints(int32 interfaceIndex)
462 for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
463 if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
464 continue;
466 usb_interface_info* interfaceInfo
467 = fCurrentConfiguration->interface[j].active;
468 if (interfaceInfo == NULL)
469 continue;
471 for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
472 usb_endpoint_info* endpoint = &interfaceInfo->endpoint[i];
473 Pipe* pipe = NULL;
475 Pipe::pipeDirection direction = Pipe::Out;
476 if ((endpoint->descr->endpoint_address & 0x80) != 0)
477 direction = Pipe::In;
479 switch (endpoint->descr->attributes & 0x03) {
480 case USB_ENDPOINT_ATTR_CONTROL: // Control Endpoint
481 pipe = new(std::nothrow) ControlPipe(this);
482 direction = Pipe::Default;
483 break;
485 case USB_ENDPOINT_ATTR_ISOCHRONOUS: // Isochronous Endpoint
486 pipe = new(std::nothrow) IsochronousPipe(this);
487 break;
489 case USB_ENDPOINT_ATTR_BULK: // Bulk Endpoint
490 pipe = new(std::nothrow) BulkPipe(this);
491 break;
493 case USB_ENDPOINT_ATTR_INTERRUPT: // Interrupt Endpoint
494 pipe = new(std::nothrow) InterruptPipe(this);
495 break;
498 if (pipe == NULL) {
499 TRACE_ERROR("failed to allocate pipe\n");
500 endpoint->handle = 0;
501 continue;
504 pipe->InitCommon(fDeviceAddress,
505 endpoint->descr->endpoint_address & 0x0f,
506 fSpeed, direction, endpoint->descr->max_packet_size,
507 endpoint->descr->interval, fHubAddress, fHubPort);
508 endpoint->handle = pipe->USBID();
514 status_t
515 Device::Unconfigure(bool atDeviceLevel)
517 // If we only want to destroy our open pipes before setting
518 // another configuration unconfigure will be called with
519 // atDevice = false. otherwise we explicitly want to unconfigure
520 // the device and have to send it the corresponding request.
521 if (atDeviceLevel && fAvailable) {
522 status_t result = fDefaultPipe->SendRequest(
523 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD,
524 USB_REQUEST_SET_CONFIGURATION, 0, 0, 0, NULL, 0, NULL);
525 if (result < B_OK)
526 return result;
528 snooze(USB_DELAY_SET_CONFIGURATION);
531 if (!fCurrentConfiguration)
532 return B_OK;
534 ClearEndpoints(-1);
535 fCurrentConfiguration = NULL;
536 return B_OK;
540 void
541 Device::ClearEndpoints(int32 interfaceIndex)
543 if (fCurrentConfiguration == NULL
544 || fCurrentConfiguration->interface == NULL)
545 return;
547 for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
548 if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
549 continue;
551 usb_interface_info* interfaceInfo
552 = fCurrentConfiguration->interface[j].active;
553 if (interfaceInfo == NULL || interfaceInfo->endpoint == NULL)
554 continue;
556 for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
557 usb_endpoint_info* endpoint = &interfaceInfo->endpoint[i];
558 delete (Pipe*)GetStack()->GetObject(endpoint->handle);
559 endpoint->handle = 0;
565 status_t
566 Device::SetAltInterface(const usb_interface_info* interface)
568 uint8 interfaceNumber = interface->descr->interface_number;
569 // Tell the device to set the alternate settings
570 status_t result = fDefaultPipe->SendRequest(
571 USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_STANDARD,
572 USB_REQUEST_SET_INTERFACE,
573 interface->descr->alternate_setting, interfaceNumber, 0, NULL, 0, NULL);
574 if (result < B_OK)
575 return result;
577 // Clear the no longer active endpoints
578 ClearEndpoints(interfaceNumber);
580 // Update the active pointer of the interface list
581 usb_interface_list* interfaceList
582 = &fCurrentConfiguration->interface[interfaceNumber];
583 interfaceList->active
584 = &interfaceList->alt[interface->descr->alternate_setting];
586 // Initialize the new endpoints
587 InitEndpoints(interfaceNumber);
588 return result;
592 const usb_device_descriptor*
593 Device::DeviceDescriptor() const
595 return &fDeviceDescriptor;
599 status_t
600 Device::ReportDevice(usb_support_descriptor* supportDescriptors,
601 uint32 supportDescriptorCount, const usb_notify_hooks* hooks,
602 usb_driver_cookie** cookies, bool added, bool recursive)
604 TRACE("reporting device\n");
605 bool supported = false;
606 if (supportDescriptorCount == 0 || supportDescriptors == NULL)
607 supported = true;
609 for (uint32 i = 0; !supported && i < supportDescriptorCount; i++) {
610 if ((supportDescriptors[i].vendor != 0
611 && fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor)
612 || (supportDescriptors[i].product != 0
613 && fDeviceDescriptor.product_id
614 != supportDescriptors[i].product))
615 continue;
617 if ((supportDescriptors[i].dev_class == 0
618 || fDeviceDescriptor.device_class
619 == supportDescriptors[i].dev_class)
620 && (supportDescriptors[i].dev_subclass == 0
621 || fDeviceDescriptor.device_subclass
622 == supportDescriptors[i].dev_subclass)
623 && (supportDescriptors[i].dev_protocol == 0
624 || fDeviceDescriptor.device_protocol
625 == supportDescriptors[i].dev_protocol)) {
626 supported = true;
629 // we have to check all interfaces for matching class/subclass/protocol
630 for (uint32 j = 0;
631 !supported && j < fDeviceDescriptor.num_configurations; j++) {
632 for (uint32 k = 0;
633 !supported && k < fConfigurations[j].interface_count; k++) {
634 for (uint32 l = 0; !supported
635 && l < fConfigurations[j].interface[k].alt_count; l++) {
636 usb_interface_descriptor* descriptor
637 = fConfigurations[j].interface[k].alt[l].descr;
638 if ((supportDescriptors[i].dev_class == 0
639 || descriptor->interface_class
640 == supportDescriptors[i].dev_class)
641 && (supportDescriptors[i].dev_subclass == 0
642 || descriptor->interface_subclass
643 == supportDescriptors[i].dev_subclass)
644 && (supportDescriptors[i].dev_protocol == 0
645 || descriptor->interface_protocol
646 == supportDescriptors[i].dev_protocol)) {
647 supported = true;
654 if (!supported)
655 return B_UNSUPPORTED;
657 if ((added && hooks->device_added == NULL)
658 || (!added && hooks->device_removed == NULL)) {
659 // hooks are not installed, but report success to indicate that
660 // the driver supports the device
661 return B_OK;
664 usb_id id = USBID();
665 if (added) {
666 usb_driver_cookie* cookie = new(std::nothrow) usb_driver_cookie;
667 if (hooks->device_added(id, &cookie->cookie) >= B_OK) {
668 cookie->device = id;
669 cookie->link = *cookies;
670 *cookies = cookie;
671 } else
672 delete cookie;
673 } else {
674 usb_driver_cookie** pointer = cookies;
675 usb_driver_cookie* cookie = *cookies;
676 while (cookie != NULL) {
677 if (cookie->device == id)
678 break;
679 pointer = &cookie->link;
680 cookie = cookie->link;
683 if (cookie == NULL) {
684 // the device is supported, but there is no cookie. this most
685 // probably means that the device_added hook above failed.
686 return B_OK;
689 hooks->device_removed(cookie->cookie);
690 *pointer = cookie->link;
691 delete cookie;
694 return B_OK;
698 status_t
699 Device::BuildDeviceName(char* string, uint32* index, size_t bufferSize,
700 Device* device)
702 if (!Parent() || (Parent()->Type() & USB_OBJECT_HUB) == 0)
703 return B_ERROR;
705 ((Hub*)Parent())->BuildDeviceName(string, index, bufferSize, this);
706 return B_OK;
710 status_t
711 Device::SetFeature(uint16 selector)
713 if (!fAvailable)
714 return B_ERROR;
716 TRACE("set feature %u\n", selector);
717 return fDefaultPipe->SendRequest(
718 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
719 USB_REQUEST_SET_FEATURE, selector, 0, 0, NULL, 0, NULL);
723 status_t
724 Device::ClearFeature(uint16 selector)
726 if (!fAvailable)
727 return B_ERROR;
729 TRACE("clear feature %u\n", selector);
730 return fDefaultPipe->SendRequest(
731 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
732 USB_REQUEST_CLEAR_FEATURE, selector, 0, 0, NULL, 0, NULL);
736 status_t
737 Device::GetStatus(uint16* status)
739 if (!fAvailable)
740 return B_ERROR;
742 TRACE("get status\n");
743 return fDefaultPipe->SendRequest(
744 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_IN,
745 USB_REQUEST_GET_STATUS, 0, 0, 2, (void*)status, 2, NULL);