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