Fix #8729.
[haiku.git] / src / add-ons / kernel / bus_managers / usb / Device.cpp
blobe16995231b0b20640dd8e9c52b42fdface5d6152
1 /*
2 * Copyright 2003-2006, 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 */
10 #include "usb_private.h"
13 Device::Device(Object *parent, int8 hubAddress, uint8 hubPort,
14 usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed,
15 bool isRootHub, void *controllerCookie)
16 : Object(parent),
17 fDeviceDescriptor(desc),
18 fInitOK(false),
19 fAvailable(true),
20 fIsRootHub(isRootHub),
21 fConfigurations(NULL),
22 fCurrentConfiguration(NULL),
23 fSpeed(speed),
24 fDeviceAddress(deviceAddress),
25 fHubAddress(hubAddress),
26 fHubPort(hubPort),
27 fControllerCookie(controllerCookie)
29 TRACE("creating device\n");
31 fDefaultPipe = new(std::nothrow) ControlPipe(this);
32 if (!fDefaultPipe) {
33 TRACE_ERROR("could not allocate default pipe\n");
34 return;
37 fDefaultPipe->InitCommon(fDeviceAddress, 0, fSpeed, Pipe::Default,
38 fDeviceDescriptor.max_packet_size_0, 0, fHubAddress, fHubPort);
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);
46 if (status < B_OK || actualLength != sizeof(fDeviceDescriptor)) {
47 TRACE_ERROR("error while getting the device descriptor\n");
48 return;
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);
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("out of memory during config creations!\n");
72 return;
75 memset(fConfigurations, 0, fDeviceDescriptor.num_configurations
76 * sizeof(usb_configuration_info));
77 for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
78 usb_configuration_descriptor configDescriptor;
79 status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
80 (void *)&configDescriptor, sizeof(usb_configuration_descriptor),
81 &actualLength);
83 if (status < B_OK || actualLength != sizeof(usb_configuration_descriptor)) {
84 TRACE_ERROR("error fetching configuration %ld\n", i);
85 return;
88 TRACE("configuration %ld\n", 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);
98 uint8 *configData = (uint8 *)malloc(configDescriptor.total_length);
99 if (configData == NULL) {
100 TRACE_ERROR("out of memory when reading config\n");
101 return;
104 status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0,
105 (void *)configData, configDescriptor.total_length, &actualLength);
107 if (status < B_OK || actualLength != configDescriptor.total_length) {
108 TRACE_ERROR("error fetching full configuration"
109 " descriptor %ld got %lu expected %u\n", i,
110 actualLength, configDescriptor.total_length);
111 free(configData);
112 return;
115 usb_configuration_descriptor *configuration
116 = (usb_configuration_descriptor *)configData;
117 fConfigurations[i].descr = configuration;
118 fConfigurations[i].interface_count = configuration->number_interfaces;
119 fConfigurations[i].interface = (usb_interface_list *)malloc(
120 configuration->number_interfaces * sizeof(usb_interface_list));
121 if (fConfigurations[i].interface == NULL) {
122 TRACE_ERROR("out of memory when creating interfaces\n");
123 return;
126 memset(fConfigurations[i].interface, 0,
127 configuration->number_interfaces * sizeof(usb_interface_list));
129 usb_interface_info *currentInterface = NULL;
130 uint32 descriptorStart = sizeof(usb_configuration_descriptor);
131 while (descriptorStart < actualLength) {
132 switch (configData[descriptorStart + 1]) {
133 case USB_DESCRIPTOR_INTERFACE: {
134 TRACE("got interface descriptor\n");
135 usb_interface_descriptor *interfaceDescriptor
136 = (usb_interface_descriptor *)&configData[descriptorStart];
137 TRACE("\tlength:.............%d\n", interfaceDescriptor->length);
138 TRACE("\tdescriptor_type:....0x%02x\n", interfaceDescriptor->descriptor_type);
139 TRACE("\tinterface_number:...%d\n", interfaceDescriptor->interface_number);
140 TRACE("\talternate_setting:..%d\n", interfaceDescriptor->alternate_setting);
141 TRACE("\tnum_endpoints:......%d\n", interfaceDescriptor->num_endpoints);
142 TRACE("\tinterface_class:....0x%02x\n", interfaceDescriptor->interface_class);
143 TRACE("\tinterface_subclass:.0x%02x\n", interfaceDescriptor->interface_subclass);
144 TRACE("\tinterface_protocol:.0x%02x\n", interfaceDescriptor->interface_protocol);
145 TRACE("\tinterface:..........%d\n", interfaceDescriptor->interface);
147 if (interfaceDescriptor->interface_number >= fConfigurations[i].interface_count) {
148 interfaceDescriptor->interface_number = fConfigurations[i].interface_count - 1;
149 TRACE_ERROR("Corrected invalid interface_number!\n");
152 usb_interface_list *interfaceList
153 = &fConfigurations[i].interface[interfaceDescriptor->interface_number];
155 /* Allocate this alternate */
156 interfaceList->alt_count++;
157 usb_interface_info *newAlternates
158 = (usb_interface_info *)realloc(interfaceList->alt,
159 interfaceList->alt_count * sizeof(usb_interface_info));
160 if (newAlternates == NULL) {
161 TRACE_ERROR("out of memory allocating"
162 " alternate interface\n");
163 interfaceList->alt_count--;
164 return;
167 interfaceList->alt = newAlternates;
169 /* Set active interface always to the first one */
170 interfaceList->active = interfaceList->alt;
172 /* Setup this alternate */
173 usb_interface_info *interfaceInfo =
174 &interfaceList->alt[interfaceList->alt_count - 1];
175 interfaceInfo->descr = interfaceDescriptor;
176 interfaceInfo->endpoint_count = 0;
177 interfaceInfo->endpoint = NULL;
178 interfaceInfo->generic_count = 0;
179 interfaceInfo->generic = NULL;
181 Interface *interface = new(std::nothrow) Interface(this,
182 interfaceDescriptor->interface_number);
183 if (interface == NULL) {
184 TRACE_ERROR("failed to allocate"
185 " interface object\n");
186 return;
189 interfaceInfo->handle = interface->USBID();
190 currentInterface = interfaceInfo;
191 break;
194 case USB_DESCRIPTOR_ENDPOINT: {
195 TRACE("got endpoint descriptor\n");
196 usb_endpoint_descriptor *endpointDescriptor
197 = (usb_endpoint_descriptor *)&configData[descriptorStart];
198 TRACE("\tlength:.............%d\n", endpointDescriptor->length);
199 TRACE("\tdescriptor_type:....0x%02x\n", endpointDescriptor->descriptor_type);
200 TRACE("\tendpoint_address:...0x%02x\n", endpointDescriptor->endpoint_address);
201 TRACE("\tattributes:.........0x%02x\n", endpointDescriptor->attributes);
202 TRACE("\tmax_packet_size:....%d\n", endpointDescriptor->max_packet_size);
203 TRACE("\tinterval:...........%d\n", endpointDescriptor->interval);
205 if (!currentInterface)
206 break;
208 /* allocate this endpoint */
209 currentInterface->endpoint_count++;
210 usb_endpoint_info *newEndpoints
211 = (usb_endpoint_info *)realloc(
212 currentInterface->endpoint,
213 currentInterface->endpoint_count
214 * sizeof(usb_endpoint_info));
215 if (newEndpoints == NULL) {
216 TRACE_ERROR("out of memory allocating"
217 " new endpoint\n");
218 currentInterface->endpoint_count--;
219 return;
222 currentInterface->endpoint = newEndpoints;
224 /* setup this endpoint */
225 usb_endpoint_info *endpointInfo =
226 &currentInterface->endpoint[currentInterface->endpoint_count - 1];
227 endpointInfo->descr = endpointDescriptor;
228 endpointInfo->handle = 0;
229 break;
232 default:
233 TRACE("got generic descriptor\n");
234 usb_generic_descriptor *genericDescriptor
235 = (usb_generic_descriptor *)&configData[descriptorStart];
236 TRACE("\tlength:.............%d\n", genericDescriptor->length);
237 TRACE("\tdescriptor_type:....0x%02x\n", genericDescriptor->descriptor_type);
239 if (!currentInterface)
240 break;
242 /* allocate this descriptor */
243 currentInterface->generic_count++;
244 usb_descriptor **newGenerics = (usb_descriptor **)realloc(
245 currentInterface->generic,
246 currentInterface->generic_count
247 * sizeof(usb_descriptor *));
248 if (newGenerics == NULL) {
249 TRACE_ERROR("out of memory allocating"
250 " generic descriptor\n");
251 currentInterface->generic_count--;
252 return;
255 currentInterface->generic = newGenerics;
257 /* add this descriptor */
258 currentInterface->generic[currentInterface->generic_count - 1] =
259 (usb_descriptor *)genericDescriptor;
260 break;
263 descriptorStart += configData[descriptorStart];
267 // Set default configuration
268 TRACE("setting default configuration\n");
269 if (SetConfigurationAt(0) < B_OK) {
270 TRACE_ERROR("failed to set default configuration\n");
271 return;
274 fInitOK = true;
278 Device::~Device()
280 delete fDefaultPipe;
282 if (fConfigurations == NULL) {
283 // we didn't get far in device setup, so everything below is unneeded
284 return;
287 // Destroy open endpoints. Do not send a device request to unconfigure
288 // though, since we may be deleted because the device was unplugged
289 // already.
290 Unconfigure(false);
292 // Free all allocated resources
293 for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
294 usb_configuration_info *configuration = &fConfigurations[i];
295 if (configuration == NULL)
296 continue;
298 free(configuration->descr);
299 if (configuration->interface == NULL)
300 continue;
302 for (size_t j = 0; j < configuration->interface_count; j++) {
303 usb_interface_list *interfaceList = &configuration->interface[j];
304 if (interfaceList->alt == NULL)
305 continue;
307 for (size_t k = 0; k < interfaceList->alt_count; k++) {
308 usb_interface_info *interface = &interfaceList->alt[k];
309 delete (Interface *)GetStack()->GetObject(interface->handle);
310 free(interface->endpoint);
311 free(interface->generic);
314 free(interfaceList->alt);
317 free(configuration->interface);
320 free(fConfigurations);
324 status_t
325 Device::InitCheck()
327 if (fInitOK)
328 return B_OK;
330 return B_ERROR;
334 status_t
335 Device::Changed(change_item **changeList, bool added)
337 fAvailable = added;
338 change_item *changeItem = new(std::nothrow) change_item;
339 if (!changeItem)
340 return B_NO_MEMORY;
342 changeItem->added = added;
343 changeItem->device = this;
344 changeItem->link = *changeList;
345 *changeList = changeItem;
346 return B_OK;
350 status_t
351 Device::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID,
352 void *data, size_t dataLength, size_t *actualLength)
354 if (!fAvailable)
355 return B_ERROR;
357 return fDefaultPipe->SendRequest(
358 USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type
359 USB_REQUEST_GET_DESCRIPTOR, // request
360 (descriptorType << 8) | index, // value
361 languageID, // index
362 dataLength, // length
363 data, // buffer
364 dataLength, // buffer length
365 actualLength); // actual length
369 const usb_configuration_info *
370 Device::Configuration() const
372 return fCurrentConfiguration;
376 const usb_configuration_info *
377 Device::ConfigurationAt(uint8 index) const
379 if (index >= fDeviceDescriptor.num_configurations)
380 return NULL;
382 return &fConfigurations[index];
386 status_t
387 Device::SetConfiguration(const usb_configuration_info *configuration)
389 if (!configuration)
390 return Unconfigure(true);
392 for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) {
393 if (configuration->descr->configuration_value
394 == fConfigurations[i].descr->configuration_value)
395 return SetConfigurationAt(i);
398 return B_BAD_VALUE;
402 status_t
403 Device::SetConfigurationAt(uint8 index)
405 if (!fAvailable)
406 return B_ERROR;
407 if (index >= fDeviceDescriptor.num_configurations)
408 return B_BAD_VALUE;
409 if (&fConfigurations[index] == fCurrentConfiguration)
410 return B_OK;
412 // Destroy our open endpoints
413 Unconfigure(false);
415 // Tell the device to set the configuration
416 status_t result = fDefaultPipe->SendRequest(
417 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type
418 USB_REQUEST_SET_CONFIGURATION, // request
419 fConfigurations[index].descr->configuration_value, // value
420 0, // index
421 0, // length
422 NULL, // buffer
423 0, // buffer length
424 NULL); // actual length
426 if (result < B_OK)
427 return result;
429 // Set current configuration
430 fCurrentConfiguration = &fConfigurations[index];
432 // Initialize all the endpoints that are now active
433 InitEndpoints(-1);
435 // Wait some for the configuration being finished
436 if (!fIsRootHub)
437 snooze(USB_DELAY_SET_CONFIGURATION);
438 return B_OK;
442 void
443 Device::InitEndpoints(int32 interfaceIndex)
445 for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
446 if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
447 continue;
449 usb_interface_info *interfaceInfo = fCurrentConfiguration->interface[j].active;
450 for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
451 usb_endpoint_info *endpoint = &interfaceInfo->endpoint[i];
452 Pipe *pipe = NULL;
454 Pipe::pipeDirection direction = Pipe::Out;
455 if (endpoint->descr->endpoint_address & 0x80)
456 direction = Pipe::In;
458 switch (endpoint->descr->attributes & 0x03) {
459 case USB_ENDPOINT_ATTR_CONTROL: /* Control Endpoint */
460 pipe = new(std::nothrow) ControlPipe(this);
461 direction = Pipe::Default;
462 break;
464 case USB_ENDPOINT_ATTR_ISOCHRONOUS: /* Isochronous Endpoint */
465 pipe = new(std::nothrow) IsochronousPipe(this);
466 break;
468 case USB_ENDPOINT_ATTR_BULK: /* Bulk Endpoint */
469 pipe = new(std::nothrow) BulkPipe(this);
470 break;
472 case USB_ENDPOINT_ATTR_INTERRUPT: /* Interrupt Endpoint */
473 pipe = new(std::nothrow) InterruptPipe(this);
474 break;
477 if (pipe == NULL) {
478 TRACE_ERROR("failed to allocate pipe\n");
479 endpoint->handle = 0;
480 continue;
483 pipe->InitCommon(fDeviceAddress,
484 endpoint->descr->endpoint_address & 0x0f,
485 fSpeed, direction, endpoint->descr->max_packet_size,
486 endpoint->descr->interval, fHubAddress, fHubPort);
487 endpoint->handle = pipe->USBID();
493 status_t
494 Device::Unconfigure(bool atDeviceLevel)
496 // if we only want to destroy our open pipes before setting
497 // another configuration unconfigure will be called with
498 // atDevice = false. otherwise we explicitly want to unconfigure
499 // the device and have to send it the corresponding request.
500 if (atDeviceLevel && fAvailable) {
501 status_t result = fDefaultPipe->SendRequest(
502 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type
503 USB_REQUEST_SET_CONFIGURATION, // request
504 0, // value
505 0, // index
506 0, // length
507 NULL, // buffer
508 0, // buffer length
509 NULL); // actual length
511 if (result < B_OK)
512 return result;
514 snooze(USB_DELAY_SET_CONFIGURATION);
517 if (!fCurrentConfiguration)
518 return B_OK;
520 ClearEndpoints(-1);
521 fCurrentConfiguration = NULL;
522 return B_OK;
526 void
527 Device::ClearEndpoints(int32 interfaceIndex)
529 if (fCurrentConfiguration == NULL || fCurrentConfiguration->interface == NULL)
530 return;
532 for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) {
533 if (interfaceIndex >= 0 && j != (size_t)interfaceIndex)
534 continue;
536 usb_interface_info *interfaceInfo = fCurrentConfiguration->interface[j].active;
537 if (interfaceInfo == NULL || interfaceInfo->endpoint == NULL)
538 continue;
540 for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) {
541 usb_endpoint_info *endpoint = &interfaceInfo->endpoint[i];
542 delete (Pipe *)GetStack()->GetObject(endpoint->handle);
543 endpoint->handle = 0;
549 status_t
550 Device::SetAltInterface(const usb_interface_info *interface)
552 uint8 interfaceNumber = interface->descr->interface_number;
553 // Tell the device to set the alternate settings
554 status_t result = fDefaultPipe->SendRequest(
555 USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_STANDARD, // type
556 USB_REQUEST_SET_INTERFACE, // request
557 interface->descr->alternate_setting, // value
558 interfaceNumber, // index
559 0, // length
560 NULL, // buffer
561 0, // buffer length
562 NULL);
564 if (result < B_OK)
565 return result;
567 // Clear the no longer active endpoints
568 ClearEndpoints(interfaceNumber);
570 // Update the active pointer of the interface list
571 usb_interface_list *interfaceList
572 = &fCurrentConfiguration->interface[interfaceNumber];
573 interfaceList->active
574 = &interfaceList->alt[interface->descr->alternate_setting];
576 // Initialize the new endpoints
577 InitEndpoints(interfaceNumber);
578 return result;
581 const usb_device_descriptor *
582 Device::DeviceDescriptor() const
584 return &fDeviceDescriptor;
588 status_t
589 Device::ReportDevice(usb_support_descriptor *supportDescriptors,
590 uint32 supportDescriptorCount, const usb_notify_hooks *hooks,
591 usb_driver_cookie **cookies, bool added, bool recursive)
593 TRACE("reporting device\n");
594 bool supported = false;
595 if (supportDescriptorCount == 0 || supportDescriptors == NULL)
596 supported = true;
598 for (uint32 i = 0; !supported && i < supportDescriptorCount; i++) {
599 if ((supportDescriptors[i].vendor != 0
600 && fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor)
601 || (supportDescriptors[i].product != 0
602 && fDeviceDescriptor.product_id != supportDescriptors[i].product))
603 continue;
605 if ((supportDescriptors[i].dev_class == 0
606 || fDeviceDescriptor.device_class == supportDescriptors[i].dev_class)
607 && (supportDescriptors[i].dev_subclass == 0
608 || fDeviceDescriptor.device_subclass == supportDescriptors[i].dev_subclass)
609 && (supportDescriptors[i].dev_protocol == 0
610 || fDeviceDescriptor.device_protocol == supportDescriptors[i].dev_protocol)) {
611 supported = true;
614 // we have to check all interfaces for matching class/subclass/protocol
615 for (uint32 j = 0; !supported && j < fDeviceDescriptor.num_configurations; j++) {
616 for (uint32 k = 0; !supported && k < fConfigurations[j].interface_count; k++) {
617 for (uint32 l = 0; !supported && l < fConfigurations[j].interface[k].alt_count; l++) {
618 usb_interface_descriptor *descriptor = fConfigurations[j].interface[k].alt[l].descr;
619 if ((supportDescriptors[i].dev_class == 0
620 || descriptor->interface_class == supportDescriptors[i].dev_class)
621 && (supportDescriptors[i].dev_subclass == 0
622 || descriptor->interface_subclass == supportDescriptors[i].dev_subclass)
623 && (supportDescriptors[i].dev_protocol == 0
624 || descriptor->interface_protocol == supportDescriptors[i].dev_protocol)) {
625 supported = true;
632 if (!supported)
633 return B_UNSUPPORTED;
635 if ((added && hooks->device_added == NULL)
636 || (!added && hooks->device_removed == NULL)) {
637 // hooks are not installed, but report success to indicate that
638 // the driver supports the device
639 return B_OK;
642 usb_id id = USBID();
643 if (added) {
644 usb_driver_cookie *cookie = new(std::nothrow) usb_driver_cookie;
645 if (hooks->device_added(id, &cookie->cookie) >= B_OK) {
646 cookie->device = id;
647 cookie->link = *cookies;
648 *cookies = cookie;
649 } else
650 delete cookie;
651 } else {
652 usb_driver_cookie **pointer = cookies;
653 usb_driver_cookie *cookie = *cookies;
654 while (cookie) {
655 if (cookie->device == id)
656 break;
657 pointer = &cookie->link;
658 cookie = cookie->link;
661 if (!cookie) {
662 // the device is supported, but there is no cookie. this most
663 // probably means that the device_added hook above failed.
664 return B_OK;
667 hooks->device_removed(cookie->cookie);
668 *pointer = cookie->link;
669 delete cookie;
672 return B_OK;
676 status_t
677 Device::BuildDeviceName(char *string, uint32 *index, size_t bufferSize,
678 Device *device)
680 if (!Parent() || (Parent()->Type() & USB_OBJECT_HUB) == 0)
681 return B_ERROR;
683 ((Hub *)Parent())->BuildDeviceName(string, index, bufferSize, this);
684 return B_OK;
688 status_t
689 Device::SetFeature(uint16 selector)
691 if (!fAvailable)
692 return B_ERROR;
694 TRACE("set feature %u\n", selector);
695 return fDefaultPipe->SendRequest(
696 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
697 USB_REQUEST_SET_FEATURE,
698 selector,
701 NULL,
703 NULL);
707 status_t
708 Device::ClearFeature(uint16 selector)
710 if (!fAvailable)
711 return B_ERROR;
713 TRACE("clear feature %u\n", selector);
714 return fDefaultPipe->SendRequest(
715 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT,
716 USB_REQUEST_CLEAR_FEATURE,
717 selector,
720 NULL,
722 NULL);
726 status_t
727 Device::GetStatus(uint16 *status)
729 if (!fAvailable)
730 return B_ERROR;
732 TRACE("get status\n");
733 return fDefaultPipe->SendRequest(
734 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_IN,
735 USB_REQUEST_GET_STATUS,
739 (void *)status,
741 NULL);