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