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