1 /* 2 * Copyright 2003-2008 Stephan Aßmus <superstippi@gmx.de>. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Copyright 2000-2002 Olaf van Es. All Rights Reserved. 6 * Distributed under the terms of the MIT license. 7 * 8 * These people have added and tested device ids: 9 * 10 * Frans van Nispen <frans@xentronix.com> 11 * Stefan Werner <stefan@keindesign.de> 12 * Hiroyuki Tsutsumi <???> 13 * Jeroen Oortwijn <oortwijn@gmail.com> 14 */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 20 #include <File.h> 21 #include <InterfaceDefs.h> 22 #include <Screen.h> 23 #include <View.h> 24 25 #include "DeviceReader.h" 26 #include "MasterServerDevice.h" 27 28 #include "TabletDevice.h" 29 30 #define SNOOZE_AMOUNT 2500 31 #define JITTER_X .0007 32 #define JITTER_Y .0007 33 #define ACCELERATION_KICK_IN 2.3 34 35 // constructor 36 TabletDevice::TabletDevice(MasterServerDevice* parent, DeviceReader* reader) 37 : PointingDevice(parent, reader), 38 fThreadID(B_ERROR), 39 fDeviceMode(DEVICE_UNKOWN), 40 fMaxX(1.0), 41 fMaxY(1.0), 42 fPosX(0.5), 43 fPosY(0.5), 44 fFakeMouseX(0.5), 45 fFakeMouseY(0.5), 46 fButtons(0), 47 fPressure(0.0), 48 fModifiers(0), 49 fEraser(0), 50 fTiltX(0.0), 51 fTiltY(0.0), 52 fClicks(0), 53 fHasContact(false) 54 { 55 } 56 57 // destructor 58 TabletDevice::~TabletDevice() 59 { 60 // cleanup 61 Stop(); 62 } 63 64 // InitCheck 65 status_t 66 TabletDevice::InitCheck() 67 { 68 status_t status = PointingDevice::InitCheck(); 69 if (status >= B_OK) 70 status = DetectDevice(fReader); 71 return status; 72 } 73 74 // Start 75 status_t 76 TabletDevice::Start() 77 { 78 status_t status = B_NO_INIT; 79 if (fReader) { 80 fActive = true; 81 // get a nice name for our polling thread 82 const char* name; 83 _GetName(fReader->ProductID(), &name); 84 // start generating events 85 fThreadID = spawn_thread(poll_usb_device, name, 104, this); 86 if (fThreadID >= B_OK) { 87 resume_thread(fThreadID); 88 status = B_OK; 89 } else 90 status = fThreadID; 91 } 92 return status; 93 } 94 95 // Stop 96 status_t 97 TabletDevice::Stop() 98 { 99 status_t err = B_OK; 100 101 fActive = false; 102 if (fThreadID >= B_OK) 103 wait_for_thread(fThreadID, &err); 104 fThreadID = B_ERROR; 105 106 return err; 107 } 108 109 // DetectDevice 110 status_t 111 TabletDevice::DetectDevice(const DeviceReader* reader) 112 { 113 status_t status = B_OK; 114 switch (reader->ProductID()) { 115 case 0x00: 116 SetDevice(5040.0, 3780.0, DEVICE_PENPARTNER); 117 break; 118 case 0x03: 119 SetDevice(2048.0, 15360.0, DEVICE_PL500); 120 break; 121 case 0x10: 122 case 0x11: 123 case 0x13: 124 SetDevice(10206.0, 7422.0, DEVICE_GRAPHIRE); 125 break; 126 case 0x12: // Graphire 3 4x5 127 SetDevice(13918.0, 10206.0, DEVICE_GRAPHIRE); 128 break; 129 case 0x14: // Graphire 3 6x8 130 SetDevice(16704.0, 12064.0, DEVICE_GRAPHIRE); 131 break; 132 case 0x15: // Graphire 4 4x5 (tested) 133 SetDevice(10208.0, 7024.0, DEVICE_GRAPHIRE); 134 break; 135 case 0x16: // Graphire 4 6x8 (tested) 136 SetDevice(16704.0, 12064.0, DEVICE_GRAPHIRE); 137 break; 138 case 0x17: // BambooFun 4x5 (from Linux Wacom Project) 139 SetDevice(14760.0, 9225.0, DEVICE_BAMBOO); 140 break; 141 case 0x18: // BambooFun 6x8 (from Linux Wacom Project) 142 SetDevice(21648.0, 13530.0, DEVICE_BAMBOO); 143 break; 144 case 0x20: 145 SetDevice(12700.0, 10600.0, DEVICE_INTUOS); 146 break; 147 case 0x21: 148 SetDevice(20320.0, 16240.0); 149 break; 150 case 0x22: 151 SetDevice(30480.0, 24060.0); 152 break; 153 case 0x23: 154 SetDevice(30480.0, 31680.0); 155 break; 156 case 0x24: 157 SetDevice(45720.0, 31680.0); 158 break; 159 case 0x30: 160 SetDevice(5408.0, 4056.0, DEVICE_PL500); 161 break; 162 case 0x31: 163 SetDevice(6144.0, 4608.0, DEVICE_PL500); 164 break; 165 case 0x32: 166 SetDevice(6126.0, 4604.0, DEVICE_PL500); 167 break; 168 case 0x33: 169 SetDevice(6260.0, 5016.0, DEVICE_PL500); 170 break; 171 case 0x34: 172 SetDevice(6144.0, 4608.0, DEVICE_PL500); 173 break; 174 case 0x35: 175 SetDevice(7220.0, 5780.0, DEVICE_PL500); 176 break; 177 case 0x3F: 178 SetDevice(87200.0, 65600.0, DEVICE_CINTIQ); 179 break; 180 case 0x41: 181 SetDevice(12700.0, 10600.0); 182 break; 183 case 0x42: 184 SetDevice(20320.0, 16240.0); 185 break; 186 case 0x43: 187 SetDevice(30480.0, 24060.0); 188 break; 189 case 0x44: 190 SetDevice(30480.0, 31680.0); 191 break; 192 case 0x45: 193 SetDevice(45720.0, 31680.0); 194 break; 195 case 0x47: // some I2 6x8 report as 0x47 196 SetDevice(20320.0, 16240.0); 197 break; 198 case 0x60: 199 SetDevice(5104.0, 3712.0, DEVICE_GRAPHIRE); 200 break; 201 case 0x61: // PenStation 202 // SetDevice(3403.0, 2475.0, DEVICE_GRAPHIRE); // this version was untested 203 SetDevice(3248.0, 2320.0, DEVICE_PENSTATION); // this version came from "beer" 204 break; 205 case 0x62: // Volito 206 SetDevice(5040.0, 3712.0, DEVICE_VOLITO); 207 break; 208 case 0x64: // PenPartner.1 209 // SetDevice(3450.0, 2100.0, DEVICE_PENSTATION); 210 SetDevice(3248.0, 2320.0, DEVICE_PENSTATION); 211 break; 212 case 0x65: // Bamboo (from Linux Wacom Project) 213 SetDevice(14760.0, 9225.0, DEVICE_BAMBOO); 214 break; 215 case 0x69: // Bamboo1 (from Linux Wacom Project) 216 SetDevice(5104.0, 3712.0, DEVICE_BAMBOO); 217 break; 218 case 0xB0: 219 SetDevice(25400.0, 20320.0, DEVICE_INTUOS3); 220 break; 221 case 0xB1: 222 SetDevice(40640.0, 30480.0, DEVICE_INTUOS3); 223 break; 224 case 0xB2: 225 SetDevice(60960.0, 45720.0, DEVICE_INTUOS3); 226 break; 227 case 0xD0: // Wacom Bamboo 2FG (from Linux Wacom Project) 228 SetDevice(14720.0, 9200.0, DEVICE_BAMBOO_PT); 229 break; 230 case 0xD1: // Wacom BambooFun 2FG 4x5 (from Linux Wacom Project) 231 SetDevice(14720.0, 9200.0, DEVICE_BAMBOO_PT); 232 break; 233 case 0xD2: // Wacom Bamboo Craft (from Linux Wacom Project) 234 SetDevice(14720.0, 9200.0, DEVICE_BAMBOO_PT); 235 break; 236 case 0xD3: // Wacom BambooFun 2FG 6x8 (from Linux Wacom Project) 237 SetDevice(21648.0, 13530.0, DEVICE_BAMBOO_PT); 238 break; 239 case 0xD4: // Wacom Bamboo 4x5 (from Linux Wacom Project) 240 SetDevice(14720.0, 9200.0, DEVICE_BAMBOO_PT); 241 break; 242 case 0xD6: // Wacom Bamboo CTH-460/K (from Linux Wacom Project) 243 SetDevice(14720.0, 9200.0, DEVICE_BAMBOO_PT); 244 break; 245 case 0xD7: // Wacom Bamboo CTH-461/S (from Linux Wacom Project) 246 SetDevice(14720.0, 9200.0, DEVICE_BAMBOO_PT); 247 break; 248 case 0xD8: // Wacom Bamboo CTH-661/S1 (from Linux Wacom Project) 249 SetDevice(21648.0, 13530.0, DEVICE_BAMBOO_PT); 250 break; 251 case 0xDA: // Wacom Bamboo CTH-461/L (from Linux Wacom Project) 252 SetDevice(14720.0, 9200.0, DEVICE_BAMBOO_PT); 253 break; 254 case 0xDB: // Wacom Bamboo CTH-661 (from Linux Wacom Project) 255 SetDevice(21648.0, 13530.0, DEVICE_BAMBOO_PT); 256 break; 257 default: 258 status = B_BAD_VALUE; 259 break; 260 } 261 return status; 262 } 263 264 // SetDevice 265 void 266 TabletDevice::SetDevice(float maxX, float maxY, uint32 mode) 267 { 268 fDeviceMode = mode; 269 fMaxX = maxX; 270 fMaxY = maxY; 271 fJitterX = JITTER_X; 272 fJitterY = JITTER_Y; 273 } 274 275 // ReadData 276 void 277 TabletDevice::ReadData(const uchar* data, int dataBytes, bool& hasContact, 278 uint32& mode, uint32& buttons, float& x, float& y, float& pressure, 279 int32& clicks, int32& eraser, float& wheelX, float& wheelY, 280 float& tiltX, float& tiltY) const 281 { 282 hasContact = false; 283 buttons = 0; 284 mode = MODE_PEN; 285 bool firstButton = false; 286 bool secondButton = false; 287 bool thirdButton = false; 288 uint16 xPos = 0; 289 uint16 yPos = 0; 290 291 switch (fDeviceMode) { 292 case DEVICE_PENPARTNER: { 293 xPos = data[2] << 8 | data[1]; 294 yPos = data[4] << 8 | data[3]; 295 296 eraser = (data[5] & 0x20); 297 298 int8 pressureData = data[6]; 299 pressure = (float)(pressureData + 120) / 240.0; 300 301 firstButton = ((pressureData > -80) && !(data[5] & 0x20)); 302 secondButton = (data[5] & 0x40); 303 304 hasContact = true; 305 break; 306 } 307 case DEVICE_GRAPHIRE: 308 case DEVICE_BAMBOO: 309 { 310 xPos = data[3] << 8 | data[2]; 311 yPos = data[5] << 8 | data[4]; 312 313 hasContact = (data[1] & 0x80); 314 315 uint16 pressureData = data[7] << 8 | data[6]; 316 pressure = (float)pressureData / 511.0; 317 eraser = (data[1] & 0x20); 318 319 // mouse wheel support 320 if (data[1] & 0x40) { // mouse is on tablet! 321 wheelY = (float)(int8)data[6]; 322 mode = MODE_MOUSE; 323 // override contact to loose it as soon as possible 324 // when mouse is lifted from tablet 325 hasContact = (uint8)data[7] >= 30; 326 pressure = 0.0; 327 eraser = 0; 328 } 329 330 firstButton = pressure > 0.0 ? true : (data[1] & 0x01); 331 secondButton = (data[1] & 0x02); 332 thirdButton = (data[1] & 0x04); 333 334 break; 335 } 336 case DEVICE_BAMBOO_PT: 337 { 338 if (dataBytes < 20) { // ignore touch-packets 339 xPos = data[3] << 8 | data[2]; 340 yPos = data[5] << 8 | data[4]; 341 342 hasContact = (data[1] & 0x20); 343 344 uint16 pressureData = data[7] << 8 | data[6]; 345 pressure = (float)pressureData / 1023.0; 346 eraser = (data[1] & 0x08); 347 348 firstButton = (data[1] & 0x01); 349 secondButton = (data[1] & 0x02); 350 thirdButton = (data[1] & 0x04); 351 352 break; 353 } 354 } 355 case DEVICE_INTUOS: 356 case DEVICE_INTUOS3: 357 case DEVICE_CINTIQ: 358 if ((data[0] == 0x02) && !(((data[1] >> 5) & 0x03) == 0x02)) { 359 if (fDeviceMode == DEVICE_INTUOS3) { 360 xPos = (data[2] << 9) | (data[3] << 1) 361 | ((data[9] >> 1) & 1); 362 yPos = (data[4] << 9) | (data[5] << 1) | (data[9] & 1); 363 } else { 364 xPos = (data[2] << 8) | data[3]; 365 yPos = (data[4] << 8) | data[5]; 366 } 367 uint16 pressureData = data[6] << 2 | ((data[7] >> 6) & 0x03); 368 pressure = (float)pressureData / 1023.0; 369 370 // mouse and wheel support 371 if (data[1] == 0xf0) { // mouse is on tablet! 372 mode = MODE_MOUSE; 373 374 if (data[8] == 0x02) 375 wheelY = 1.0; 376 else if (data[8] == 0x01) 377 wheelY = -1.0; 378 379 firstButton = (data[8] & 0x04); 380 secondButton = (data[8] & 0x10); 381 thirdButton = (data[8] & 0x08); 382 383 // override contact to loose it as soon as possible 384 // when mouse is lifted from tablet 385 hasContact = data[9] <= 0x68; 386 pressure = 0.0; 387 eraser = 0; 388 } else { 389 // eraser = (data[1] & 0x20); // eraser is een tool-id 390 // firstButton = (pressureData > 0) && data[9] <= 0x68;// > 180); 391 // firstButton = (pressureData > 180); 392 firstButton = (data[6] > 0); 393 secondButton = (data[1] & 0x02); 394 thirdButton = (data[1] & 0x04); 395 hasContact = (data[1] & 0x40); 396 // convert tilt (-128 ... 127) 397 // int8 tiltDataX = ((data[7] & 0x3f) << 2) | ((data[8] & 0x80) >> 6); 398 int8 tiltDataX = ((data[7] & 0x3f) << 1) | ((data[8] & 0x80) >> 7); 399 int8 tiltDataY = data[8] & 0x7f; 400 // int8 tiltDataY = 0; 401 // convert to floats 402 tiltX = (float)(tiltDataX - 64) / 64.0; 403 tiltY = (float)(tiltDataY - 64) / 64.0; 404 } 405 } 406 break; 407 case DEVICE_PL500: { 408 hasContact = ( data[1] & 0x20); 409 xPos = data[2] << 8 | data[3]; 410 yPos = data[5] << 8 | data[6]; 411 firstButton = (data[4] & 0x08); 412 secondButton = (data[4] & 0x10); 413 thirdButton = (data[4] & 0x20); 414 uint16 pressureData = (data[4] & 0x04) >> 2 | (data[7] & 0x7f) << 1; 415 pressure = (float)pressureData / 511.0; 416 break; 417 } 418 case DEVICE_VOLITO: { 419 eraser = 0; 420 thirdButton = 0; 421 422 xPos = data[3] << 8 | data[2]; 423 yPos = data[5] << 8 | data[4]; 424 425 hasContact = (data[1] & 0x80); 426 427 firstButton = (data[1] & 0x01) == 1; 428 secondButton = data[1] & 0x04; 429 430 uint16 pressureData = data[7] << 8 | data[6]; 431 pressure = (float)pressureData / 511.0; 432 433 if (data[1] & 0x40) { // mouse is on tablet 434 wheelY = 0; 435 mode = MODE_MOUSE; 436 hasContact = (uint8)data[7] >= 30; 437 pressure = 0.0; 438 secondButton = data[1] & 0x02; 439 } 440 441 break; 442 } 443 case DEVICE_PENSTATION: { 444 xPos = data[3] << 8 | data[2]; 445 yPos = data[5] << 8 | data[4]; 446 hasContact = (data[1] & 0x10); 447 uint16 pressureData = data[7] << 8 | data[6]; 448 pressure = (float)pressureData / 511.0; 449 firstButton = (data[1] & 0x01); 450 secondButton = (data[1] & 0x02); 451 thirdButton = (data[1] & 0x04); 452 break; 453 } 454 } 455 if (pressure > 1.0) 456 pressure = 1.0; 457 else if (pressure < 0.0) 458 pressure = 0.0; 459 buttons = (firstButton ? B_PRIMARY_MOUSE_BUTTON : 0) 460 | (secondButton ? B_SECONDARY_MOUSE_BUTTON : 0) 461 | (thirdButton ? B_TERTIARY_MOUSE_BUTTON : 0); 462 x = (float)xPos; 463 y = (float)yPos; 464 } 465 466 // SetStatus 467 void 468 TabletDevice::SetStatus(uint32 mode, uint32 buttons, float x, float y, 469 float pressure, int32 clicks, uint32 modifiers, int32 eraser, 470 float wheelX, float wheelY, float tiltX, float tiltY, const uchar* data) 471 { 472 if (fActive) { 473 uint32 what = B_MOUSE_MOVED; 474 if (buttons > fButtons) 475 what = B_MOUSE_DOWN; 476 else if (buttons < fButtons) 477 what = B_MOUSE_UP; 478 479 480 #if DEBUG 481 float tabletX = x; 482 float tabletY = y; 483 #endif 484 x /= fMaxX; 485 y /= fMaxY; 486 487 float deltaX = 0.0; 488 float deltaY = 0.0; 489 490 float absDeltaX = 0.0; 491 float absDeltaY = 0.0; 492 493 float unfilteredX = x; 494 float unfilteredY = y; 495 496 if (fHasContact) { 497 deltaX = x - fPosX; 498 deltaY = y - fPosY; 499 500 absDeltaX = fabsf(deltaX); 501 absDeltaY = fabsf(deltaY); 502 503 #if 0 //DEBUG 504 fParent->LogString() << "x: " << x << ", y: " << y << ", pressure: " << pressure << "\n"; 505 fParent->LogString() << "tilt x: " << tiltX << ", tilt y: " << tiltY << "\n\n"; 506 #endif 507 // apply a bit of filtering 508 if (absDeltaX < fJitterX) 509 x = fPosX; 510 if (absDeltaY < fJitterY) 511 y = fPosY; 512 } 513 514 // only do send message if something changed 515 if (x != fPosX || y != fPosY || fButtons != buttons || pressure != fPressure 516 || fEraser != eraser || fTiltX != tiltX || fTiltY != tiltY) { 517 518 bigtime_t now = system_time(); 519 520 // common fields for any mouse message 521 BMessage* event = new BMessage(what); 522 event->AddInt64("when", now); 523 event->AddInt32("buttons", buttons); 524 if (mode == MODE_PEN) { 525 event->AddFloat("x", x); 526 event->AddFloat("y", y); 527 event->AddFloat("be:tablet_x", unfilteredX); 528 event->AddFloat("be:tablet_y", unfilteredY); 529 event->AddFloat("be:tablet_pressure", pressure); 530 event->AddInt32("be:tablet_eraser", eraser); 531 if (_DeviceSupportsTilt()) { 532 event->AddFloat("be:tablet_tilt_x", tiltX); 533 event->AddFloat("be:tablet_tilt_y", tiltY); 534 } 535 // adjust mouse coordinates as well 536 // to have the mouse appear at the pens 537 // last position when switching 538 fFakeMouseX = unfilteredX; 539 fFakeMouseY = unfilteredY; 540 } else if (mode == MODE_MOUSE) { 541 // apply acceleration 542 float accelerationX = fJitterX * ACCELERATION_KICK_IN; 543 // if (absDeltaX > accelerationX) 544 deltaX *= absDeltaX / accelerationX; 545 float accelerationY = fJitterY * ACCELERATION_KICK_IN; 546 // if (absDeltaY > accelerationY) 547 deltaY *= absDeltaY / accelerationY; 548 // calculate screen coordinates 549 fFakeMouseX = min_c(1.0, max_c(0.0, fFakeMouseX + deltaX)); 550 fFakeMouseY = min_c(1.0, max_c(0.0, fFakeMouseY + deltaY)); 551 event->AddFloat("x", fFakeMouseX); 552 event->AddFloat("y", fFakeMouseY); 553 event->AddFloat("be:tablet_x", fFakeMouseX); 554 event->AddFloat("be:tablet_y", fFakeMouseY); 555 } 556 event->AddInt32("modifiers", modifiers); 557 558 #if DEBUG 559 if (data) { 560 event->AddData("raw usb data", B_RAW_TYPE, data, 12); 561 } 562 event->AddFloat("tablet x", tabletX); 563 event->AddFloat("tablet y", tabletY); 564 #endif 565 // additional fields for mouse down or up 566 if (what == B_MOUSE_DOWN) { 567 if (now - fLastClickTime < fParent->DoubleClickSpeed()) { 568 fClicks++; 569 if (fClicks > 3) 570 fClicks = 1; 571 } else { 572 fClicks = 1; 573 } 574 fLastClickTime = now; 575 event->AddInt32("clicks", fClicks); 576 } else if (what == B_MOUSE_UP) 577 event->AddInt32("clicks", 0); 578 579 status_t ret = fParent->EnqueueMessage(event); 580 if (ret < B_OK) 581 PRINT(("EnqueueMessage(): %s\n", strerror(ret))); 582 583 // apply values to members 584 fPosX = x; 585 fPosY = y; 586 fButtons = buttons; 587 fPressure = pressure; 588 fModifiers = modifiers; 589 fEraser = eraser; 590 fTiltX = tiltX; 591 fTiltY = tiltY; 592 } 593 594 // separate wheel changed message 595 if (fWheelX != wheelX || fWheelY != wheelY) { 596 BMessage* event = new BMessage(B_MOUSE_WHEEL_CHANGED); 597 event->AddInt64("when", system_time()); 598 event->AddFloat("be:wheel_delta_x", wheelX); 599 event->AddFloat("be:wheel_delta_y", wheelY); 600 fParent->EnqueueMessage(event); 601 602 // apply values to members 603 fWheelX = wheelX; 604 fWheelY = wheelY; 605 } 606 } 607 } 608 609 // SetContact 610 void 611 TabletDevice::SetContact(bool contact) 612 { 613 fHasContact = contact; 614 } 615 616 // poll_usb_device 617 int32 618 TabletDevice::poll_usb_device(void* arg) 619 { 620 TabletDevice* tabletDevice = (TabletDevice*)arg; 621 DeviceReader* reader = tabletDevice->fReader; 622 623 if (!reader || reader->InitCheck() < B_OK) 624 return B_BAD_VALUE; 625 626 int dataBytes = reader->MaxPacketSize(); 627 if (dataBytes > 128) 628 return B_BAD_VALUE; 629 630 uchar data[max_c(12, dataBytes)]; 631 632 while (tabletDevice->IsActive()) { 633 634 status_t ret = reader->ReadData(data, dataBytes); 635 636 if (ret == dataBytes) { 637 // data we read from the wacom device 638 uint32 mode; 639 bool hasContact = false; 640 uint32 buttons = 0; 641 float x = 0.0; 642 float y = 0.0; 643 float pressure = 0.0; 644 int32 clicks = 0; 645 int32 eraser = 0; 646 float wheelX = 0.0; 647 float wheelY = 0.0; 648 float tiltX = 0.0; 649 float tiltY = 0.0; 650 // let the device extract all information from the data 651 tabletDevice->ReadData(data, dataBytes, hasContact, mode, buttons, 652 x, y, pressure, clicks, eraser, 653 wheelX, wheelY, tiltX, tiltY); 654 if (hasContact) { 655 // apply the changes to the device 656 tabletDevice->SetStatus(mode, buttons, x, y, pressure, 657 clicks, modifiers(), eraser, 658 wheelX, wheelY, tiltX, tiltY, data); 659 } else 660 PRINT(("device has no contact\n")); 661 tabletDevice->SetContact(hasContact); 662 } else { 663 PRINT(("failed to read %ld bytes, read: %ld or %s\n", 664 dataBytes, ret, strerror(ret))); 665 666 if (ret < B_OK) { 667 if (ret == B_TIMED_OUT) 668 snooze(SNOOZE_AMOUNT); 669 else if (ret == B_INTERRUPTED) 670 snooze(SNOOZE_AMOUNT); 671 else { 672 return ret; 673 } 674 } 675 } 676 } 677 678 return B_OK; 679 } 680 681 // _DeviceSupportsTilt 682 bool 683 TabletDevice::_DeviceSupportsTilt() const 684 { 685 bool tilt = false; 686 switch (fDeviceMode) { 687 case DEVICE_INTUOS: 688 case DEVICE_INTUOS3: 689 case DEVICE_CINTIQ: 690 tilt = true; 691 break; 692 } 693 return tilt; 694 } 695 696 // _GetName 697 void 698 TabletDevice::_GetName(uint16 productID, const char** name) const 699 { 700 switch (productID) { 701 case 0x00: 702 *name = "Wacom USB"; 703 break; 704 case 0x03: // driver does not support this yet 705 *name = "Wacom Cintiq Partner USB"; 706 break; 707 case 0x10: 708 *name = "Wacom Graphire USB"; 709 break; 710 case 0x11: 711 *name = "Wacom Graphire2 4x5\" USB"; 712 break; 713 case 0x12: 714 *name = "Wacom Graphire2 5x7\" USB"; 715 break; 716 case 0x13: 717 *name = "Wacom Graphire3 4x5\" USB"; 718 break; 719 case 0x14: 720 *name = "Wacom Graphire3 6x8\" USB"; 721 break; 722 case 0x15: 723 *name = "Wacom Graphire4 4x5\" USB"; 724 break; 725 case 0x16: 726 *name = "Wacom Graphire4 6x8\" USB"; 727 break; 728 case 0x17: 729 *name = "Wacom BambooFun 4x5\" USB"; 730 break; 731 case 0x18: 732 *name = "Wacom BambooFun 6x8\" USB"; 733 break; 734 case 0x20: 735 *name = "Wacom Intuos 4x5\" USB"; 736 break; 737 case 0x21: 738 *name = "Wacom Intuos 6x8\" USB"; 739 break; 740 case 0x22: 741 *name = "Wacom Intuos 9x12\" USB"; 742 break; 743 case 0x23: 744 *name = "Wacom Intuos 12x12\" USB"; 745 break; 746 case 0x24: 747 *name = "Wacom Intuos 12x18\" USB"; 748 break; 749 case 0x30: 750 *name = "Wacom PL400 USB"; 751 break; 752 case 0x31: 753 *name = "Wacom PL500 USB"; 754 break; 755 case 0x32: 756 *name = "Wacom PL600 USB"; 757 break; 758 case 0x33: 759 *name = "Wacom PL600SX USB"; 760 break; 761 case 0x34: 762 *name = "Wacom PL550 USB"; 763 break; 764 case 0x35: 765 *name = "Wacom PL800 USB"; 766 break; 767 768 case 0x3F: 769 *name = "Wacom Cintiq 21UX USB"; 770 break; 771 772 case 0x41: 773 *name = "Wacom Intuos2 4x5\" USB"; 774 break; 775 case 0x42: 776 *name = "Wacom Intuos2 6x8\" USB"; 777 break; 778 case 0x43: 779 *name = "Wacom Intuos2 9x12\" USB"; 780 break; 781 case 0x44: 782 *name = "Wacom Intuos2 12x12\" USB"; 783 break; 784 case 0x45: 785 *name = "Wacom Intuos2 12x18\" USB"; 786 break; 787 case 0x47: // some I2 6x8s seem to report as 0x47 788 *name = "Wacom Intuos2 6x8\" USB"; 789 break; 790 791 case 0x60: 792 *name = "Wacom Volito USB"; 793 break; 794 case 0x61: 795 *name = "Wacom PenStation USB"; 796 break; 797 case 0x62: 798 *name = "Wacom Volito2 USB"; 799 break; 800 case 0x64: 801 *name = "Wacom PenPartner.1 USB"; 802 break; 803 case 0x65: 804 *name = "Wacom Bamboo USB"; 805 break; 806 case 0x69: 807 *name = "Wacom Bamboo1 USB"; 808 break; 809 810 case 0xB0: 811 *name = "Wacom Intuos3 4x5 USB"; 812 break; 813 case 0xB1: 814 *name = "Wacom Intuos3 6x8 USB"; 815 break; 816 case 0xB2: 817 *name = "Wacom Intuos3 9x12 USB"; 818 break; 819 820 case 0xD0: 821 *name = "Wacom Bamboo 2FG USB"; 822 break; 823 case 0xD1: 824 *name = "Wacom BambooFun 2FG 4x5\" USB"; 825 break; 826 case 0xD2: 827 *name = "Wacom Bamboo Craft USB"; 828 break; 829 case 0xD3: 830 *name = "Wacom BambooFun 2FG 6x8\" USB"; 831 break; 832 case 0xD4: 833 *name = "Wacom Bamboo 4x5\" USB"; 834 break; 835 case 0xD6: 836 *name = "Wacom Bamboo (CTH-460/K)"; 837 break; 838 case 0xD7: 839 *name = "Wacom Bamboo (CTH-461/S)"; 840 break; 841 case 0xD8: 842 *name = "Wacom Bamboo (CTH-661/S1)"; 843 break; 844 case 0xDA: 845 *name = "Wacom Bamboo (CTH-461/L)"; 846 break; 847 case 0xDB: 848 *name = "Wacom Bamboo (CTH-661)"; 849 break; 850 851 default: 852 *name = "<unkown wacom tablet>"; 853 break; 854 } 855 } 856 857