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