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