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 hubAddress, uint8 hubPort, 14 usb_device_descriptor &desc, int8 deviceAddress, usb_speed speed, 15 bool isRootHub) 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 { 28 TRACE("creating device\n"); 29 30 fDefaultPipe = new(std::nothrow) ControlPipe(this); 31 if (!fDefaultPipe) { 32 TRACE_ERROR("could not allocate default pipe\n"); 33 return; 34 } 35 36 fDefaultPipe->InitCommon(fDeviceAddress, 0, fSpeed, Pipe::Default, 37 fDeviceDescriptor.max_packet_size_0, 0, fHubAddress, 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("error while getting the device descriptor\n"); 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("out of memory during config creations!\n"); 71 return; 72 } 73 74 memset(fConfigurations, 0, fDeviceDescriptor.num_configurations 75 * sizeof(usb_configuration_info)); 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("error fetching configuration %ld\n", i); 84 return; 85 } 86 87 TRACE("configuration %ld\n", 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 if (configData == NULL) { 99 TRACE_ERROR("out of memory when reading config\n"); 100 return; 101 } 102 103 status = GetDescriptor(USB_DESCRIPTOR_CONFIGURATION, i, 0, 104 (void *)configData, configDescriptor.total_length, &actualLength); 105 106 if (status < B_OK || actualLength != configDescriptor.total_length) { 107 TRACE_ERROR("error fetching full configuration" 108 " descriptor %ld got %lu expected %u\n", i, 109 actualLength, configDescriptor.total_length); 110 free(configData); 111 return; 112 } 113 114 usb_configuration_descriptor *configuration 115 = (usb_configuration_descriptor *)configData; 116 fConfigurations[i].descr = configuration; 117 fConfigurations[i].interface_count = configuration->number_interfaces; 118 fConfigurations[i].interface = (usb_interface_list *)malloc( 119 configuration->number_interfaces * sizeof(usb_interface_list)); 120 if (fConfigurations[i].interface == NULL) { 121 TRACE_ERROR("out of memory when creating interfaces\n"); 122 return; 123 } 124 125 memset(fConfigurations[i].interface, 0, 126 configuration->number_interfaces * sizeof(usb_interface_list)); 127 128 usb_interface_info *currentInterface = NULL; 129 uint32 descriptorStart = sizeof(usb_configuration_descriptor); 130 while (descriptorStart < actualLength) { 131 switch (configData[descriptorStart + 1]) { 132 case USB_DESCRIPTOR_INTERFACE: { 133 TRACE("got interface descriptor\n"); 134 usb_interface_descriptor *interfaceDescriptor 135 = (usb_interface_descriptor *)&configData[descriptorStart]; 136 TRACE("\tlength:.............%d\n", interfaceDescriptor->length); 137 TRACE("\tdescriptor_type:....0x%02x\n", interfaceDescriptor->descriptor_type); 138 TRACE("\tinterface_number:...%d\n", interfaceDescriptor->interface_number); 139 TRACE("\talternate_setting:..%d\n", interfaceDescriptor->alternate_setting); 140 TRACE("\tnum_endpoints:......%d\n", interfaceDescriptor->num_endpoints); 141 TRACE("\tinterface_class:....0x%02x\n", interfaceDescriptor->interface_class); 142 TRACE("\tinterface_subclass:.0x%02x\n", interfaceDescriptor->interface_subclass); 143 TRACE("\tinterface_protocol:.0x%02x\n", interfaceDescriptor->interface_protocol); 144 TRACE("\tinterface:..........%d\n", interfaceDescriptor->interface); 145 146 usb_interface_list *interfaceList 147 = &fConfigurations[i].interface[interfaceDescriptor->interface_number]; 148 149 /* Allocate this alternate */ 150 interfaceList->alt_count++; 151 usb_interface_info *newAlternates 152 = (usb_interface_info *)realloc(interfaceList->alt, 153 interfaceList->alt_count * sizeof(usb_interface_info)); 154 if (newAlternates == NULL) { 155 TRACE_ERROR("out of memory allocating" 156 " alternate interface\n"); 157 interfaceList->alt_count--; 158 return; 159 } 160 161 interfaceList->alt = newAlternates; 162 163 /* Set active interface always to the first one */ 164 interfaceList->active = interfaceList->alt; 165 166 /* Setup this alternate */ 167 usb_interface_info *interfaceInfo = 168 &interfaceList->alt[interfaceList->alt_count - 1]; 169 interfaceInfo->descr = interfaceDescriptor; 170 interfaceInfo->endpoint_count = 0; 171 interfaceInfo->endpoint = NULL; 172 interfaceInfo->generic_count = 0; 173 interfaceInfo->generic = NULL; 174 175 Interface *interface = new(std::nothrow) Interface(this, 176 interfaceDescriptor->interface_number); 177 if (interface == NULL) { 178 TRACE_ERROR("failed to allocate" 179 " interface object\n"); 180 return; 181 } 182 183 interfaceInfo->handle = interface->USBID(); 184 currentInterface = interfaceInfo; 185 break; 186 } 187 188 case USB_DESCRIPTOR_ENDPOINT: { 189 TRACE("got endpoint descriptor\n"); 190 usb_endpoint_descriptor *endpointDescriptor 191 = (usb_endpoint_descriptor *)&configData[descriptorStart]; 192 TRACE("\tlength:.............%d\n", endpointDescriptor->length); 193 TRACE("\tdescriptor_type:....0x%02x\n", endpointDescriptor->descriptor_type); 194 TRACE("\tendpoint_address:...0x%02x\n", endpointDescriptor->endpoint_address); 195 TRACE("\tattributes:.........0x%02x\n", endpointDescriptor->attributes); 196 TRACE("\tmax_packet_size:....%d\n", endpointDescriptor->max_packet_size); 197 TRACE("\tinterval:...........%d\n", endpointDescriptor->interval); 198 199 if (!currentInterface) 200 break; 201 202 /* allocate this endpoint */ 203 currentInterface->endpoint_count++; 204 usb_endpoint_info *newEndpoints 205 = (usb_endpoint_info *)realloc( 206 currentInterface->endpoint, 207 currentInterface->endpoint_count 208 * sizeof(usb_endpoint_info)); 209 if (newEndpoints == NULL) { 210 TRACE_ERROR("out of memory allocating" 211 " new endpoint\n"); 212 currentInterface->endpoint_count--; 213 return; 214 } 215 216 currentInterface->endpoint = newEndpoints; 217 218 /* setup this endpoint */ 219 usb_endpoint_info *endpointInfo = 220 ¤tInterface->endpoint[currentInterface->endpoint_count - 1]; 221 endpointInfo->descr = endpointDescriptor; 222 endpointInfo->handle = 0; 223 break; 224 } 225 226 default: 227 TRACE("got generic descriptor\n"); 228 usb_generic_descriptor *genericDescriptor 229 = (usb_generic_descriptor *)&configData[descriptorStart]; 230 TRACE("\tlength:.............%d\n", genericDescriptor->length); 231 TRACE("\tdescriptor_type:....0x%02x\n", genericDescriptor->descriptor_type); 232 233 if (!currentInterface) 234 break; 235 236 /* allocate this descriptor */ 237 currentInterface->generic_count++; 238 usb_descriptor **newGenerics = (usb_descriptor **)realloc( 239 currentInterface->generic, 240 currentInterface->generic_count 241 * sizeof(usb_descriptor *)); 242 if (newGenerics == NULL) { 243 TRACE_ERROR("out of memory allocating" 244 " generic descriptor\n"); 245 currentInterface->generic_count--; 246 return; 247 } 248 249 currentInterface->generic = newGenerics; 250 251 /* add this descriptor */ 252 currentInterface->generic[currentInterface->generic_count - 1] = 253 (usb_descriptor *)genericDescriptor; 254 break; 255 } 256 257 descriptorStart += configData[descriptorStart]; 258 } 259 } 260 261 // Set default configuration 262 TRACE("setting default configuration\n"); 263 if (SetConfigurationAt(0) < B_OK) { 264 TRACE_ERROR("failed to set default configuration\n"); 265 return; 266 } 267 268 fInitOK = true; 269 } 270 271 272 Device::~Device() 273 { 274 // Destroy open endpoints. Do not send a device request to unconfigure 275 // though, since we may be deleted because the device was unplugged 276 // already. 277 Unconfigure(false); 278 279 // Free all allocated resources 280 for (int32 i = 0; i < fDeviceDescriptor.num_configurations; i++) { 281 usb_configuration_info *configuration = &fConfigurations[i]; 282 if (configuration == NULL) 283 continue; 284 285 free(configuration->descr); 286 if (configuration->interface == NULL) 287 continue; 288 289 for (size_t j = 0; j < configuration->interface_count; j++) { 290 usb_interface_list *interfaceList = &configuration->interface[j]; 291 if (interfaceList->alt == NULL) 292 continue; 293 294 for (size_t k = 0; k < interfaceList->alt_count; k++) { 295 usb_interface_info *interface = &interfaceList->alt[k]; 296 delete (Interface *)GetStack()->GetObject(interface->handle); 297 free(interface->endpoint); 298 free(interface->generic); 299 } 300 301 free(interfaceList->alt); 302 } 303 304 free(configuration->interface); 305 } 306 307 free(fConfigurations); 308 delete fDefaultPipe; 309 } 310 311 312 status_t 313 Device::InitCheck() 314 { 315 if (fInitOK) 316 return B_OK; 317 318 return B_ERROR; 319 } 320 321 322 status_t 323 Device::Changed(change_item **changeList, bool added) 324 { 325 fAvailable = added; 326 change_item *changeItem = new(std::nothrow) change_item; 327 if (!changeItem) 328 return B_NO_MEMORY; 329 330 changeItem->added = added; 331 changeItem->device = this; 332 changeItem->link = *changeList; 333 *changeList = changeItem; 334 return B_OK; 335 } 336 337 338 status_t 339 Device::GetDescriptor(uint8 descriptorType, uint8 index, uint16 languageID, 340 void *data, size_t dataLength, size_t *actualLength) 341 { 342 if (!fAvailable) 343 return B_ERROR; 344 345 return fDefaultPipe->SendRequest( 346 USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type 347 USB_REQUEST_GET_DESCRIPTOR, // request 348 (descriptorType << 8) | index, // value 349 languageID, // index 350 dataLength, // length 351 data, // buffer 352 dataLength, // buffer length 353 actualLength); // actual length 354 } 355 356 357 const usb_configuration_info * 358 Device::Configuration() const 359 { 360 return fCurrentConfiguration; 361 } 362 363 364 const usb_configuration_info * 365 Device::ConfigurationAt(uint8 index) const 366 { 367 if (index >= fDeviceDescriptor.num_configurations) 368 return NULL; 369 370 return &fConfigurations[index]; 371 } 372 373 374 status_t 375 Device::SetConfiguration(const usb_configuration_info *configuration) 376 { 377 if (!configuration) 378 return Unconfigure(true); 379 380 for (uint8 i = 0; i < fDeviceDescriptor.num_configurations; i++) { 381 if (configuration->descr->configuration_value 382 == fConfigurations[i].descr->configuration_value) 383 return SetConfigurationAt(i); 384 } 385 386 return B_BAD_VALUE; 387 } 388 389 390 status_t 391 Device::SetConfigurationAt(uint8 index) 392 { 393 if (!fAvailable) 394 return B_ERROR; 395 if (index >= fDeviceDescriptor.num_configurations) 396 return B_BAD_VALUE; 397 if (&fConfigurations[index] == fCurrentConfiguration) 398 return B_OK; 399 400 // Destroy our open endpoints 401 Unconfigure(false); 402 403 // Tell the device to set the configuration 404 status_t result = fDefaultPipe->SendRequest( 405 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type 406 USB_REQUEST_SET_CONFIGURATION, // request 407 fConfigurations[index].descr->configuration_value, // value 408 0, // index 409 0, // length 410 NULL, // buffer 411 0, // buffer length 412 NULL); // actual length 413 414 if (result < B_OK) 415 return result; 416 417 // Set current configuration 418 fCurrentConfiguration = &fConfigurations[index]; 419 420 // Initialize all the endpoints that are now active 421 InitEndpoints(-1); 422 423 // Wait some for the configuration being finished 424 if (!fIsRootHub) 425 snooze(USB_DELAY_SET_CONFIGURATION); 426 return B_OK; 427 } 428 429 430 void 431 Device::InitEndpoints(int32 interfaceIndex) 432 { 433 for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) { 434 if (interfaceIndex >= 0 && j != (size_t)interfaceIndex) 435 continue; 436 437 usb_interface_info *interfaceInfo = fCurrentConfiguration->interface[j].active; 438 for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) { 439 usb_endpoint_info *endpoint = &interfaceInfo->endpoint[i]; 440 Pipe *pipe = NULL; 441 442 Pipe::pipeDirection direction = Pipe::Out; 443 if (endpoint->descr->endpoint_address & 0x80) 444 direction = Pipe::In; 445 446 switch (endpoint->descr->attributes & 0x03) { 447 case 0x00: /* Control Endpoint */ 448 pipe = new(std::nothrow) ControlPipe(this); 449 direction = Pipe::Default; 450 break; 451 452 case 0x01: /* Isochronous Endpoint */ 453 pipe = new(std::nothrow) IsochronousPipe(this); 454 break; 455 456 case 0x02: /* Bulk Endpoint */ 457 pipe = new(std::nothrow) BulkPipe(this); 458 break; 459 460 case 0x03: /* Interrupt Endpoint */ 461 pipe = new(std::nothrow) InterruptPipe(this); 462 break; 463 } 464 465 if (pipe == NULL) { 466 TRACE_ERROR("failed to allocate pipe\n"); 467 endpoint->handle = 0; 468 continue; 469 } 470 471 pipe->InitCommon(fDeviceAddress, 472 endpoint->descr->endpoint_address & 0x0f, 473 fSpeed, direction, endpoint->descr->max_packet_size, 474 endpoint->descr->interval, fHubAddress, fHubPort); 475 endpoint->handle = pipe->USBID(); 476 } 477 } 478 } 479 480 481 status_t 482 Device::Unconfigure(bool atDeviceLevel) 483 { 484 // if we only want to destroy our open pipes before setting 485 // another configuration unconfigure will be called with 486 // atDevice = false. otherwise we explicitly want to unconfigure 487 // the device and have to send it the corresponding request. 488 if (atDeviceLevel && fAvailable) { 489 status_t result = fDefaultPipe->SendRequest( 490 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type 491 USB_REQUEST_SET_CONFIGURATION, // request 492 0, // value 493 0, // index 494 0, // length 495 NULL, // buffer 496 0, // buffer length 497 NULL); // actual length 498 499 if (result < B_OK) 500 return result; 501 502 snooze(USB_DELAY_SET_CONFIGURATION); 503 } 504 505 if (!fCurrentConfiguration) 506 return B_OK; 507 508 ClearEndpoints(-1); 509 fCurrentConfiguration = NULL; 510 return B_OK; 511 } 512 513 514 void 515 Device::ClearEndpoints(int32 interfaceIndex) 516 { 517 if (fCurrentConfiguration == NULL || fCurrentConfiguration->interface == NULL) 518 return; 519 520 for (size_t j = 0; j < fCurrentConfiguration->interface_count; j++) { 521 if (interfaceIndex >= 0 && j != (size_t)interfaceIndex) 522 continue; 523 524 usb_interface_info *interfaceInfo = fCurrentConfiguration->interface[j].active; 525 if (interfaceInfo == NULL || interfaceInfo->endpoint == NULL) 526 continue; 527 528 for (size_t i = 0; i < interfaceInfo->endpoint_count; i++) { 529 usb_endpoint_info *endpoint = &interfaceInfo->endpoint[i]; 530 delete (Pipe *)GetStack()->GetObject(endpoint->handle); 531 endpoint->handle = 0; 532 } 533 } 534 } 535 536 537 status_t 538 Device::SetAltInterface(const usb_interface_info *interface) 539 { 540 uint8 interfaceNumber = interface->descr->interface_number; 541 // Tell the device to set the alternate settings 542 status_t result = fDefaultPipe->SendRequest( 543 USB_REQTYPE_INTERFACE_OUT | USB_REQTYPE_STANDARD, // type 544 USB_REQUEST_SET_INTERFACE, // request 545 interface->descr->alternate_setting, // value 546 interfaceNumber, // index 547 0, // length 548 NULL, // buffer 549 0, // buffer length 550 NULL); 551 552 if (result < B_OK) 553 return result; 554 555 // Clear the no longer active endpoints 556 ClearEndpoints(interfaceNumber); 557 558 // Update the active pointer of the interface list 559 usb_interface_list *interfaceList 560 = &fCurrentConfiguration->interface[interfaceNumber]; 561 interfaceList->active 562 = &interfaceList->alt[interface->descr->alternate_setting]; 563 564 // Initialize the new endpoints 565 InitEndpoints(interfaceNumber); 566 return result; 567 } 568 569 const usb_device_descriptor * 570 Device::DeviceDescriptor() const 571 { 572 return &fDeviceDescriptor; 573 } 574 575 576 status_t 577 Device::ReportDevice(usb_support_descriptor *supportDescriptors, 578 uint32 supportDescriptorCount, const usb_notify_hooks *hooks, 579 usb_driver_cookie **cookies, bool added, bool recursive) 580 { 581 TRACE("reporting device\n"); 582 bool supported = false; 583 if (supportDescriptorCount == 0 || supportDescriptors == NULL) 584 supported = true; 585 586 for (uint32 i = 0; !supported && i < supportDescriptorCount; i++) { 587 if ((supportDescriptors[i].vendor != 0 588 && fDeviceDescriptor.vendor_id != supportDescriptors[i].vendor) 589 || (supportDescriptors[i].product != 0 590 && fDeviceDescriptor.product_id != supportDescriptors[i].product)) 591 continue; 592 593 if ((supportDescriptors[i].dev_class == 0 594 || fDeviceDescriptor.device_class == supportDescriptors[i].dev_class) 595 && (supportDescriptors[i].dev_subclass == 0 596 || fDeviceDescriptor.device_subclass == supportDescriptors[i].dev_subclass) 597 && (supportDescriptors[i].dev_protocol == 0 598 || fDeviceDescriptor.device_protocol == supportDescriptors[i].dev_protocol)) { 599 supported = true; 600 } 601 602 // we have to check all interfaces for matching class/subclass/protocol 603 for (uint32 j = 0; !supported && j < fDeviceDescriptor.num_configurations; j++) { 604 for (uint32 k = 0; !supported && k < fConfigurations[j].interface_count; k++) { 605 for (uint32 l = 0; !supported && l < fConfigurations[j].interface[k].alt_count; l++) { 606 usb_interface_descriptor *descriptor = fConfigurations[j].interface[k].alt[l].descr; 607 if ((supportDescriptors[i].dev_class == 0 608 || descriptor->interface_class == supportDescriptors[i].dev_class) 609 && (supportDescriptors[i].dev_subclass == 0 610 || descriptor->interface_subclass == supportDescriptors[i].dev_subclass) 611 && (supportDescriptors[i].dev_protocol == 0 612 || descriptor->interface_protocol == supportDescriptors[i].dev_protocol)) { 613 supported = true; 614 } 615 } 616 } 617 } 618 } 619 620 if (!supported) 621 return B_UNSUPPORTED; 622 623 if ((added && hooks->device_added == NULL) 624 || (!added && hooks->device_removed == NULL)) { 625 // hooks are not installed, but report success to indicate that 626 // the driver supports the device 627 return B_OK; 628 } 629 630 usb_id id = USBID(); 631 if (added) { 632 usb_driver_cookie *cookie = new(std::nothrow) usb_driver_cookie; 633 if (hooks->device_added(id, &cookie->cookie) >= B_OK) { 634 cookie->device = id; 635 cookie->link = *cookies; 636 *cookies = cookie; 637 } else 638 delete cookie; 639 } else { 640 usb_driver_cookie **pointer = cookies; 641 usb_driver_cookie *cookie = *cookies; 642 while (cookie) { 643 if (cookie->device == id) 644 break; 645 pointer = &cookie->link; 646 cookie = cookie->link; 647 } 648 649 if (!cookie) { 650 // the device is supported, but there is no cookie. this most 651 // probably means that the device_added hook above failed. 652 return B_OK; 653 } 654 655 hooks->device_removed(cookie->cookie); 656 *pointer = cookie->link; 657 delete cookie; 658 } 659 660 return B_OK; 661 } 662 663 664 status_t 665 Device::BuildDeviceName(char *string, uint32 *index, size_t bufferSize, 666 Device *device) 667 { 668 if (!Parent() || (Parent()->Type() & USB_OBJECT_HUB) == 0) 669 return B_ERROR; 670 671 ((Hub *)Parent())->BuildDeviceName(string, index, bufferSize, this); 672 return B_OK; 673 } 674 675 676 status_t 677 Device::SetFeature(uint16 selector) 678 { 679 if (!fAvailable) 680 return B_ERROR; 681 682 TRACE("set feature %u\n", selector); 683 return fDefaultPipe->SendRequest( 684 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT, 685 USB_REQUEST_SET_FEATURE, 686 selector, 687 0, 688 0, 689 NULL, 690 0, 691 NULL); 692 } 693 694 695 status_t 696 Device::ClearFeature(uint16 selector) 697 { 698 if (!fAvailable) 699 return B_ERROR; 700 701 TRACE("clear feature %u\n", selector); 702 return fDefaultPipe->SendRequest( 703 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_OUT, 704 USB_REQUEST_CLEAR_FEATURE, 705 selector, 706 0, 707 0, 708 NULL, 709 0, 710 NULL); 711 } 712 713 714 status_t 715 Device::GetStatus(uint16 *status) 716 { 717 if (!fAvailable) 718 return B_ERROR; 719 720 TRACE("get status\n"); 721 return fDefaultPipe->SendRequest( 722 USB_REQTYPE_STANDARD | USB_REQTYPE_DEVICE_IN, 723 USB_REQUEST_GET_STATUS, 724 0, 725 0, 726 2, 727 (void *)status, 728 2, 729 NULL); 730 } 731