1 /* 2 * Copyright 2005-2008, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 * 8 * Portions of this code are based on Be Sample Code released under the 9 * Be Sample Code license. (USB sound device driver sample code IIRC.) 10 */ 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 16 #include <Drivers.h> 17 #include <KernelExport.h> 18 #include <OS.h> 19 #include <USB3.h> 20 21 int32 api_version = B_CUR_DRIVER_API_VERSION; 22 23 #define DEBUG_DRIVER 0 24 25 #if DEBUG_DRIVER 26 # define DPRINTF_INFO(x) dprintf x; 27 # define DPRINTF_ERR(x) dprintf x; 28 #else 29 # define DPRINTF_INFO(x) 30 # define DPRINTF_ERR(x) dprintf x; 31 #endif 32 33 typedef struct wacom_device wacom_device; 34 35 struct wacom_device { 36 wacom_device* next; 37 38 int open; 39 int number; 40 41 usb_device dev; 42 43 usb_pipe pipe; 44 char* data; 45 size_t max_packet_size; 46 size_t length; 47 48 uint16 vendor; 49 uint16 product; 50 51 sem_id notify_lock; 52 uint32 status; 53 }; 54 55 // handy strings for referring to ourself 56 #define ID "wacom: " 57 static const char* kDriverName = "wacom"; 58 static const char* kBasePublishPath = "input/wacom/usb/"; 59 60 // list of device instances and names for publishing 61 static wacom_device* sDeviceList = NULL; 62 static sem_id sDeviceListLock = -1; 63 static int sDeviceCount = 0; 64 65 static char** sDeviceNames = NULL; 66 67 // handle for the USB bus manager 68 static usb_module_info* usb; 69 70 // These rather inelegant routines are used to assign numbers to 71 // device instances so that they have unique names in devfs. 72 73 static uint32 sDeviceNumbers = 0; 74 75 // get_number 76 static int 77 get_number() 78 { 79 int num; 80 81 for (num = 0; num < 32; num++) { 82 if (!(sDeviceNumbers & (1 << num))) { 83 sDeviceNumbers |= (1 << num); 84 return num; 85 } 86 } 87 88 return -1; 89 } 90 91 // put_number 92 static void 93 put_number(int num) 94 { 95 sDeviceNumbers &= ~(1 << num); 96 } 97 98 // #pragma mark - Device addition and removal 99 // 100 // add_device() and remove_device() are used to create and tear down 101 // device instances. They are used from the callbacks device_added() 102 // and device_removed() which are invoked by the USB bus manager. 103 104 // add_device 105 static wacom_device* 106 add_device(usb_device dev) 107 { 108 wacom_device *device = NULL; 109 int num, ifc, alt; 110 const usb_interface_info *ii; 111 status_t st; 112 const usb_device_descriptor* udd; 113 const usb_configuration_info *conf; 114 bool setConfiguration = false; 115 116 // we need these four for a Wacom tablet 117 size_t controlTransferLength; 118 int tryCount; 119 char repData[2] = { 0x02, 0x02 }; 120 char retData[2] = { 0x00, 0x00 }; 121 122 conf = usb->get_configuration(dev); 123 DPRINTF_INFO((ID "add_device(%ld, %p)\n", dev, conf)); 124 125 if ((num = get_number()) < 0) 126 return NULL; 127 128 udd = usb->get_device_descriptor(dev); 129 // only pick up wacom tablets 130 if (udd && udd->vendor_id == 0x056a) { 131 132 DPRINTF_ERR((ID "add_device() - wacom detected\n")); 133 134 // see if the device has been configured already 135 if (!conf) { 136 conf = usb->get_nth_configuration(dev, 0); 137 setConfiguration = true; 138 } 139 140 if (!conf) 141 goto fail; 142 143 for (ifc = 0; ifc < conf->interface_count; ifc++) { 144 DPRINTF_INFO((ID "add_device() - examining interface: %d\n", ifc)); 145 for (alt = 0; alt < conf->interface[ifc].alt_count; alt++) { 146 ii = &conf->interface[ifc].alt[alt]; 147 DPRINTF_INFO((ID "add_device() - examining alt interface: " 148 "%d\n", alt)); 149 150 151 // does it have the correct type of interface? 152 if (ii->descr->interface_class != 3) continue; 153 if (ii->descr->interface_subclass != 1) continue; 154 if (ii->endpoint_count != 1) continue; 155 156 // only accept input endpoints 157 if (ii->endpoint[0].descr->endpoint_address & 0x80) { 158 DPRINTF_INFO((ID "add_device() - found input endpoint\n")); 159 goto got_one; 160 } 161 } 162 } 163 } else 164 goto fail; 165 166 fail: 167 put_number(num); 168 if (device) { 169 free(device->data); 170 free(device); 171 } 172 return NULL; 173 174 got_one: 175 if ((device = (wacom_device *) malloc(sizeof(wacom_device))) == NULL) 176 goto fail; 177 178 device->dev = dev; 179 device->number = num; 180 device->open = 1; 181 device->notify_lock = -1; 182 device->data = NULL; 183 184 // if (setConfiguration) { 185 // the configuration has to be set yet (was not the current one) 186 DPRINTF_INFO((ID "add_device() - setting configuration...\n")); 187 if ((st = usb->set_configuration(dev, conf)) != B_OK) { 188 dprintf(ID "add_device() -> " 189 "set_configuration() returns %" B_PRId32 "\n", st); 190 goto fail; 191 } else 192 DPRINTF_ERR((ID " ... success!\n")); 193 194 if (conf->interface[ifc].active != ii) { 195 // the interface we found is not the active one and has to be set 196 DPRINTF_INFO((ID "add_device() - setting interface: %p...\n", ii)); 197 if ((st = usb->set_alt_interface(dev, ii)) != B_OK) { 198 dprintf(ID "add_device() -> " 199 "set_alt_interface() returns %" B_PRId32 "\n", st); 200 goto fail; 201 } else 202 DPRINTF_ERR((ID " ... success!\n")); 203 } 204 // see if the device is a Wacom tablet and needs some special treatment 205 // let's hope Wacom doesn't produce normal mice any time soon, or this 206 // check will have to be more specific about product_id...hehe 207 if (udd->vendor_id == 0x056a) { 208 // do the control transfers to set up absolute mode (default is HID 209 // mode) 210 211 // see 'Device Class Definition for HID 1.11' (HID1_11.pdf), 212 // par. 7.2 (available at www.usb.org/developers/hidpage) 213 214 // set protocol mode to 'report' (instead of 'boot') 215 controlTransferLength = 0; 216 // HID Class-Specific Request, Host to device (=0x21): 217 // SET_PROTOCOL (=0x0b) to Report Protocol (=1) 218 // of Interface #0 (=0) 219 st = usb->send_request(dev, 0x21, 0x0b, 1, 0, 0, 0, 220 &controlTransferLength); 221 222 if (st < B_OK) { 223 dprintf(ID "add_device() - " 224 "control transfer 1 failed: %" B_PRId32 "\n", st); 225 } 226 227 // try up to five times to set the tablet to 'Wacom'-mode (enabling 228 // absolute mode, pressure data, etc.) 229 controlTransferLength = 2; 230 231 for (tryCount = 0; tryCount < 5; tryCount++) { 232 // HID Class-Specific Request, Host to device (=0x21): 233 // SET_REPORT (=0x09) type Feature (=3) with ID 2 (=2) of 234 // Interface #0 (=0) to repData (== { 0x02, 0x02 }) 235 st = usb->send_request(dev, 0x21, 0x09, (3 << 8) + 2, 0, 2, 236 repData, &controlTransferLength); 237 238 if (st < B_OK) { 239 dprintf(ID "add_device() - " 240 "control transfer 2 failed: %" B_PRId32 "\n", st); 241 } 242 243 // check if registers are set correctly 244 245 // HID Class-Specific Request, Device to host (=0xA1): 246 // GET_REPORT (=0x01) type Feature (=3) with ID 2 (=2) of 247 // Interface #0 (=0) to retData 248 st = usb->send_request(dev, 0xA1, 0x01, (3 << 8) + 2, 0, 2, 249 retData, &controlTransferLength); 250 251 if (st < B_OK) { 252 dprintf(ID "add_device() - " 253 "control transfer 3 failed: %" B_PRId32 "\n", st); 254 } 255 256 DPRINTF_INFO((ID "add_device() - retData: %u - %u\n", 257 retData[0], retData[1])); 258 259 if (retData[0] == repData[0] && retData[1] == repData[1]) { 260 DPRINTF_INFO((ID "add_device() - successfully set " 261 "'Wacom'-mode\n")); 262 break; 263 } 264 } 265 266 DPRINTF_INFO((ID "add_device() - number of tries: %u\n", 267 tryCount + 1)); 268 269 if (tryCount > 4) { 270 dprintf(ID "add_device() - set 'Wacom'-mode failed\n"); 271 } 272 } 273 // } 274 275 // configure the rest of the wacom_device 276 device->pipe = ii->endpoint[0].handle; 277 //DPRINTF_INFO((ID "add_device() - pipe id = %ld\n", device->pipe)); 278 device->length = 0; 279 device->max_packet_size = ii->endpoint[0].descr->max_packet_size; 280 device->data = (char*)malloc(device->max_packet_size); 281 if (device->data == NULL) 282 goto fail; 283 //DPRINTF_INFO((ID "add_device() - max packet length = %ld\n", 284 // device->max_packet_size)); 285 device->status = 0;//B_USB_STATUS_SUCCESS; 286 device->vendor = udd->vendor_id; 287 device->product = udd->product_id; 288 289 DPRINTF_INFO((ID "add_device() - added %p (/dev/%s%d)\n", device, 290 kBasePublishPath, num)); 291 292 // add it to the list of devices so it will be published, etc 293 acquire_sem(sDeviceListLock); 294 device->next = sDeviceList; 295 sDeviceList = device; 296 sDeviceCount++; 297 release_sem(sDeviceListLock); 298 299 return device; 300 } 301 302 // remove_device 303 static void 304 remove_device(wacom_device *device) 305 { 306 put_number(device->number); 307 308 usb->cancel_queued_transfers(device->pipe); 309 310 delete_sem(device->notify_lock); 311 if (device->data) 312 free(device->data); 313 free(device); 314 } 315 316 // device_added 317 static status_t 318 device_added(usb_device dev, void** cookie) 319 { 320 wacom_device* device; 321 322 DPRINTF_INFO((ID "device_added(%ld,...)\n", dev)); 323 324 // first see, if this device is already added 325 acquire_sem(sDeviceListLock); 326 for (device = sDeviceList; device; device = device->next) { 327 DPRINTF_ERR((ID "device_added() - old device: %" B_PRIu32 "\n", 328 device->dev)); 329 if (device->dev == dev) { 330 DPRINTF_ERR((ID "device_added() - already added - done!\n")); 331 *cookie = (void*)device; 332 release_sem(sDeviceListLock); 333 return B_OK; 334 } 335 } 336 release_sem(sDeviceListLock); 337 338 if ((device = add_device(dev)) != NULL) { 339 *cookie = (void*)device; 340 DPRINTF_INFO((ID "device_added() - done!\n")); 341 return B_OK; 342 } else 343 DPRINTF_INFO((ID "device_added() - failed to add device!\n")); 344 345 return B_ERROR; 346 } 347 348 // device_removed 349 static status_t 350 device_removed(void *cookie) 351 { 352 wacom_device *device = (wacom_device *) cookie; 353 354 DPRINTF_INFO((ID "device_removed(%p)\n", device)); 355 356 if (device) { 357 358 acquire_sem(sDeviceListLock); 359 360 // remove it from the list of devices 361 if (device == sDeviceList) { 362 sDeviceList = device->next; 363 } else { 364 wacom_device *n; 365 for (n = sDeviceList; n; n = n->next) { 366 if (n->next == device) { 367 n->next = device->next; 368 break; 369 } 370 } 371 } 372 sDeviceCount--; 373 374 // tear it down if it's not open -- 375 // otherwise the last device_free() will handle it 376 377 device->open--; 378 379 DPRINTF_ERR((ID "device_removed() open: %d\n", device->open)); 380 381 if (device->open == 0) { 382 remove_device(device); 383 } else { 384 dprintf(ID "device /dev/%s%d still open -- marked for removal\n", 385 kBasePublishPath, device->number); 386 } 387 388 release_sem(sDeviceListLock); 389 } 390 391 return B_OK; 392 } 393 394 // #pragma mark - Device Hooks 395 // 396 // Here we implement the posixy driver hooks (open/close/read/write/ioctl) 397 398 // device_open 399 static status_t 400 device_open(const char *dname, uint32 flags, void** cookie) 401 { 402 wacom_device *device; 403 int n; 404 status_t ret = B_ERROR; 405 406 n = atoi(dname + strlen(kBasePublishPath)); 407 408 DPRINTF_INFO((ID "device_open(\"%s\",%d,...)\n", dname, flags)); 409 410 acquire_sem(sDeviceListLock); 411 for (device = sDeviceList; device; device = device->next) { 412 if (device->number == n) { 413 // if (device->open <= 1) { 414 device->open++; 415 *cookie = device; 416 DPRINTF_ERR((ID "device_open() open: %d\n", device->open)); 417 418 if (device->notify_lock < 0) { 419 device->notify_lock = create_sem(0, "notify_lock"); 420 if (device->notify_lock < 0) { 421 ret = device->notify_lock; 422 device->open--; 423 *cookie = NULL; 424 dprintf(ID "device_open() -> " 425 "create_sem() returns %" B_PRId32 "\n", ret); 426 } else { 427 ret = B_OK; 428 } 429 } 430 release_sem(sDeviceListLock); 431 return ret; 432 // } else { 433 // dprintf(ID "device_open() -> device is already open %ld\n", ret); 434 // release_sem(sDeviceListLock); 435 // return B_ERROR; 436 // } 437 } 438 } 439 release_sem(sDeviceListLock); 440 return ret; 441 } 442 443 // device_close 444 static status_t 445 device_close (void *cookie) 446 { 447 #if DEBUG_DRIVER 448 wacom_device *device = (wacom_device*) cookie; 449 DPRINTF_ERR((ID "device_close() name = \"%s%d\"\n", kBasePublishPath, 450 device->number)); 451 #endif 452 return B_OK; 453 } 454 455 // device_free 456 static status_t 457 device_free(void *cookie) 458 { 459 wacom_device *device = (wacom_device *)cookie; 460 461 DPRINTF_INFO((ID "device_free() name = \"%s%d\"\n", kBasePublishPath, 462 device->number)); 463 464 acquire_sem(sDeviceListLock); 465 466 device->open--; 467 468 DPRINTF_INFO((ID "device_free() open: %ld\n", device->open)); 469 470 if (device->open == 0) { 471 remove_device(device); 472 } 473 release_sem(sDeviceListLock); 474 475 return B_OK; 476 } 477 478 // device_interupt_callback 479 static void 480 device_interupt_callback(void* cookie, status_t status, void* data, 481 uint32 actualLength) 482 { 483 wacom_device* device = (wacom_device*)cookie; 484 uint32 length = min_c(actualLength, device->max_packet_size); 485 486 DPRINTF_INFO((ID "device_interupt_callback(%p) name = \"%s%d\" -> " 487 "status: %ld, length: %ld\n", cookie, kBasePublishPath, device->number, 488 status, actualLength)); 489 490 device->status = status; 491 if (device->notify_lock >= 0) { 492 if (status == B_OK) { 493 memcpy(device->data, data, length); 494 device->length = length; 495 } else { 496 device->length = 0; 497 } 498 release_sem(device->notify_lock); 499 } 500 501 DPRINTF_INFO((ID "device_interupt_callback() - done\n")); 502 } 503 504 // read_header 505 static void 506 read_header(const wacom_device* device, void* buffer) 507 { 508 uint16* ids = (uint16*)buffer; 509 uint32* size = (uint32*)buffer; 510 511 ids[0] = device->vendor; 512 ids[1] = device->product; 513 size[1] = device->max_packet_size; 514 } 515 516 // device_read 517 static status_t 518 device_read(void* cookie, off_t pos, void* buf, size_t* count) 519 { 520 wacom_device* device = (wacom_device*) cookie; 521 status_t ret = B_BAD_VALUE; 522 uint8* buffer = (uint8*)buf; 523 uint32 dataLength; 524 525 if (!device) 526 return ret; 527 528 ret = device->notify_lock; 529 530 DPRINTF_INFO((ID "device_read(%p,%Ld,0x%x,%d) name = \"%s%d\"\n", 531 cookie, pos, buf, *count, kBasePublishPath, device->number)); 532 533 if (ret >= B_OK) { 534 // what the client "reads" is decided depending on how much bytes are 535 // provided 8 bytes are needed to "read" vendor id, product id and max 536 // packet size in case the client wants to read more than 8 bytes, a usb 537 // interupt transfer is scheduled, and an error report is returned as 538 // appropriate 539 if (*count > 8) { 540 // queue the interrupt transfer 541 ret = usb->queue_interrupt(device->pipe, device->data, 542 device->max_packet_size, device_interupt_callback, device); 543 if (ret >= B_OK) { 544 // we will block here until the interrupt transfer has been done 545 ret = acquire_sem_etc(device->notify_lock, 1, 546 B_RELATIVE_TIMEOUT, 500 * 1000); 547 // handle time out 548 if (ret < B_OK) { 549 usb->cancel_queued_transfers(device->pipe); 550 acquire_sem(device->notify_lock); 551 // collect the sem released by the cancel 552 553 if (ret == B_TIMED_OUT) { 554 // a time_out is ok, since it only means that the device 555 // had nothing to report (ie mouse/pen was not moved) 556 // within the given time interval 557 DPRINTF_INFO((ID "device_read(%p) name = \"%s%d\" -> " 558 "B_TIMED_OUT\n", cookie, kBasePublishPath, 559 device->number)); 560 *count = 8; 561 read_header(device, buffer); 562 ret = B_OK; 563 } else { 564 // any other error trying to acquire the semaphore 565 *count = 0; 566 } 567 } else { 568 if (device->status == 0/*B_USBD_SUCCESS*/) { 569 DPRINTF_INFO((ID "interrupt transfer - success\n")); 570 // copy the data from the buffer 571 dataLength = min_c(device->length, *count - 8); 572 *count = dataLength + 8; 573 read_header(device, buffer); 574 memcpy(buffer + 8, device->data, dataLength); 575 } else { 576 // an error happened during the interrupt transfer 577 *count = 0; 578 dprintf(ID "interrupt transfer - " 579 "failure: %" B_PRIu32 "\n", device->status); 580 ret = B_ERROR; 581 } 582 } 583 } else { 584 *count = 0; 585 dprintf(ID "device_read(%p) name = \"%s%d\" -> error queuing " 586 "interrupt: %" B_PRId32 "\n", cookie, kBasePublishPath, 587 device->number, ret); 588 } 589 } else if (*count == 8) { 590 read_header(device, buffer); 591 ret = B_OK; 592 } else { 593 dprintf(ID "device_read(%p) name = \"%s%d\" -> buffer size must be " 594 "at least 8 bytes!\n", cookie, kBasePublishPath, 595 device->number); 596 *count = 0; 597 ret = B_BAD_VALUE; 598 } 599 } 600 601 return ret; 602 } 603 604 // device_write 605 static status_t 606 device_write(void *cookie, off_t pos, const void *buf, size_t *count) 607 { 608 return B_ERROR; 609 } 610 611 // device_control 612 static status_t 613 device_control (void *cookie, uint32 msg, void *arg1, size_t len) 614 { 615 return B_ERROR; 616 } 617 618 // #pragma mark - Driver Hooks 619 // 620 // These functions provide the glue used by DevFS to load/unload 621 // the driver and also handle registering with the USB bus manager 622 // to receive device added and removed events 623 624 static usb_notify_hooks notify_hooks = 625 { 626 &device_added, 627 &device_removed 628 }; 629 630 static const usb_support_descriptor kSupportedDevices[] = 631 { 632 { 3, 1, 2, 0, 0 } 633 }; 634 635 // init_hardware 636 status_t 637 init_hardware(void) 638 { 639 return B_OK; 640 } 641 642 // init_driver 643 status_t 644 init_driver(void) 645 { 646 DPRINTF_INFO((ID "init_driver(), built %s %s\n", __DATE__, __TIME__)); 647 648 #if DEBUG_DRIVER && !defined(__HAIKU__) 649 if (load_driver_symbols(kDriverName) == B_OK) { 650 DPRINTF_INFO((ID "loaded symbols\n")); 651 } else { 652 DPRINTF_ERR((ID "no driver symbols loaded!\n")); 653 } 654 #endif 655 656 if (get_module(B_USB_MODULE_NAME, (module_info**) &usb) != B_OK) { 657 DPRINTF_ERR((ID "cannot get module \"%s\"\n", B_USB_MODULE_NAME)); 658 return B_ERROR; 659 } 660 661 if ((sDeviceListLock = create_sem(1,"sDeviceListLock")) < 0) { 662 put_module(B_USB_MODULE_NAME); 663 return sDeviceListLock; 664 } 665 666 usb->register_driver(kDriverName, kSupportedDevices, 1, NULL); 667 usb->install_notify(kDriverName, ¬ify_hooks); 668 669 return B_OK; 670 } 671 672 // uninit_driver 673 void 674 uninit_driver(void) 675 { 676 int i; 677 678 DPRINTF_INFO((ID "uninit_driver()\n")); 679 680 usb->uninstall_notify(kDriverName); 681 682 delete_sem(sDeviceListLock); 683 684 put_module(B_USB_MODULE_NAME); 685 686 if (sDeviceNames) { 687 for (i = 0; sDeviceNames[i]; i++) 688 free(sDeviceNames[i]); 689 free(sDeviceNames); 690 } 691 692 DPRINTF_INFO((ID "uninit_driver() done\n")); 693 } 694 695 // publish_devices 696 const char** 697 publish_devices() 698 { 699 wacom_device *device; 700 int i; 701 702 DPRINTF_INFO((ID "publish_devices()\n")); 703 704 if (sDeviceNames) { 705 for (i = 0; sDeviceNames[i]; i++) 706 free((char *) sDeviceNames[i]); 707 free(sDeviceNames); 708 } 709 710 acquire_sem(sDeviceListLock); 711 sDeviceNames = (char**)malloc(sizeof(char*) * (sDeviceCount + 2)); 712 if (sDeviceNames) { 713 for (i = 0, device = sDeviceList; device; device = device->next) { 714 sDeviceNames[i] = (char*)malloc(strlen(kBasePublishPath) + 4); 715 if (sDeviceNames[i]) { 716 sprintf(sDeviceNames[i],"%s%d",kBasePublishPath,device->number); 717 DPRINTF_INFO((ID "publishing: \"/dev/%s\"\n",sDeviceNames[i])); 718 i++; 719 } 720 } 721 sDeviceNames[i] = NULL; 722 } 723 724 release_sem(sDeviceListLock); 725 726 return (const char**)sDeviceNames; 727 } 728 729 static device_hooks sDeviceHooks = { 730 device_open, 731 device_close, 732 device_free, 733 device_control, 734 device_read, 735 device_write 736 }; 737 738 // find_device 739 device_hooks* 740 find_device(const char* name) 741 { 742 return &sDeviceHooks; 743 } 744