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 ¤tInterface->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