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