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