1 /* 2 * Copyright 2006-2010, 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 "usb_raw.h" 10 11 #include <KernelExport.h> 12 #include <Drivers.h> 13 #include <lock.h> 14 #include <malloc.h> 15 #include <stdio.h> 16 #include <string.h> 17 18 #include <kernel.h> 19 20 21 //#define TRACE_USB_RAW 22 #ifdef TRACE_USB_RAW 23 #define TRACE(x) dprintf x 24 #else 25 #define TRACE(x) /* nothing */ 26 #endif 27 28 #define DRIVER_NAME "usb_raw" 29 #define DEVICE_NAME "bus/usb/raw" 30 31 typedef struct { 32 usb_device device; 33 mutex lock; 34 uint32 reference_count; 35 36 char name[64]; 37 void *link; 38 39 sem_id notify; 40 status_t status; 41 size_t actual_length; 42 } raw_device; 43 44 int32 api_version = B_CUR_DRIVER_API_VERSION; 45 static usb_module_info *gUSBModule = NULL; 46 static raw_device *gDeviceList = NULL; 47 static uint32 gDeviceCount = 0; 48 static mutex gDeviceListLock; 49 static char **gDeviceNames = NULL; 50 51 static status_t 52 usb_raw_device_added(usb_device newDevice, void **cookie) 53 { 54 TRACE((DRIVER_NAME": device_added(0x%08" B_PRIx32 ")\n", newDevice)); 55 raw_device *device = (raw_device *)malloc(sizeof(raw_device)); 56 57 mutex_init(&device->lock, "usb_raw device lock"); 58 59 device->notify = create_sem(0, "usb_raw callback notify"); 60 if (device->notify < B_OK) { 61 mutex_destroy(&device->lock); 62 free(device); 63 return B_NO_MORE_SEMS; 64 } 65 66 char deviceName[64]; 67 memcpy(deviceName, &newDevice, sizeof(usb_device)); 68 if (gUSBModule->usb_ioctl('DNAM', deviceName, sizeof(deviceName)) >= B_OK) { 69 snprintf(device->name, sizeof(device->name), "bus/usb/%s", deviceName); 70 } else { 71 snprintf(device->name, sizeof(device->name), "bus/usb/%08" B_PRIx32, 72 newDevice); 73 } 74 75 device->device = newDevice; 76 device->reference_count = 0; 77 78 mutex_lock(&gDeviceListLock); 79 device->link = (void *)gDeviceList; 80 gDeviceList = device; 81 gDeviceCount++; 82 mutex_unlock(&gDeviceListLock); 83 84 TRACE((DRIVER_NAME": new device: 0x%p\n", device)); 85 *cookie = (void *)device; 86 return B_OK; 87 } 88 89 90 static status_t 91 usb_raw_device_removed(void *cookie) 92 { 93 TRACE((DRIVER_NAME": device_removed(0x%p)\n", cookie)); 94 raw_device *device = (raw_device *)cookie; 95 96 mutex_lock(&gDeviceListLock); 97 if (gDeviceList == device) { 98 gDeviceList = (raw_device *)device->link; 99 } else { 100 raw_device *element = gDeviceList; 101 while (element) { 102 if (element->link == device) { 103 element->link = device->link; 104 break; 105 } 106 107 element = (raw_device *)element->link; 108 } 109 } 110 gDeviceCount--; 111 mutex_unlock(&gDeviceListLock); 112 113 device->device = 0; 114 if (device->reference_count == 0) { 115 mutex_lock(&device->lock); 116 mutex_destroy(&device->lock); 117 delete_sem(device->notify); 118 free(device); 119 } 120 121 return B_OK; 122 } 123 124 125 // 126 //#pragma mark - 127 // 128 129 130 static const usb_configuration_info * 131 usb_raw_get_configuration(raw_device *device, uint32 configIndex, 132 status_t *status) 133 { 134 const usb_configuration_info *result = gUSBModule->get_nth_configuration( 135 device->device, configIndex); 136 if (result == NULL) { 137 *status = B_USB_RAW_STATUS_INVALID_CONFIGURATION; 138 return NULL; 139 } 140 141 return result; 142 } 143 144 145 static const usb_interface_info * 146 usb_raw_get_interface(raw_device *device, uint32 configIndex, 147 uint32 interfaceIndex, uint32 alternateIndex, status_t *status) 148 { 149 const usb_configuration_info *configurationInfo 150 = usb_raw_get_configuration(device, configIndex, status); 151 if (configurationInfo == NULL) 152 return NULL; 153 154 if (interfaceIndex >= configurationInfo->interface_count) { 155 *status = B_USB_RAW_STATUS_INVALID_INTERFACE; 156 return NULL; 157 } 158 159 const usb_interface_info *result = NULL; 160 if (alternateIndex == B_USB_RAW_ACTIVE_ALTERNATE) 161 result = configurationInfo->interface[interfaceIndex].active; 162 else { 163 const usb_interface_list *interfaceList = 164 &configurationInfo->interface[interfaceIndex]; 165 if (alternateIndex >= interfaceList->alt_count) { 166 *status = B_USB_RAW_STATUS_INVALID_INTERFACE; 167 return NULL; 168 } 169 170 result = &interfaceList->alt[alternateIndex]; 171 } 172 173 return result; 174 } 175 176 177 // 178 //#pragma mark - 179 // 180 181 182 static status_t 183 usb_raw_open(const char *name, uint32 flags, void **cookie) 184 { 185 TRACE((DRIVER_NAME": open()\n")); 186 mutex_lock(&gDeviceListLock); 187 raw_device *element = gDeviceList; 188 while (element) { 189 if (strcmp(name, element->name) == 0) { 190 element->reference_count++; 191 *cookie = element; 192 mutex_unlock(&gDeviceListLock); 193 return B_OK; 194 } 195 196 element = (raw_device *)element->link; 197 } 198 199 mutex_unlock(&gDeviceListLock); 200 return B_NAME_NOT_FOUND; 201 } 202 203 204 static status_t 205 usb_raw_close(void *cookie) 206 { 207 TRACE((DRIVER_NAME": close()\n")); 208 return B_OK; 209 } 210 211 212 static status_t 213 usb_raw_free(void *cookie) 214 { 215 TRACE((DRIVER_NAME": free()\n")); 216 mutex_lock(&gDeviceListLock); 217 218 raw_device *device = (raw_device *)cookie; 219 device->reference_count--; 220 if (device->device == 0) { 221 mutex_lock(&device->lock); 222 mutex_destroy(&device->lock); 223 delete_sem(device->notify); 224 free(device); 225 } 226 227 mutex_unlock(&gDeviceListLock); 228 return B_OK; 229 } 230 231 232 static void 233 usb_raw_callback(void *cookie, status_t status, void *data, size_t actualLength) 234 { 235 TRACE((DRIVER_NAME": callback()\n")); 236 raw_device *device = (raw_device *)cookie; 237 238 switch (status) { 239 case B_OK: 240 device->status = B_USB_RAW_STATUS_SUCCESS; 241 break; 242 case B_TIMED_OUT: 243 device->status = B_USB_RAW_STATUS_TIMEOUT; 244 break; 245 case B_CANCELED: 246 device->status = B_USB_RAW_STATUS_ABORTED; 247 break; 248 case B_DEV_CRC_ERROR: 249 device->status = B_USB_RAW_STATUS_CRC_ERROR; 250 break; 251 case B_DEV_STALLED: 252 device->status = B_USB_RAW_STATUS_STALLED; 253 break; 254 default: 255 device->status = B_USB_RAW_STATUS_FAILED; 256 break; 257 } 258 259 device->actual_length = actualLength; 260 release_sem(device->notify); 261 } 262 263 264 static status_t 265 usb_raw_ioctl(void *cookie, uint32 op, void *buffer, size_t length) 266 { 267 TRACE((DRIVER_NAME": ioctl\n")); 268 raw_device *device = (raw_device *)cookie; 269 if (device->device == 0) 270 return B_DEV_NOT_READY; 271 272 usb_raw_command command; 273 if (length < sizeof(command.version.status)) 274 return B_BUFFER_OVERFLOW; 275 if (!IS_USER_ADDRESS(buffer) 276 || user_memcpy(&command, buffer, min_c(length, sizeof(command))) 277 != B_OK) { 278 return B_BAD_ADDRESS; 279 } 280 281 command.version.status = B_USB_RAW_STATUS_ABORTED; 282 status_t status = B_DEV_INVALID_IOCTL; 283 284 switch (op) { 285 case B_USB_RAW_COMMAND_GET_VERSION: 286 { 287 command.version.status = B_USB_RAW_PROTOCOL_VERSION; 288 status = B_OK; 289 break; 290 } 291 292 case B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR: 293 { 294 if (length < sizeof(command.device)) 295 return B_BUFFER_OVERFLOW; 296 297 status = B_OK; 298 const usb_device_descriptor *deviceDescriptor = 299 gUSBModule->get_device_descriptor(device->device); 300 if (deviceDescriptor == NULL) 301 return B_OK; 302 303 if (!IS_USER_ADDRESS(command.device.descriptor) 304 || user_memcpy(command.device.descriptor, deviceDescriptor, 305 sizeof(usb_device_descriptor)) != B_OK) { 306 return B_BAD_ADDRESS; 307 } 308 309 command.device.status = B_USB_RAW_STATUS_SUCCESS; 310 break; 311 } 312 313 case B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR: 314 { 315 if (length < sizeof(command.config)) 316 return B_BUFFER_OVERFLOW; 317 318 status = B_OK; 319 const usb_configuration_info *configurationInfo = 320 usb_raw_get_configuration(device, command.config.config_index, 321 &command.config.status); 322 if (configurationInfo == NULL) 323 break; 324 325 if (!IS_USER_ADDRESS(command.config.descriptor) 326 || user_memcpy(command.config.descriptor, 327 configurationInfo->descr, 328 sizeof(usb_configuration_descriptor)) != B_OK) { 329 return B_BAD_ADDRESS; 330 } 331 332 command.config.status = B_USB_RAW_STATUS_SUCCESS; 333 break; 334 } 335 336 case B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT: 337 case B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX: 338 { 339 if (length < sizeof(command.alternate)) 340 return B_BUFFER_OVERFLOW; 341 342 status = B_OK; 343 const usb_configuration_info *configurationInfo = 344 usb_raw_get_configuration(device, 345 command.alternate.config_index, 346 &command.alternate.status); 347 if (configurationInfo == NULL) 348 break; 349 350 if (command.alternate.interface_index 351 >= configurationInfo->interface_count) { 352 command.alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 353 break; 354 } 355 356 const usb_interface_list *interfaceList 357 = &configurationInfo->interface[ 358 command.alternate.interface_index]; 359 if (op == B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT) { 360 command.alternate.alternate_info = interfaceList->alt_count; 361 } else { 362 for (size_t i = 0; i < interfaceList->alt_count; i++) { 363 if (&interfaceList->alt[i] == interfaceList->active) { 364 command.alternate.alternate_info = i; 365 break; 366 } 367 } 368 } 369 370 command.alternate.status = B_USB_RAW_STATUS_SUCCESS; 371 break; 372 } 373 374 case B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR: 375 case B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC: 376 { 377 const usb_interface_info *interfaceInfo = NULL; 378 status = B_OK; 379 if (op == B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR) { 380 if (length < sizeof(command.interface)) 381 return B_BUFFER_OVERFLOW; 382 383 interfaceInfo = usb_raw_get_interface(device, 384 command.interface.config_index, 385 command.interface.interface_index, 386 B_USB_RAW_ACTIVE_ALTERNATE, 387 &command.interface.status); 388 } else { 389 if (length < sizeof(command.interface_etc)) 390 return B_BUFFER_OVERFLOW; 391 392 interfaceInfo = usb_raw_get_interface(device, 393 command.interface_etc.config_index, 394 command.interface_etc.interface_index, 395 command.interface_etc.alternate_index, 396 &command.interface_etc.status); 397 } 398 399 if (interfaceInfo == NULL) 400 break; 401 402 if (!IS_USER_ADDRESS(command.interface.descriptor) 403 || user_memcpy(command.interface.descriptor, interfaceInfo->descr, 404 sizeof(usb_interface_descriptor)) != B_OK) { 405 return B_BAD_ADDRESS; 406 } 407 408 command.interface.status = B_USB_RAW_STATUS_SUCCESS; 409 break; 410 } 411 412 case B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR: 413 case B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC: 414 { 415 uint32 endpointIndex = 0; 416 const usb_interface_info *interfaceInfo = NULL; 417 status = B_OK; 418 if (op == B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR) { 419 if (length < sizeof(command.endpoint)) 420 return B_BUFFER_OVERFLOW; 421 422 interfaceInfo = usb_raw_get_interface(device, 423 command.endpoint.config_index, 424 command.endpoint.interface_index, 425 B_USB_RAW_ACTIVE_ALTERNATE, 426 &command.endpoint.status); 427 endpointIndex = command.endpoint.endpoint_index; 428 } else { 429 if (length < sizeof(command.endpoint_etc)) 430 return B_BUFFER_OVERFLOW; 431 432 interfaceInfo = usb_raw_get_interface(device, 433 command.endpoint_etc.config_index, 434 command.endpoint_etc.interface_index, 435 command.endpoint_etc.alternate_index, 436 &command.endpoint_etc.status); 437 endpointIndex = command.endpoint_etc.endpoint_index; 438 } 439 440 if (interfaceInfo == NULL) 441 break; 442 443 if (endpointIndex >= interfaceInfo->endpoint_count) { 444 command.endpoint.status = B_USB_RAW_STATUS_INVALID_ENDPOINT; 445 break; 446 } 447 448 if (!IS_USER_ADDRESS(command.endpoint.descriptor) 449 || user_memcpy(command.endpoint.descriptor, 450 interfaceInfo->endpoint[endpointIndex].descr, 451 sizeof(usb_endpoint_descriptor)) != B_OK) { 452 return B_BAD_ADDRESS; 453 } 454 455 command.endpoint.status = B_USB_RAW_STATUS_SUCCESS; 456 break; 457 } 458 459 case B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR: 460 case B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC: 461 { 462 uint32 genericIndex = 0; 463 size_t genericLength = 0; 464 const usb_interface_info *interfaceInfo = NULL; 465 status = B_OK; 466 if (op == B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR) { 467 if (length < sizeof(command.generic)) 468 return B_BUFFER_OVERFLOW; 469 470 interfaceInfo = usb_raw_get_interface(device, 471 command.generic.config_index, 472 command.generic.interface_index, 473 B_USB_RAW_ACTIVE_ALTERNATE, 474 &command.generic.status); 475 genericIndex = command.generic.generic_index; 476 genericLength = command.generic.length; 477 } else { 478 if (length < sizeof(command.generic_etc)) 479 return B_BUFFER_OVERFLOW; 480 481 interfaceInfo = usb_raw_get_interface(device, 482 command.generic_etc.config_index, 483 command.generic_etc.interface_index, 484 command.generic_etc.alternate_index, 485 &command.generic_etc.status); 486 genericIndex = command.generic_etc.generic_index; 487 genericLength = command.generic_etc.length; 488 } 489 490 if (interfaceInfo == NULL) 491 break; 492 493 if (genericIndex >= interfaceInfo->generic_count) { 494 command.endpoint.status = B_USB_RAW_STATUS_INVALID_ENDPOINT; 495 break; 496 } 497 498 usb_descriptor *descriptor = interfaceInfo->generic[genericIndex]; 499 if (descriptor == NULL) 500 break; 501 502 if (!IS_USER_ADDRESS(command.generic.descriptor) 503 || user_memcpy(command.generic.descriptor, descriptor, 504 min_c(genericLength, descriptor->generic.length)) != B_OK) { 505 return B_BAD_ADDRESS; 506 } 507 508 if (descriptor->generic.length > genericLength) 509 command.generic.status = B_USB_RAW_STATUS_NO_MEMORY; 510 else 511 command.generic.status = B_USB_RAW_STATUS_SUCCESS; 512 break; 513 } 514 515 case B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR: 516 { 517 if (length < sizeof(command.string)) 518 return B_BUFFER_OVERFLOW; 519 520 size_t actualLength = 0; 521 uint8 firstTwoBytes[2]; 522 status = B_OK; 523 524 if (gUSBModule->get_descriptor(device->device, 525 USB_DESCRIPTOR_STRING, command.string.string_index, 0, 526 firstTwoBytes, 2, &actualLength) < B_OK 527 || actualLength != 2 528 || firstTwoBytes[1] != USB_DESCRIPTOR_STRING) { 529 command.string.status = B_USB_RAW_STATUS_ABORTED; 530 command.string.length = 0; 531 break; 532 } 533 534 uint8 stringLength = MIN(firstTwoBytes[0], command.string.length); 535 char *string = (char *)malloc(stringLength); 536 if (string == NULL) { 537 command.string.status = B_USB_RAW_STATUS_ABORTED; 538 command.string.length = 0; 539 status = B_NO_MEMORY; 540 break; 541 } 542 543 if (gUSBModule->get_descriptor(device->device, 544 USB_DESCRIPTOR_STRING, command.string.string_index, 0, 545 string, stringLength, &actualLength) < B_OK 546 || actualLength != stringLength) { 547 command.string.status = B_USB_RAW_STATUS_ABORTED; 548 command.string.length = 0; 549 free(string); 550 break; 551 } 552 553 if (!IS_USER_ADDRESS(command.string.descriptor) 554 || user_memcpy(command.string.descriptor, string, 555 stringLength) != B_OK) { 556 free(string); 557 return B_BAD_ADDRESS; 558 } 559 560 command.string.status = B_USB_RAW_STATUS_SUCCESS; 561 command.string.length = stringLength; 562 free(string); 563 break; 564 } 565 566 case B_USB_RAW_COMMAND_GET_DESCRIPTOR: 567 { 568 if (length < sizeof(command.descriptor)) 569 return B_BUFFER_OVERFLOW; 570 571 size_t actualLength = 0; 572 uint8 firstTwoBytes[2]; 573 status = B_OK; 574 575 if (gUSBModule->get_descriptor(device->device, 576 command.descriptor.type, command.descriptor.index, 577 command.descriptor.language_id, firstTwoBytes, 2, 578 &actualLength) < B_OK 579 || actualLength != 2 580 || firstTwoBytes[1] != command.descriptor.type) { 581 command.descriptor.status = B_USB_RAW_STATUS_ABORTED; 582 command.descriptor.length = 0; 583 break; 584 } 585 586 uint8 descriptorLength = MIN(firstTwoBytes[0], 587 command.descriptor.length); 588 uint8 *descriptorBuffer = (uint8 *)malloc(descriptorLength); 589 if (descriptorBuffer == NULL) { 590 command.descriptor.status = B_USB_RAW_STATUS_ABORTED; 591 command.descriptor.length = 0; 592 status = B_NO_MEMORY; 593 break; 594 } 595 596 if (gUSBModule->get_descriptor(device->device, 597 command.descriptor.type, command.descriptor.index, 598 command.descriptor.language_id, descriptorBuffer, 599 descriptorLength, &actualLength) < B_OK 600 || actualLength != descriptorLength) { 601 command.descriptor.status = B_USB_RAW_STATUS_ABORTED; 602 command.descriptor.length = 0; 603 free(descriptorBuffer); 604 break; 605 } 606 607 if (!IS_USER_ADDRESS(command.descriptor.data) 608 || user_memcpy(command.descriptor.data, descriptorBuffer, 609 descriptorLength) != B_OK) { 610 free(descriptorBuffer); 611 return B_BAD_ADDRESS; 612 } 613 614 command.descriptor.status = B_USB_RAW_STATUS_SUCCESS; 615 command.descriptor.length = descriptorLength; 616 free(descriptorBuffer); 617 break; 618 } 619 620 case B_USB_RAW_COMMAND_SET_CONFIGURATION: 621 { 622 if (length < sizeof(command.config)) 623 return B_BUFFER_OVERFLOW; 624 625 status = B_OK; 626 const usb_configuration_info *configurationInfo = 627 usb_raw_get_configuration(device, command.config.config_index, 628 &command.config.status); 629 if (configurationInfo == NULL) 630 break; 631 632 if (gUSBModule->set_configuration(device->device, 633 configurationInfo) < B_OK) { 634 command.config.status = B_USB_RAW_STATUS_FAILED; 635 break; 636 } 637 638 command.config.status = B_USB_RAW_STATUS_SUCCESS; 639 break; 640 } 641 642 case B_USB_RAW_COMMAND_SET_ALT_INTERFACE: 643 { 644 if (length < sizeof(command.alternate)) 645 return B_BUFFER_OVERFLOW; 646 647 status = B_OK; 648 const usb_configuration_info *configurationInfo = 649 usb_raw_get_configuration(device, 650 command.alternate.config_index, 651 &command.alternate.status); 652 if (configurationInfo == NULL) 653 break; 654 655 if (command.alternate.interface_index 656 >= configurationInfo->interface_count) { 657 command.alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 658 break; 659 } 660 661 const usb_interface_list *interfaceList = 662 &configurationInfo->interface[command.alternate.interface_index]; 663 if (command.alternate.alternate_info >= interfaceList->alt_count) { 664 command.alternate.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 665 break; 666 } 667 668 if (gUSBModule->set_alt_interface(device->device, 669 &interfaceList->alt[command.alternate.alternate_info]) < B_OK) { 670 command.alternate.status = B_USB_RAW_STATUS_FAILED; 671 break; 672 } 673 674 command.alternate.status = B_USB_RAW_STATUS_SUCCESS; 675 break; 676 } 677 678 case B_USB_RAW_COMMAND_CONTROL_TRANSFER: 679 { 680 if (length < sizeof(command.control)) 681 return B_BUFFER_OVERFLOW; 682 683 void *controlData = malloc(command.control.length); 684 bool inTransfer = (command.control.request_type 685 & USB_ENDPOINT_ADDR_DIR_IN) != 0; 686 if (!IS_USER_ADDRESS(command.control.data) 687 || (!inTransfer && user_memcpy(controlData, 688 command.control.data, command.control.length) != B_OK)) { 689 return B_BAD_ADDRESS; 690 } 691 692 mutex_lock(&device->lock); 693 if (gUSBModule->queue_request(device->device, 694 command.control.request_type, command.control.request, 695 command.control.value, command.control.index, 696 command.control.length, controlData, 697 usb_raw_callback, device) < B_OK) { 698 command.control.status = B_USB_RAW_STATUS_FAILED; 699 command.control.length = 0; 700 mutex_unlock(&device->lock); 701 free(controlData); 702 status = B_OK; 703 break; 704 } 705 706 acquire_sem(device->notify); 707 command.control.status = device->status; 708 command.control.length = device->actual_length; 709 mutex_unlock(&device->lock); 710 711 status = B_OK; 712 if (inTransfer && user_memcpy(command.control.data, controlData, 713 command.control.length) != B_OK) { 714 status = B_BAD_ADDRESS; 715 } 716 717 free(controlData); 718 break; 719 } 720 721 case B_USB_RAW_COMMAND_INTERRUPT_TRANSFER: 722 case B_USB_RAW_COMMAND_BULK_TRANSFER: 723 case B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER: 724 { 725 if (length < sizeof(command.transfer)) 726 return B_BUFFER_OVERFLOW; 727 728 status = B_OK; 729 const usb_configuration_info *configurationInfo = 730 gUSBModule->get_configuration(device->device); 731 if (configurationInfo == NULL) { 732 command.transfer.status = B_USB_RAW_STATUS_INVALID_CONFIGURATION; 733 break; 734 } 735 736 if (command.transfer.interface >= configurationInfo->interface_count) { 737 command.transfer.status = B_USB_RAW_STATUS_INVALID_INTERFACE; 738 break; 739 } 740 741 const usb_interface_info *interfaceInfo = 742 configurationInfo->interface[command.transfer.interface].active; 743 if (interfaceInfo == NULL) { 744 command.transfer.status = B_USB_RAW_STATUS_ABORTED; 745 break; 746 } 747 748 if (command.transfer.endpoint >= interfaceInfo->endpoint_count) { 749 command.transfer.status = B_USB_RAW_STATUS_INVALID_ENDPOINT; 750 break; 751 } 752 753 const usb_endpoint_info *endpointInfo = 754 &interfaceInfo->endpoint[command.transfer.endpoint]; 755 if (!endpointInfo->handle) { 756 command.transfer.status = B_USB_RAW_STATUS_INVALID_ENDPOINT; 757 break; 758 } 759 760 size_t descriptorsSize = 0; 761 usb_iso_packet_descriptor *packetDescriptors = NULL; 762 void *transferData = NULL; 763 bool inTransfer = (endpointInfo->descr->endpoint_address 764 & USB_ENDPOINT_ADDR_DIR_IN) != 0; 765 if (op == B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER) { 766 if (length < sizeof(command.isochronous)) 767 return B_BUFFER_OVERFLOW; 768 769 descriptorsSize = sizeof(usb_iso_packet_descriptor) 770 * command.isochronous.packet_count; 771 packetDescriptors 772 = (usb_iso_packet_descriptor *)malloc(descriptorsSize); 773 if (packetDescriptors == NULL) { 774 command.transfer.status = B_USB_RAW_STATUS_NO_MEMORY; 775 command.transfer.length = 0; 776 break; 777 } 778 779 if (!IS_USER_ADDRESS(command.isochronous.data) 780 || !IS_USER_ADDRESS(command.isochronous.packet_descriptors) 781 || user_memcpy(packetDescriptors, 782 command.isochronous.packet_descriptors, 783 descriptorsSize) != B_OK) { 784 free(packetDescriptors); 785 return B_BAD_ADDRESS; 786 } 787 } else { 788 transferData = malloc(command.transfer.length); 789 if (transferData == NULL) { 790 command.transfer.status = B_USB_RAW_STATUS_NO_MEMORY; 791 command.transfer.length = 0; 792 break; 793 } 794 795 if (!IS_USER_ADDRESS(command.transfer.data) || (!inTransfer 796 && user_memcpy(transferData, command.transfer.data, 797 command.transfer.length) != B_OK)) { 798 free(transferData); 799 return B_BAD_ADDRESS; 800 } 801 } 802 803 status_t status; 804 mutex_lock(&device->lock); 805 if (op == B_USB_RAW_COMMAND_INTERRUPT_TRANSFER) { 806 status = gUSBModule->queue_interrupt(endpointInfo->handle, 807 transferData, command.transfer.length, 808 usb_raw_callback, device); 809 } else if (op == B_USB_RAW_COMMAND_BULK_TRANSFER) { 810 status = gUSBModule->queue_bulk(endpointInfo->handle, 811 transferData, command.transfer.length, 812 usb_raw_callback, device); 813 } else { 814 status = gUSBModule->queue_isochronous(endpointInfo->handle, 815 command.isochronous.data, command.isochronous.length, 816 packetDescriptors, command.isochronous.packet_count, NULL, 817 0, usb_raw_callback, device); 818 } 819 820 if (status < B_OK) { 821 command.transfer.status = B_USB_RAW_STATUS_FAILED; 822 command.transfer.length = 0; 823 free(packetDescriptors); 824 free(transferData); 825 mutex_unlock(&device->lock); 826 status = B_OK; 827 break; 828 } 829 830 acquire_sem(device->notify); 831 command.transfer.status = device->status; 832 command.transfer.length = device->actual_length; 833 mutex_unlock(&device->lock); 834 835 status = B_OK; 836 if (op == B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER) { 837 if (user_memcpy(command.isochronous.packet_descriptors, 838 packetDescriptors, descriptorsSize) != B_OK) { 839 status = B_BAD_ADDRESS; 840 } 841 842 free(packetDescriptors); 843 } else { 844 if (inTransfer && user_memcpy(command.transfer.data, 845 transferData, command.transfer.length) != B_OK) { 846 status = B_BAD_ADDRESS; 847 } 848 free(transferData); 849 } 850 851 break; 852 } 853 } 854 855 if (user_memcpy(buffer, &command, min_c(length, sizeof(command))) != B_OK) 856 return B_BAD_ADDRESS; 857 858 return status; 859 } 860 861 862 static status_t 863 usb_raw_read(void *cookie, off_t position, void *buffer, size_t *length) 864 { 865 TRACE((DRIVER_NAME": read()\n")); 866 *length = 0; 867 return B_OK; 868 } 869 870 871 static status_t 872 usb_raw_write(void *cookie, off_t position, const void *buffer, size_t *length) 873 { 874 TRACE((DRIVER_NAME": write()\n")); 875 *length = 0; 876 return B_OK; 877 } 878 879 880 // 881 //#pragma mark - 882 // 883 884 885 status_t 886 init_hardware() 887 { 888 TRACE((DRIVER_NAME": init_hardware()\n")); 889 return B_OK; 890 } 891 892 893 status_t 894 init_driver() 895 { 896 TRACE((DRIVER_NAME": init_driver()\n")); 897 static usb_notify_hooks notifyHooks = { 898 &usb_raw_device_added, 899 &usb_raw_device_removed 900 }; 901 902 gDeviceList = NULL; 903 gDeviceCount = 0; 904 mutex_init(&gDeviceListLock, "usb_raw device list lock"); 905 906 TRACE((DRIVER_NAME": trying module %s\n", B_USB_MODULE_NAME)); 907 status_t result = get_module(B_USB_MODULE_NAME, 908 (module_info **)&gUSBModule); 909 if (result < B_OK) { 910 TRACE((DRIVER_NAME": getting module failed 0x%08" B_PRIx32 "\n", 911 result)); 912 mutex_destroy(&gDeviceListLock); 913 return result; 914 } 915 916 gUSBModule->register_driver(DRIVER_NAME, NULL, 0, NULL); 917 gUSBModule->install_notify(DRIVER_NAME, ¬ifyHooks); 918 return B_OK; 919 } 920 921 922 void 923 uninit_driver() 924 { 925 TRACE((DRIVER_NAME": uninit_driver()\n")); 926 gUSBModule->uninstall_notify(DRIVER_NAME); 927 mutex_lock(&gDeviceListLock); 928 929 if (gDeviceNames) { 930 for (int32 i = 1; gDeviceNames[i]; i++) 931 free(gDeviceNames[i]); 932 free(gDeviceNames); 933 gDeviceNames = NULL; 934 } 935 936 mutex_destroy(&gDeviceListLock); 937 put_module(B_USB_MODULE_NAME); 938 } 939 940 941 const char ** 942 publish_devices() 943 { 944 TRACE((DRIVER_NAME": publish_devices()\n")); 945 if (gDeviceNames) { 946 for (int32 i = 0; gDeviceNames[i]; i++) 947 free(gDeviceNames[i]); 948 free(gDeviceNames); 949 gDeviceNames = NULL; 950 } 951 952 int32 index = 0; 953 gDeviceNames = (char **)malloc(sizeof(char *) * (gDeviceCount + 2)); 954 if (gDeviceNames == NULL) 955 return NULL; 956 957 gDeviceNames[index++] = strdup(DEVICE_NAME); 958 959 mutex_lock(&gDeviceListLock); 960 raw_device *element = gDeviceList; 961 while (element) { 962 gDeviceNames[index++] = strdup(element->name); 963 element = (raw_device *)element->link; 964 } 965 966 gDeviceNames[index++] = NULL; 967 mutex_unlock(&gDeviceListLock); 968 return (const char **)gDeviceNames; 969 } 970 971 972 device_hooks * 973 find_device(const char *name) 974 { 975 TRACE((DRIVER_NAME": find_device()\n")); 976 static device_hooks hooks = { 977 &usb_raw_open, 978 &usb_raw_close, 979 &usb_raw_free, 980 &usb_raw_ioctl, 981 &usb_raw_read, 982 &usb_raw_write, 983 NULL, 984 NULL, 985 NULL, 986 NULL 987 }; 988 989 return &hooks; 990 } 991