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 const usb_configuration_info *configurationInfo = 472 gUSBModule->get_configuration(device->device); 473 if (!configurationInfo) { 474 command->transfer.status = RAW_STATUS_INVALID_CONFIGURATION; 475 return B_OK; 476 } 477 478 if (command->transfer.interface >= configurationInfo->interface_count) { 479 command->transfer.status = RAW_STATUS_INVALID_INTERFACE; 480 return B_OK; 481 } 482 483 const usb_interface_info *interfaceInfo = 484 configurationInfo->interface[command->transfer.interface].active; 485 if (!interfaceInfo) { 486 command->transfer.status = RAW_STATUS_ABORTED; 487 return B_OK; 488 } 489 490 if (command->transfer.endpoint >= interfaceInfo->endpoint_count) { 491 command->transfer.status = RAW_STATUS_INVALID_ENDPOINT; 492 return B_OK; 493 } 494 495 const usb_endpoint_info *endpointInfo = 496 &interfaceInfo->endpoint[command->transfer.endpoint]; 497 if (!endpointInfo->handle) { 498 command->transfer.status = RAW_STATUS_INVALID_ENDPOINT; 499 return B_OK; 500 } 501 502 benaphore_lock(&device->lock); 503 504 status_t status; 505 if (op == RAW_COMMAND_INTERRUPT_TRANSFER) { 506 status = gUSBModule->queue_interrupt(endpointInfo->handle, 507 command->transfer.data, command->transfer.length, 508 usb_raw_callback, device); 509 } else { 510 status = gUSBModule->queue_bulk(endpointInfo->handle, 511 command->transfer.data, command->transfer.length, 512 usb_raw_callback, device); 513 } 514 515 if (status < B_OK) { 516 command->transfer.status = RAW_STATUS_FAILED; 517 command->transfer.length = 0; 518 benaphore_unlock(&device->lock); 519 return B_OK; 520 } 521 522 acquire_sem(device->notify); 523 command->transfer.status = device->status; 524 command->transfer.length = device->actual_length; 525 benaphore_unlock(&device->lock); 526 return B_OK; 527 } 528 } 529 530 return B_DEV_INVALID_IOCTL; 531 } 532 533 534 static status_t 535 usb_raw_read(void *cookie, off_t position, void *buffer, size_t *length) 536 { 537 TRACE((DRIVER_NAME": read()\n")); 538 *length = 0; 539 return B_OK; 540 } 541 542 543 static status_t 544 usb_raw_write(void *cookie, off_t position, const void *buffer, size_t *length) 545 { 546 TRACE((DRIVER_NAME": write()\n")); 547 *length = 0; 548 return B_OK; 549 } 550 551 552 // 553 //#pragma mark - 554 // 555 556 557 status_t 558 init_hardware() 559 { 560 TRACE((DRIVER_NAME": init_hardware()\n")); 561 return B_OK; 562 } 563 564 565 status_t 566 init_driver() 567 { 568 TRACE((DRIVER_NAME": init_driver()\n")); 569 static usb_notify_hooks notifyHooks = { 570 &usb_raw_device_added, 571 &usb_raw_device_removed 572 }; 573 574 gDeviceList = NULL; 575 gDeviceCount = 0; 576 status_t result = benaphore_init(&gDeviceListLock, "usb_raw device list lock"); 577 if (result < B_OK) { 578 TRACE((DRIVER_NAME": failed to create device list lock\n")); 579 return result; 580 } 581 582 TRACE((DRIVER_NAME": trying module %s\n", B_USB_MODULE_NAME)); 583 result = get_module(B_USB_MODULE_NAME, (module_info **)&gUSBModule); 584 if (result < B_OK) { 585 TRACE((DRIVER_NAME": getting module failed 0x%08lx\n", result)); 586 return result; 587 } 588 589 gUSBModule->register_driver(DRIVER_NAME, NULL, 0, NULL); 590 gUSBModule->install_notify(DRIVER_NAME, ¬ifyHooks); 591 return B_OK; 592 } 593 594 595 void 596 uninit_driver() 597 { 598 TRACE((DRIVER_NAME": uninit_driver()\n")); 599 gUSBModule->uninstall_notify(DRIVER_NAME); 600 benaphore_lock(&gDeviceListLock); 601 602 if (gDeviceNames) { 603 for (int32 i = 1; gDeviceNames[i]; i++) 604 free(gDeviceNames[i]); 605 free(gDeviceNames); 606 } 607 608 benaphore_destroy(&gDeviceListLock); 609 put_module(B_USB_MODULE_NAME); 610 } 611 612 613 const char ** 614 publish_devices() 615 { 616 TRACE((DRIVER_NAME": publish_devices()\n")); 617 if (gDeviceNames) { 618 for (int32 i = 1; gDeviceNames[i]; i++) 619 free(gDeviceNames[i]); 620 free(gDeviceNames); 621 } 622 623 int32 index = 0; 624 gDeviceNames = (char **)malloc(sizeof(char *) * (gDeviceCount + 2)); 625 gDeviceNames[index++] = DEVICE_NAME; 626 627 benaphore_lock(&gDeviceListLock); 628 raw_device *element = gDeviceList; 629 while (element) { 630 gDeviceNames[index++] = strdup(element->name); 631 element = (raw_device *)element->link; 632 } 633 634 gDeviceNames[index++] = NULL; 635 benaphore_unlock(&gDeviceListLock); 636 return (const char **)gDeviceNames; 637 } 638 639 640 device_hooks * 641 find_device(const char *name) 642 { 643 TRACE((DRIVER_NAME": find_device()\n")); 644 static device_hooks hooks = { 645 &usb_raw_open, 646 &usb_raw_close, 647 &usb_raw_free, 648 &usb_raw_ioctl, 649 &usb_raw_read, 650 &usb_raw_write, 651 NULL, 652 NULL, 653 NULL, 654 NULL 655 }; 656 657 return &hooks; 658 } 659