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