2 * Copyright 2003-2014, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Michael Lotz <mmlr@mlotz.ch>
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
)
19 fDeviceDescriptor(desc
),
22 fIsRootHub(isRootHub
),
23 fConfigurations(NULL
),
24 fCurrentConfiguration(NULL
),
26 fDeviceAddress(deviceAddress
),
27 fHubAddress(hubAddress
),
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");
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
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");
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");
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
),
86 || actualLength
!= sizeof(usb_configuration_descriptor
)) {
87 TRACE_ERROR("error fetching configuration %" B_PRId32
"\n", i
);
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");
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
);
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");
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
[
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
--;
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");
209 interfaceInfo
->handle
= interface
->USBID();
210 currentInterface
= interfaceInfo
;
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
)
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
--;
247 currentInterface
->endpoint
= newEndpoints
;
249 // Setup this endpoint
250 usb_endpoint_info
* endpointInfo
= ¤tInterface
251 ->endpoint
[currentInterface
->endpoint_count
- 1];
252 endpointInfo
->descr
= endpointDescriptor
;
253 endpointInfo
->handle
= 0;
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
)
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
--;
282 currentInterface
->generic
= newGenerics
;
284 // Add this descriptor
285 currentInterface
->generic
[
286 currentInterface
->generic_count
- 1]
287 = (usb_descriptor
*)genericDescriptor
;
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");
310 if (fConfigurations
== NULL
) {
311 // we didn't get far in device setup, so everything below is unneeded
315 // Destroy open endpoints. Do not send a device request to unconfigure
316 // though, since we may be deleted because the device was unplugged
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
)
326 free(configuration
->descr
);
327 if (configuration
->interface
== NULL
)
330 for (size_t j
= 0; j
< configuration
->interface_count
; j
++) {
331 usb_interface_list
* interfaceList
= &configuration
->interface
[j
];
332 if (interfaceList
->alt
== NULL
)
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
);
363 Device::Changed(change_item
** changeList
, bool added
)
366 change_item
* changeItem
= new(std::nothrow
) change_item
;
367 if (changeItem
== NULL
)
370 changeItem
->added
= added
;
371 changeItem
->device
= this;
372 changeItem
->link
= *changeList
;
373 *changeList
= changeItem
;
379 Device::GetDescriptor(uint8 descriptorType
, uint8 index
, uint16 languageID
,
380 void* data
, size_t dataLength
, size_t* actualLength
)
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
)
405 return &fConfigurations
[index
];
410 Device::SetConfiguration(const usb_configuration_info
* 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
);
426 Device::SetConfigurationAt(uint8 index
)
430 if (index
>= fDeviceDescriptor
.num_configurations
)
432 if (&fConfigurations
[index
] == fCurrentConfiguration
)
435 // Destroy our open endpoints
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
);
446 // Set current configuration
447 fCurrentConfiguration
= &fConfigurations
[index
];
449 // Initialize all the endpoints that are now active
452 // Wait some for the configuration being finished
454 snooze(USB_DELAY_SET_CONFIGURATION
);
460 Device::InitEndpoints(int32 interfaceIndex
)
462 for (size_t j
= 0; j
< fCurrentConfiguration
->interface_count
; j
++) {
463 if (interfaceIndex
>= 0 && j
!= (size_t)interfaceIndex
)
466 usb_interface_info
* interfaceInfo
467 = fCurrentConfiguration
->interface
[j
].active
;
468 if (interfaceInfo
== NULL
)
471 for (size_t i
= 0; i
< interfaceInfo
->endpoint_count
; i
++) {
472 usb_endpoint_info
* endpoint
= &interfaceInfo
->endpoint
[i
];
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
;
485 case USB_ENDPOINT_ATTR_ISOCHRONOUS
: // Isochronous Endpoint
486 pipe
= new(std::nothrow
) IsochronousPipe(this);
489 case USB_ENDPOINT_ATTR_BULK
: // Bulk Endpoint
490 pipe
= new(std::nothrow
) BulkPipe(this);
493 case USB_ENDPOINT_ATTR_INTERRUPT
: // Interrupt Endpoint
494 pipe
= new(std::nothrow
) InterruptPipe(this);
499 TRACE_ERROR("failed to allocate pipe\n");
500 endpoint
->handle
= 0;
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();
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
);
528 snooze(USB_DELAY_SET_CONFIGURATION
);
531 if (!fCurrentConfiguration
)
535 fCurrentConfiguration
= NULL
;
541 Device::ClearEndpoints(int32 interfaceIndex
)
543 if (fCurrentConfiguration
== NULL
544 || fCurrentConfiguration
->interface
== NULL
)
547 for (size_t j
= 0; j
< fCurrentConfiguration
->interface_count
; j
++) {
548 if (interfaceIndex
>= 0 && j
!= (size_t)interfaceIndex
)
551 usb_interface_info
* interfaceInfo
552 = fCurrentConfiguration
->interface
[j
].active
;
553 if (interfaceInfo
== NULL
|| interfaceInfo
->endpoint
== NULL
)
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;
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
);
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
);
592 const usb_device_descriptor
*
593 Device::DeviceDescriptor() const
595 return &fDeviceDescriptor
;
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
)
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
))
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
)) {
629 // we have to check all interfaces for matching class/subclass/protocol
631 !supported
&& j
< fDeviceDescriptor
.num_configurations
; j
++) {
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
)) {
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
666 usb_driver_cookie
* cookie
= new(std::nothrow
) usb_driver_cookie
;
667 if (hooks
->device_added(id
, &cookie
->cookie
) >= B_OK
) {
669 cookie
->link
= *cookies
;
674 usb_driver_cookie
** pointer
= cookies
;
675 usb_driver_cookie
* cookie
= *cookies
;
676 while (cookie
!= NULL
) {
677 if (cookie
->device
== id
)
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.
689 hooks
->device_removed(cookie
->cookie
);
690 *pointer
= cookie
->link
;
699 Device::BuildDeviceName(char* string
, uint32
* index
, size_t bufferSize
,
702 if (!Parent() || (Parent()->Type() & USB_OBJECT_HUB
) == 0)
705 ((Hub
*)Parent())->BuildDeviceName(string
, index
, bufferSize
, this);
711 Device::SetFeature(uint16 selector
)
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
);
724 Device::ClearFeature(uint16 selector
)
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
);
737 Device::GetStatus(uint16
* status
)
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
);