1 /* 2 * Copyright 2006-2008, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 9 #include "BeOSCompatibility.h" 10 #include "usb_raw.h" 11 12 #include <KernelExport.h> 13 #include <Drivers.h> 14 #include <lock.h> 15 #include <malloc.h> 16 #include <stdio.h> 17 #include <string.h> 18 19 //#define TRACE_USB_RAW 20 #ifdef TRACE_USB_RAW 21 #define TRACE(x) dprintf x 22 #else 23 #define TRACE(x) /* nothing */ 24 #endif 25 26 #define DRIVER_NAME "usb_raw" 27 #define DEVICE_NAME "bus/usb/raw" 28 29 typedef struct { 30 usb_device device; 31 benaphore lock; 32 uint32 reference_count; 33 34 char name[32]; 35 void *link; 36 37 sem_id notify; 38 status_t status; 39 size_t actual_length; 40 } raw_device; 41 42 int32 api_version = B_CUR_DRIVER_API_VERSION; 43 static usb_module_info *gUSBModule = NULL; 44 static raw_device *gDeviceList = NULL; 45 static uint32 gDeviceCount = 0; 46 static benaphore gDeviceListLock; 47 static char **gDeviceNames = NULL; 48 49 static status_t 50 usb_raw_device_added(usb_device newDevice, void **cookie) 51 { 52 TRACE((DRIVER_NAME": device_added(0x%08lx)\n", newDevice)); 53 raw_device *device = (raw_device *)malloc(sizeof(raw_device)); 54 55 status_t result = benaphore_init(&device->lock, "usb_raw device lock"); 56 if (result < B_OK) { 57 free(device); 58 return result; 59 } 60 61 device->notify = create_sem(0, "usb_raw callback notify"); 62 if (device->notify < B_OK) { 63 benaphore_destroy(&device->lock); 64 free(device); 65 return B_NO_MORE_SEMS; 66 } 67 68 char deviceName[32]; 69 memcpy(deviceName, &newDevice, sizeof(usb_device)); 70 if (gUSBModule->usb_ioctl('DNAM', deviceName, sizeof(deviceName)) >= B_OK) { 71 sprintf(device->name, "bus/usb/%s", deviceName); 72 } else { 73 sprintf(device->name, "bus/usb/%08lx", newDevice); 74 } 75 76 device->device = newDevice; 77 device->reference_count = 0; 78 79 benaphore_lock(&gDeviceListLock); 80 device->link = (void *)gDeviceList; 81 gDeviceList = device; 82 gDeviceCount++; 83 benaphore_unlock(&gDeviceListLock); 84 85 TRACE((DRIVER_NAME": new device: 0x%08lx\n", (uint32)device)); 86 *cookie = (void *)device; 87 return B_OK; 88 } 89 90 91 static status_t 92 usb_raw_device_removed(void *cookie) 93 { 94 TRACE((DRIVER_NAME": device_removed(0x%08lx)\n", (uint32)cookie)); 95 raw_device *device = (raw_device *)cookie; 96 97 benaphore_lock(&gDeviceListLock); 98 if (gDeviceList == device) { 99 gDeviceList = (raw_device *)device->link; 100 } else { 101 raw_device *element = gDeviceList; 102 while (element) { 103 if (element->link == device) { 104 element->link = device->link; 105 break; 106 } 107 108 element = (raw_device *)element->link; 109 } 110 } 111 gDeviceCount--; 112 benaphore_unlock(&gDeviceListLock); 113 114 device->device = 0; 115 if (device->reference_count == 0) { 116 benaphore_lock(&device->lock); 117 benaphore_destroy(&device->lock); 118 delete_sem(device->notify); 119 free(device); 120 } 121 122 return B_OK; 123 } 124 125 126 // 127 //#pragma mark - 128 // 129 130 131 static status_t 132 usb_raw_open(const char *name, uint32 flags, void **cookie) 133 { 134 TRACE((DRIVER_NAME": open()\n")); 135 benaphore_lock(&gDeviceListLock); 136 raw_device *element = gDeviceList; 137 while (element) { 138 if (strcmp(name, element->name) == 0) { 139 element->reference_count++; 140 *cookie = element; 141 benaphore_unlock(&gDeviceListLock); 142 return B_OK; 143 } 144 145 element = (raw_device *)element->link; 146 } 147 148 benaphore_unlock(&gDeviceListLock); 149 return B_NAME_NOT_FOUND; 150 } 151 152 153 static status_t 154 usb_raw_close(void *cookie) 155 { 156 TRACE((DRIVER_NAME": close()\n")); 157 return B_OK; 158 } 159 160 161 static status_t 162 usb_raw_free(void *cookie) 163 { 164 TRACE((DRIVER_NAME": free()\n")); 165 benaphore_lock(&gDeviceListLock); 166 167 raw_device *device = (raw_device *)cookie; 168 device->reference_count--; 169 if (device->device == 0) { 170 benaphore_lock(&device->lock); 171 benaphore_destroy(&device->lock); 172 delete_sem(device->notify); 173 free(device); 174 } 175 176 benaphore_unlock(&gDeviceListLock); 177 return B_OK; 178 } 179 180 181 static void 182 usb_raw_callback(void *cookie, status_t status, void *data, size_t actualLength) 183 { 184 TRACE((DRIVER_NAME": callback()\n")); 185 raw_device *device = (raw_device *)cookie; 186 187 switch (status) { 188 case B_OK: 189 device->status = B_USB_RAW_STATUS_SUCCESS; 190 break; 191 case B_TIMED_OUT: 192 device->status = B_USB_RAW_STATUS_TIMEOUT; 193 break; 194 case B_CANCELED: 195 device->status = B_USB_RAW_STATUS_ABORTED; 196 break; 197 case B_DEV_CRC_ERROR: 198 device->status = B_USB_RAW_STATUS_CRC_ERROR; 199 break; 200 case B_DEV_STALLED: 201 device->status = B_USB_RAW_STATUS_STALLED; 202 break; 203 default: 204 device->status = B_USB_RAW_STATUS_FAILED; 205 break; 206 } 207 208 device->actual_length = actualLength; 209 release_sem(device->notify); 210 } 211 212 213 static status_t 214 usb_raw_ioctl(void *cookie, uint32 op, void *buffer, size_t length) 215 { 216 TRACE((DRIVER_NAME": ioctl\n")); 217 raw_device *device = (raw_device *)cookie; 218 usb_raw_command *command = (usb_raw_command *)buffer; 219 220 if (device->device == 0) 221 return B_DEV_NOT_READY; 222 223 switch (op) { 224 case B_USB_RAW_COMMAND_GET_VERSION: { 225 command->version.status = B_USB_RAW_PROTOCOL_VERSION; 226 return B_OK; 227 } 228 229 case B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR: { 230 const usb_device_descriptor *deviceDescriptor = 231 gUSBModule->get_device_descriptor(device->device); 232 if (!deviceDescriptor) { 233 command->device.status = B_USB_RAW_STATUS_ABORTED; 234 return B_OK; 235 } 236 237 memcpy(command->device.descriptor, deviceDescriptor, 238 sizeof(usb_device_descriptor)); 239 command->device.status = B_USB_RAW_STATUS_SUCCESS; 240 return B_OK; 241 } 242 243 case B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR: { 244 const usb_configuration_info *configurationInfo = 245 gUSBModule->get_nth_configuration(device->device, 246 command->config.config_index); 247 if (!configurationInfo) { 248 command->config.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION; 249 return B_OK; 250 } 251 252 memcpy(command->config.descriptor, configurationInfo->descr, 253 sizeof(usb_configuration_descriptor)); 254 command->config.status = B_USB_RAW_STATUS_SUCCESS; 255 return B_OK; 256 } 257 258 case B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR: { 259 const usb_configuration_info *configurationInfo = 260 gUSBModule->get_nth_configuration(device->device, 261 command->interface.config_index); 262 if (!configurationInfo) { 263 command->interface.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION; 264 return B_OK; 265 } 266 267 if (command->interface.interface_index >= configurationInfo->interface_count) { 268 command->interface.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 269 return B_OK; 270 } 271 272 const usb_interface_info *interfaceInfo = 273 configurationInfo->interface[command->interface.interface_index].active; 274 if (!interfaceInfo) { 275 command->interface.status = B_USB_RAW_STATUS_ABORTED; 276 return B_OK; 277 } 278 279 memcpy(command->interface.descriptor, interfaceInfo->descr, 280 sizeof(usb_interface_descriptor)); 281 command->interface.status = B_USB_RAW_STATUS_SUCCESS; 282 return B_OK; 283 } 284 285 case B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT: { 286 const usb_configuration_info *configurationInfo = 287 gUSBModule->get_nth_configuration(device->device, 288 command->alternate.config_index); 289 if (!configurationInfo) { 290 command->alternate.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION; 291 return B_OK; 292 } 293 294 if (command->alternate.interface_index >= configurationInfo->interface_count) { 295 command->alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 296 return B_OK; 297 } 298 299 *command->alternate.alternate_count 300 = configurationInfo->interface[command->alternate.interface_index].alt_count; 301 command->alternate.status = B_USB_RAW_STATUS_SUCCESS; 302 return B_OK; 303 } 304 305 case B_USB_RAW_COMMAND_GET_ALT_INTERFACE_DESCRIPTOR: { 306 const usb_configuration_info *configurationInfo = 307 gUSBModule->get_nth_configuration(device->device, 308 command->alternate.config_index); 309 if (!configurationInfo) { 310 command->alternate.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION; 311 return B_OK; 312 } 313 314 if (command->alternate.interface_index >= configurationInfo->interface_count) { 315 command->alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 316 return B_OK; 317 } 318 319 const usb_interface_list *interfaceList = 320 &configurationInfo->interface[command->alternate.interface_index]; 321 if (command->alternate.alternate_index >= interfaceList->alt_count) { 322 command->alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 323 return B_OK; 324 } 325 326 memcpy(command->alternate.descriptor, 327 &interfaceList->alt[command->alternate.alternate_index], 328 sizeof(usb_interface_descriptor)); 329 command->alternate.status = B_USB_RAW_STATUS_SUCCESS; 330 return B_OK; 331 } 332 333 case B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR: { 334 const usb_configuration_info *configurationInfo = 335 gUSBModule->get_nth_configuration(device->device, 336 command->endpoint.config_index); 337 if (!configurationInfo) { 338 command->endpoint.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION; 339 return B_OK; 340 } 341 342 if (command->endpoint.interface_index >= configurationInfo->interface_count) { 343 command->endpoint.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 344 return B_OK; 345 } 346 347 const usb_interface_info *interfaceInfo = 348 configurationInfo->interface[command->endpoint.interface_index].active; 349 if (!interfaceInfo) { 350 command->endpoint.status = B_USB_RAW_STATUS_ABORTED; 351 return B_OK; 352 } 353 354 if (command->endpoint.endpoint_index >= interfaceInfo->endpoint_count) { 355 command->endpoint.status = B_USB_RAW_STATUS_INVALID_ENDPOINT; 356 return B_OK; 357 } 358 359 memcpy(command->endpoint.descriptor, 360 interfaceInfo->endpoint[command->endpoint.endpoint_index].descr, 361 sizeof(usb_endpoint_descriptor)); 362 command->endpoint.status = B_USB_RAW_STATUS_SUCCESS; 363 return B_OK; 364 } 365 366 case B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR: { 367 const usb_configuration_info *configurationInfo = 368 gUSBModule->get_nth_configuration(device->device, 369 command->generic.config_index); 370 if (!configurationInfo) { 371 command->generic.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION; 372 return B_OK; 373 } 374 375 if (command->generic.interface_index >= configurationInfo->interface_count) { 376 command->generic.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 377 return B_OK; 378 } 379 380 const usb_interface_info *interfaceInfo = 381 configurationInfo->interface[command->generic.interface_index].active; 382 if (!interfaceInfo) { 383 command->generic.status = B_USB_RAW_STATUS_ABORTED; 384 return B_OK; 385 } 386 387 if (command->generic.generic_index >= interfaceInfo->generic_count) { 388 // ToDo: add B_USB_RAW_STATUS_INVALID_GENERIC 389 command->generic.status = B_USB_RAW_STATUS_INVALID_ENDPOINT; 390 return B_OK; 391 } 392 393 usb_descriptor *descriptor = interfaceInfo->generic[command->generic.generic_index]; 394 if (!descriptor) { 395 command->generic.status = B_USB_RAW_STATUS_ABORTED; 396 return B_OK; 397 } 398 399 if (descriptor->generic.length > command->generic.length) { 400 command->generic.status = B_USB_RAW_STATUS_NO_MEMORY; 401 return B_OK; 402 } 403 404 memcpy(command->generic.descriptor, descriptor, 405 descriptor->generic.length); 406 command->generic.status = B_USB_RAW_STATUS_SUCCESS; 407 return B_OK; 408 } 409 410 case B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR: { 411 size_t actualLength = 0; 412 uint8 firstTwoBytes[2]; 413 414 if (gUSBModule->get_descriptor(device->device, 415 USB_DESCRIPTOR_STRING, command->string.string_index, 0, 416 firstTwoBytes, 2, &actualLength) < B_OK 417 || actualLength != 2 418 || firstTwoBytes[1] != USB_DESCRIPTOR_STRING) { 419 command->string.status = B_USB_RAW_STATUS_ABORTED; 420 command->string.length = 0; 421 return B_OK; 422 } 423 424 uint8 stringLength = MIN(firstTwoBytes[0], command->string.length); 425 char *string = (char *)malloc(stringLength); 426 if (!string) { 427 command->string.status = B_USB_RAW_STATUS_ABORTED; 428 command->string.length = 0; 429 return B_NO_MEMORY; 430 } 431 432 if (gUSBModule->get_descriptor(device->device, 433 USB_DESCRIPTOR_STRING, command->string.string_index, 0, 434 string, stringLength, &actualLength) < B_OK 435 || actualLength != stringLength) { 436 command->string.status = B_USB_RAW_STATUS_ABORTED; 437 command->string.length = 0; 438 free(string); 439 return B_OK; 440 } 441 442 memcpy(command->string.descriptor, string, stringLength); 443 command->string.status = B_USB_RAW_STATUS_SUCCESS; 444 command->string.length = stringLength; 445 free(string); 446 return B_OK; 447 } 448 449 case B_USB_RAW_COMMAND_GET_DESCRIPTOR: { 450 size_t actualLength = 0; 451 uint8 firstTwoBytes[2]; 452 453 if (gUSBModule->get_descriptor(device->device, 454 command->descriptor.type, command->descriptor.index, 455 command->descriptor.language_id, firstTwoBytes, 2, 456 &actualLength) < B_OK 457 || actualLength != 2 458 || firstTwoBytes[1] != command->descriptor.type) { 459 command->descriptor.status = B_USB_RAW_STATUS_ABORTED; 460 command->descriptor.length = 0; 461 return B_OK; 462 } 463 464 uint8 length = MIN(firstTwoBytes[0], command->descriptor.length); 465 uint8 *buffer = (uint8 *)malloc(length); 466 if (!buffer) { 467 command->descriptor.status = B_USB_RAW_STATUS_ABORTED; 468 command->descriptor.length = 0; 469 return B_NO_MEMORY; 470 } 471 472 if (gUSBModule->get_descriptor(device->device, 473 command->descriptor.type, command->descriptor.index, 474 command->descriptor.language_id, buffer, length, 475 &actualLength) < B_OK 476 || actualLength != length) { 477 command->descriptor.status = B_USB_RAW_STATUS_ABORTED; 478 command->descriptor.length = 0; 479 free(buffer); 480 return B_OK; 481 } 482 483 memcpy(command->descriptor.data, buffer, length); 484 command->descriptor.status = B_USB_RAW_STATUS_SUCCESS; 485 command->descriptor.length = length; 486 free(buffer); 487 return B_OK; 488 } 489 490 case B_USB_RAW_COMMAND_SET_CONFIGURATION: { 491 const usb_configuration_info *configurationInfo = 492 gUSBModule->get_nth_configuration(device->device, 493 command->config.config_index); 494 if (!configurationInfo) { 495 command->config.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION; 496 return B_OK; 497 } 498 499 if (gUSBModule->set_configuration(device->device, 500 configurationInfo) < B_OK) { 501 command->config.status = B_USB_RAW_STATUS_FAILED; 502 return B_OK; 503 } 504 505 command->config.status = B_USB_RAW_STATUS_SUCCESS; 506 return B_OK; 507 } 508 509 case B_USB_RAW_COMMAND_SET_ALT_INTERFACE: { 510 const usb_configuration_info *configurationInfo = 511 gUSBModule->get_nth_configuration(device->device, 512 command->alternate.config_index); 513 if (!configurationInfo) { 514 command->alternate.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION; 515 return B_OK; 516 } 517 518 if (command->alternate.interface_index >= configurationInfo->interface_count) { 519 command->alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 520 return B_OK; 521 } 522 523 const usb_interface_list *interfaceList = 524 &configurationInfo->interface[command->alternate.interface_index]; 525 if (command->alternate.alternate_index >= interfaceList->alt_count) { 526 command->alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 527 return B_OK; 528 } 529 530 if (gUSBModule->set_alt_interface(device->device, 531 &interfaceList->alt[command->alternate.alternate_index]) < B_OK) { 532 command->alternate.status = B_USB_RAW_STATUS_FAILED; 533 return B_OK; 534 } 535 536 command->alternate.status = B_USB_RAW_STATUS_SUCCESS; 537 return B_OK; 538 } 539 540 case B_USB_RAW_COMMAND_CONTROL_TRANSFER: { 541 benaphore_lock(&device->lock); 542 if (gUSBModule->queue_request(device->device, 543 command->control.request_type, command->control.request, 544 command->control.value, command->control.index, 545 command->control.length, command->control.data, 546 usb_raw_callback, device) < B_OK) { 547 command->control.status = B_USB_RAW_STATUS_FAILED; 548 command->control.length = 0; 549 benaphore_unlock(&device->lock); 550 return B_OK; 551 } 552 553 acquire_sem(device->notify); 554 command->control.status = device->status; 555 command->control.length = device->actual_length; 556 benaphore_unlock(&device->lock); 557 return B_OK; 558 } 559 560 case B_USB_RAW_COMMAND_INTERRUPT_TRANSFER: 561 case B_USB_RAW_COMMAND_BULK_TRANSFER: 562 case B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER: { 563 const usb_configuration_info *configurationInfo = 564 gUSBModule->get_configuration(device->device); 565 if (!configurationInfo) { 566 command->transfer.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION; 567 return B_OK; 568 } 569 570 if (command->transfer.interface >= configurationInfo->interface_count) { 571 command->transfer.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 572 return B_OK; 573 } 574 575 const usb_interface_info *interfaceInfo = 576 configurationInfo->interface[command->transfer.interface].active; 577 if (!interfaceInfo) { 578 command->transfer.status = B_USB_RAW_STATUS_ABORTED; 579 return B_OK; 580 } 581 582 if (command->transfer.endpoint >= interfaceInfo->endpoint_count) { 583 command->transfer.status = B_USB_RAW_STATUS_INVALID_ENDPOINT; 584 return B_OK; 585 } 586 587 const usb_endpoint_info *endpointInfo = 588 &interfaceInfo->endpoint[command->transfer.endpoint]; 589 if (!endpointInfo->handle) { 590 command->transfer.status = B_USB_RAW_STATUS_INVALID_ENDPOINT; 591 return B_OK; 592 } 593 594 size_t descriptorsSize = 0; 595 usb_iso_packet_descriptor *packetDescriptors = NULL; 596 if (op == B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER) { 597 descriptorsSize = sizeof(usb_iso_packet_descriptor) 598 * command->isochronous.packet_count; 599 packetDescriptors 600 = (usb_iso_packet_descriptor *)malloc(descriptorsSize); 601 if (!packetDescriptors) { 602 command->transfer.status = B_USB_RAW_STATUS_NO_MEMORY; 603 command->transfer.length = 0; 604 return B_OK; 605 } 606 607 memcpy(packetDescriptors, 608 command->isochronous.packet_descriptors, descriptorsSize); 609 } 610 611 status_t status; 612 benaphore_lock(&device->lock); 613 if (op == B_USB_RAW_COMMAND_INTERRUPT_TRANSFER) { 614 status = gUSBModule->queue_interrupt(endpointInfo->handle, 615 command->transfer.data, command->transfer.length, 616 usb_raw_callback, device); 617 } else if (op == B_USB_RAW_COMMAND_BULK_TRANSFER) { 618 status = gUSBModule->queue_bulk(endpointInfo->handle, 619 command->transfer.data, command->transfer.length, 620 usb_raw_callback, device); 621 } else { 622 status = gUSBModule->queue_isochronous(endpointInfo->handle, 623 command->isochronous.data, command->isochronous.length, 624 packetDescriptors, command->isochronous.packet_count, NULL, 625 0, usb_raw_callback, device); 626 } 627 628 if (status < B_OK) { 629 command->transfer.status = B_USB_RAW_STATUS_FAILED; 630 command->transfer.length = 0; 631 free(packetDescriptors); 632 benaphore_unlock(&device->lock); 633 return B_OK; 634 } 635 636 acquire_sem(device->notify); 637 command->transfer.status = device->status; 638 command->transfer.length = device->actual_length; 639 benaphore_unlock(&device->lock); 640 641 if (op == B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER) { 642 memcpy(command->isochronous.packet_descriptors, 643 packetDescriptors, descriptorsSize); 644 free(packetDescriptors); 645 } 646 647 return B_OK; 648 } 649 } 650 651 return B_DEV_INVALID_IOCTL; 652 } 653 654 655 static status_t 656 usb_raw_read(void *cookie, off_t position, void *buffer, size_t *length) 657 { 658 TRACE((DRIVER_NAME": read()\n")); 659 *length = 0; 660 return B_OK; 661 } 662 663 664 static status_t 665 usb_raw_write(void *cookie, off_t position, const void *buffer, size_t *length) 666 { 667 TRACE((DRIVER_NAME": write()\n")); 668 *length = 0; 669 return B_OK; 670 } 671 672 673 // 674 //#pragma mark - 675 // 676 677 678 status_t 679 init_hardware() 680 { 681 TRACE((DRIVER_NAME": init_hardware()\n")); 682 return B_OK; 683 } 684 685 686 status_t 687 init_driver() 688 { 689 TRACE((DRIVER_NAME": init_driver()\n")); 690 static usb_notify_hooks notifyHooks = { 691 &usb_raw_device_added, 692 &usb_raw_device_removed 693 }; 694 695 gDeviceList = NULL; 696 gDeviceCount = 0; 697 status_t result = benaphore_init(&gDeviceListLock, "usb_raw device list lock"); 698 if (result < B_OK) { 699 TRACE((DRIVER_NAME": failed to create device list lock\n")); 700 return result; 701 } 702 703 TRACE((DRIVER_NAME": trying module %s\n", B_USB_MODULE_NAME)); 704 result = get_module(B_USB_MODULE_NAME, (module_info **)&gUSBModule); 705 if (result < B_OK) { 706 TRACE((DRIVER_NAME": getting module failed 0x%08lx\n", result)); 707 benaphore_destroy(&gDeviceListLock); 708 return result; 709 } 710 711 gUSBModule->register_driver(DRIVER_NAME, NULL, 0, NULL); 712 gUSBModule->install_notify(DRIVER_NAME, ¬ifyHooks); 713 return B_OK; 714 } 715 716 717 void 718 uninit_driver() 719 { 720 TRACE((DRIVER_NAME": uninit_driver()\n")); 721 gUSBModule->uninstall_notify(DRIVER_NAME); 722 benaphore_lock(&gDeviceListLock); 723 724 if (gDeviceNames) { 725 for (int32 i = 1; gDeviceNames[i]; i++) 726 free(gDeviceNames[i]); 727 free(gDeviceNames); 728 gDeviceNames = NULL; 729 } 730 731 benaphore_destroy(&gDeviceListLock); 732 put_module(B_USB_MODULE_NAME); 733 } 734 735 736 const char ** 737 publish_devices() 738 { 739 TRACE((DRIVER_NAME": publish_devices()\n")); 740 if (gDeviceNames) { 741 for (int32 i = 1; gDeviceNames[i]; i++) 742 free(gDeviceNames[i]); 743 free(gDeviceNames); 744 gDeviceNames = NULL; 745 } 746 747 int32 index = 0; 748 gDeviceNames = (char **)malloc(sizeof(char *) * (gDeviceCount + 2)); 749 if (!gDeviceNames) 750 return NULL; 751 752 gDeviceNames[index++] = DEVICE_NAME; 753 754 benaphore_lock(&gDeviceListLock); 755 raw_device *element = gDeviceList; 756 while (element) { 757 gDeviceNames[index++] = strdup(element->name); 758 element = (raw_device *)element->link; 759 } 760 761 gDeviceNames[index++] = NULL; 762 benaphore_unlock(&gDeviceListLock); 763 return (const char **)gDeviceNames; 764 } 765 766 767 device_hooks * 768 find_device(const char *name) 769 { 770 TRACE((DRIVER_NAME": find_device()\n")); 771 static device_hooks hooks = { 772 &usb_raw_open, 773 &usb_raw_close, 774 &usb_raw_free, 775 &usb_raw_ioctl, 776 &usb_raw_read, 777 &usb_raw_write, 778 NULL, 779 NULL, 780 NULL, 781 NULL 782 }; 783 784 return &hooks; 785 } 786