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 firstButton = (data[6] > 2); 390 // For Intuos it MUST be >1, 391 // but '>1' still gets false actuations (shaking) 392 secondButton = (data[1] & 0x02); 393 thirdButton = (data[1] & 0x04); 394 hasContact = (data[1] & 0x40); 395 // TODO: is this meaningful? (always true on Intuos) 396 if (fDeviceMode == DEVICE_INTUOS) { // TODO: test perhaps superfluous? 397 // Original Intuos protocol: 398 // data[6] is used to signal use of the eraser, 399 // as well as being the high bits of pressure. 400 // While not in contact: 401 // If the pen end is lowermost data[6] = 1; 402 // If the eraser end is down data[6] = 0, and pressure is strictly 0 403 // data[9] (top 5 bits: 0x70..0xd0) indicates height above the tablet. 404 eraser = fEraser; 405 // keep established value unless not touching pad 406 // Eraser state only valid when away from surface 407 if (data[6] <= 1 && data[9] > 0x80) { // not touching tablet 408 if (pressureData == 0) eraser = 1; // strictly 0 means eraser 409 else if (pressureData > 6) eraser = 0; // avoid slop 410 } 411 } 412 // Get raw tilt values (0..54..127) 413 int8 tiltDataX = ((data[7] & 0x3f) << 1) | ((data[8] & 0x80) >> 7); 414 int8 tiltDataY = data[8] & 0x7f; 415 // convert to floats 416 tiltX = (float)(tiltDataX - 64) / 64.0; 417 tiltY = (float)(tiltDataY - 64) / 64.0; 418 } 419 } 420 break; 421 case DEVICE_PL500: { 422 hasContact = ( data[1] & 0x20); 423 xPos = data[2] << 8 | data[3]; 424 yPos = data[5] << 8 | data[6]; 425 firstButton = (data[4] & 0x08); 426 secondButton = (data[4] & 0x10); 427 thirdButton = (data[4] & 0x20); 428 uint16 pressureData = (data[4] & 0x04) >> 2 | (data[7] & 0x7f) << 1; 429 pressure = (float)pressureData / 511.0; 430 break; 431 } 432 case DEVICE_VOLITO: { 433 eraser = 0; 434 thirdButton = 0; 435 436 xPos = data[3] << 8 | data[2]; 437 yPos = data[5] << 8 | data[4]; 438 439 hasContact = (data[1] & 0x80); 440 441 firstButton = (data[1] & 0x01) == 1; 442 secondButton = data[1] & 0x04; 443 444 uint16 pressureData = data[7] << 8 | data[6]; 445 pressure = (float)pressureData / 511.0; 446 447 if (data[1] & 0x40) { // mouse is on tablet 448 wheelY = 0; 449 mode = MODE_MOUSE; 450 hasContact = (uint8)data[7] >= 30; 451 pressure = 0.0; 452 secondButton = data[1] & 0x02; 453 } 454 455 break; 456 } 457 case DEVICE_PENSTATION: { 458 xPos = data[3] << 8 | data[2]; 459 yPos = data[5] << 8 | data[4]; 460 hasContact = (data[1] & 0x10); 461 uint16 pressureData = data[7] << 8 | data[6]; 462 pressure = (float)pressureData / 511.0; 463 firstButton = (data[1] & 0x01); 464 secondButton = (data[1] & 0x02); 465 thirdButton = (data[1] & 0x04); 466 break; 467 } 468 } 469 if (pressure > 1.0) 470 pressure = 1.0; 471 else if (pressure < 0.0) 472 pressure = 0.0; 473 buttons = (firstButton ? B_PRIMARY_MOUSE_BUTTON : 0) 474 | (secondButton ? B_SECONDARY_MOUSE_BUTTON : 0) 475 | (thirdButton ? B_TERTIARY_MOUSE_BUTTON : 0); 476 x = (float)xPos; 477 y = (float)yPos; 478 } 479 480 // SetStatus 481 void 482 TabletDevice::SetStatus(uint32 mode, uint32 buttons, float x, float y, 483 float pressure, int32 clicks, uint32 modifiers, int32 eraser, 484 float wheelX, float wheelY, float tiltX, float tiltY, const uchar* data) 485 { 486 if (fActive) { 487 uint32 what = B_MOUSE_MOVED; 488 if (buttons > fButtons) 489 what = B_MOUSE_DOWN; 490 else if (buttons < fButtons) 491 what = B_MOUSE_UP; 492 493 494 #if DEBUG 495 float tabletX = x; 496 float tabletY = y; 497 #endif 498 x /= fMaxX; 499 y /= fMaxY; 500 501 float deltaX = 0.0; 502 float deltaY = 0.0; 503 504 float absDeltaX = 0.0; 505 float absDeltaY = 0.0; 506 507 float unfilteredX = x; 508 float unfilteredY = y; 509 510 if (fHasContact) { 511 deltaX = x - fPosX; 512 deltaY = y - fPosY; 513 514 absDeltaX = fabsf(deltaX); 515 absDeltaY = fabsf(deltaY); 516 517 #if 0 //DEBUG 518 fParent->LogString() << "x: " << x << ", y: " << y << ", pressure: " << pressure << "\n"; 519 fParent->LogString() << "tilt x: " << tiltX << ", tilt y: " << tiltY << "\n\n"; 520 #endif 521 // apply a bit of filtering 522 if (absDeltaX < fJitterX) 523 x = fPosX; 524 if (absDeltaY < fJitterY) 525 y = fPosY; 526 } 527 528 // only do send message if something changed 529 if (x != fPosX || y != fPosY || fButtons != buttons || pressure != fPressure 530 || fEraser != eraser || fTiltX != tiltX || fTiltY != tiltY) { 531 532 bigtime_t now = system_time(); 533 534 // common fields for any mouse message 535 BMessage* event = new BMessage(what); 536 event->AddInt64("when", now); 537 event->AddInt32("buttons", buttons); 538 if (mode == MODE_PEN) { 539 event->AddFloat("x", x); 540 event->AddFloat("y", y); 541 event->AddFloat("be:tablet_x", unfilteredX); 542 event->AddFloat("be:tablet_y", unfilteredY); 543 event->AddFloat("be:tablet_pressure", pressure); 544 event->AddInt32("be:tablet_eraser", eraser); 545 if (_DeviceSupportsTilt()) { 546 event->AddFloat("be:tablet_tilt_x", tiltX); 547 event->AddFloat("be:tablet_tilt_y", tiltY); 548 } 549 // adjust mouse coordinates as well 550 // to have the mouse appear at the pens 551 // last position when switching 552 fFakeMouseX = unfilteredX; 553 fFakeMouseY = unfilteredY; 554 } else if (mode == MODE_MOUSE) { 555 // apply acceleration 556 float accelerationX = fJitterX * ACCELERATION_KICK_IN; 557 // if (absDeltaX > accelerationX) 558 deltaX *= absDeltaX / accelerationX; 559 float accelerationY = fJitterY * ACCELERATION_KICK_IN; 560 // if (absDeltaY > accelerationY) 561 deltaY *= absDeltaY / accelerationY; 562 // calculate screen coordinates 563 fFakeMouseX = min_c(1.0, max_c(0.0, fFakeMouseX + deltaX)); 564 fFakeMouseY = min_c(1.0, max_c(0.0, fFakeMouseY + deltaY)); 565 event->AddFloat("x", fFakeMouseX); 566 event->AddFloat("y", fFakeMouseY); 567 event->AddFloat("be:tablet_x", fFakeMouseX); 568 event->AddFloat("be:tablet_y", fFakeMouseY); 569 } 570 event->AddInt32("modifiers", modifiers); 571 572 #if DEBUG 573 if (data) { 574 event->AddData("raw usb data", B_RAW_TYPE, data, 12); 575 } 576 event->AddFloat("tablet x", tabletX); 577 event->AddFloat("tablet y", tabletY); 578 #endif 579 // additional fields for mouse down or up 580 if (what == B_MOUSE_DOWN) { 581 if (now - fLastClickTime < fParent->DoubleClickSpeed()) { 582 fClicks++; 583 if (fClicks > 3) 584 fClicks = 1; 585 } else { 586 fClicks = 1; 587 } 588 fLastClickTime = now; 589 event->AddInt32("clicks", fClicks); 590 } else if (what == B_MOUSE_UP) 591 event->AddInt32("clicks", 0); 592 593 status_t ret = fParent->EnqueueMessage(event); 594 if (ret < B_OK) 595 PRINT(("EnqueueMessage(): %s\n", strerror(ret))); 596 597 // apply values to members 598 fPosX = x; 599 fPosY = y; 600 fButtons = buttons; 601 fPressure = pressure; 602 fModifiers = modifiers; 603 fEraser = eraser; 604 fTiltX = tiltX; 605 fTiltY = tiltY; 606 } 607 608 // separate wheel changed message 609 if (fWheelX != wheelX || fWheelY != wheelY) { 610 BMessage* event = new BMessage(B_MOUSE_WHEEL_CHANGED); 611 event->AddInt64("when", system_time()); 612 event->AddFloat("be:wheel_delta_x", wheelX); 613 event->AddFloat("be:wheel_delta_y", wheelY); 614 fParent->EnqueueMessage(event); 615 616 // apply values to members 617 fWheelX = wheelX; 618 fWheelY = wheelY; 619 } 620 } 621 } 622 623 // SetContact 624 void 625 TabletDevice::SetContact(bool contact) 626 { 627 fHasContact = contact; 628 } 629 630 // poll_usb_device 631 int32 632 TabletDevice::poll_usb_device(void* arg) 633 { 634 TabletDevice* tabletDevice = (TabletDevice*)arg; 635 DeviceReader* reader = tabletDevice->fReader; 636 637 if (!reader || reader->InitCheck() < B_OK) 638 return B_BAD_VALUE; 639 640 int dataBytes = reader->MaxPacketSize(); 641 if (dataBytes > 128) 642 return B_BAD_VALUE; 643 644 uchar data[max_c(12, dataBytes)]; 645 646 while (tabletDevice->IsActive()) { 647 648 status_t ret = reader->ReadData(data, dataBytes); 649 650 if (ret == dataBytes) { 651 // data we read from the wacom device 652 uint32 mode; 653 bool hasContact = false; 654 uint32 buttons = 0; 655 float x = 0.0; 656 float y = 0.0; 657 float pressure = 0.0; 658 int32 clicks = 0; 659 int32 eraser = 0; 660 float wheelX = 0.0; 661 float wheelY = 0.0; 662 float tiltX = 0.0; 663 float tiltY = 0.0; 664 // let the device extract all information from the data 665 tabletDevice->ReadData(data, dataBytes, hasContact, mode, buttons, 666 x, y, pressure, clicks, eraser, 667 wheelX, wheelY, tiltX, tiltY); 668 if (hasContact) { 669 // apply the changes to the device 670 tabletDevice->SetStatus(mode, buttons, x, y, pressure, 671 clicks, modifiers(), eraser, 672 wheelX, wheelY, tiltX, tiltY, data); 673 } else 674 PRINT(("device has no contact\n")); 675 tabletDevice->SetContact(hasContact); 676 } else { 677 PRINT(("failed to read %ld bytes, read: %ld or %s\n", 678 dataBytes, ret, strerror(ret))); 679 680 if (ret < B_OK) { 681 if (ret == B_TIMED_OUT) 682 snooze(SNOOZE_AMOUNT); 683 else if (ret == B_INTERRUPTED) 684 snooze(SNOOZE_AMOUNT); 685 else { 686 return ret; 687 } 688 } 689 } 690 } 691 692 return B_OK; 693 } 694 695 // _DeviceSupportsTilt 696 bool 697 TabletDevice::_DeviceSupportsTilt() const 698 { 699 bool tilt = false; 700 switch (fDeviceMode) { 701 case DEVICE_INTUOS: 702 case DEVICE_INTUOS3: 703 case DEVICE_CINTIQ: 704 tilt = true; 705 break; 706 } 707 return tilt; 708 } 709 710 // _GetName 711 void 712 TabletDevice::_GetName(uint16 productID, const char** name) const 713 { 714 switch (productID) { 715 case 0x00: 716 *name = "Wacom USB"; 717 break; 718 case 0x03: // driver does not support this yet 719 *name = "Wacom Cintiq Partner USB"; 720 break; 721 case 0x10: 722 *name = "Wacom Graphire USB"; 723 break; 724 case 0x11: 725 *name = "Wacom Graphire2 4x5\" USB"; 726 break; 727 case 0x12: 728 *name = "Wacom Graphire2 5x7\" USB"; 729 break; 730 case 0x13: 731 *name = "Wacom Graphire3 4x5\" USB"; 732 break; 733 case 0x14: 734 *name = "Wacom Graphire3 6x8\" USB"; 735 break; 736 case 0x15: 737 *name = "Wacom Graphire4 4x5\" USB"; 738 break; 739 case 0x16: 740 *name = "Wacom Graphire4 6x8\" USB"; 741 break; 742 case 0x17: 743 *name = "Wacom BambooFun 4x5\" USB"; 744 break; 745 case 0x18: 746 *name = "Wacom BambooFun 6x8\" USB"; 747 break; 748 case 0x20: 749 *name = "Wacom Intuos 4x5\" USB"; 750 break; 751 case 0x21: 752 *name = "Wacom Intuos 6x8\" USB"; 753 break; 754 case 0x22: 755 *name = "Wacom Intuos 9x12\" USB"; 756 break; 757 case 0x23: 758 *name = "Wacom Intuos 12x12\" USB"; 759 break; 760 case 0x24: 761 *name = "Wacom Intuos 12x18\" USB"; 762 break; 763 case 0x30: 764 *name = "Wacom PL400 USB"; 765 break; 766 case 0x31: 767 *name = "Wacom PL500 USB"; 768 break; 769 case 0x32: 770 *name = "Wacom PL600 USB"; 771 break; 772 case 0x33: 773 *name = "Wacom PL600SX USB"; 774 break; 775 case 0x34: 776 *name = "Wacom PL550 USB"; 777 break; 778 case 0x35: 779 *name = "Wacom PL800 USB"; 780 break; 781 782 case 0x3F: 783 *name = "Wacom Cintiq 21UX USB"; 784 break; 785 786 case 0x41: 787 *name = "Wacom Intuos2 4x5\" USB"; 788 break; 789 case 0x42: 790 *name = "Wacom Intuos2 6x8\" USB"; 791 break; 792 case 0x43: 793 *name = "Wacom Intuos2 9x12\" USB"; 794 break; 795 case 0x44: 796 *name = "Wacom Intuos2 12x12\" USB"; 797 break; 798 case 0x45: 799 *name = "Wacom Intuos2 12x18\" USB"; 800 break; 801 case 0x47: // some I2 6x8s seem to report as 0x47 802 *name = "Wacom Intuos2 6x8\" USB"; 803 break; 804 805 case 0x60: 806 *name = "Wacom Volito USB"; 807 break; 808 case 0x61: 809 *name = "Wacom PenStation USB"; 810 break; 811 case 0x62: 812 *name = "Wacom Volito2 USB"; 813 break; 814 case 0x64: 815 *name = "Wacom PenPartner.1 USB"; 816 break; 817 case 0x65: 818 *name = "Wacom Bamboo USB"; 819 break; 820 case 0x69: 821 *name = "Wacom Bamboo1 USB"; 822 break; 823 824 case 0xB0: 825 *name = "Wacom Intuos3 4x5 USB"; 826 break; 827 case 0xB1: 828 *name = "Wacom Intuos3 6x8 USB"; 829 break; 830 case 0xB2: 831 *name = "Wacom Intuos3 9x12 USB"; 832 break; 833 834 case 0xD0: 835 *name = "Wacom Bamboo 2FG USB"; 836 break; 837 case 0xD1: 838 *name = "Wacom BambooFun 2FG 4x5\" USB"; 839 break; 840 case 0xD2: 841 *name = "Wacom Bamboo Craft USB"; 842 break; 843 case 0xD3: 844 *name = "Wacom BambooFun 2FG 6x8\" USB"; 845 break; 846 case 0xD4: 847 *name = "Wacom Bamboo 4x5\" USB"; 848 break; 849 case 0xD6: 850 *name = "Wacom Bamboo (CTH-460/K)"; 851 break; 852 case 0xD7: 853 *name = "Wacom Bamboo (CTH-461/S)"; 854 break; 855 case 0xD8: 856 *name = "Wacom Bamboo (CTH-661/S1)"; 857 break; 858 case 0xDA: 859 *name = "Wacom Bamboo (CTH-461/L)"; 860 break; 861 case 0xDB: 862 *name = "Wacom Bamboo (CTH-661)"; 863 break; 864 865 default: 866 *name = "<unkown wacom tablet>"; 867 break; 868 } 869 } 870 871