00001
00002
00003 #if defined(linux) || defined(_AIX)
00004 #include <sys/ioctl.h>
00005 #elif WIN32
00006
00007 #define ioctl(a,b,c)
00008 #else
00009 #include <sys/filio.h>
00010 #endif
00011
00012 #include "dev.H"
00013 #include "tablet.H"
00014
00015 #include "std/config.H"
00016
00017 using namespace mlib;
00018
00019 #define BIT(N, INT) ((1 << N) & ((int)(INT)))
00020 #define BITS(SN, EN, INT) (((1 << EN) -1) & (~((1 << SN)-1)) & ((int)(INT)))
00021
00022 static bool debug = Config::get_var_bool("DEBUG_TABLET",false,true);
00023
00024 TabletDesc::TabletDesc(
00025 TabletType t
00026 )
00027 {
00028 switch (t) {
00029 case CROSS : *this = TabletDesc(B19200, 5, "@", 5000);
00030 brcase LCD : *this = TabletDesc(B9600, 7, "", 3162);
00031 brcase TINY : *this = TabletDesc(B9600, 7, "", 3162);
00032 brcase MULTI_MODE : *this = TabletDesc(B9600, 7, "MU1\n", 15000);
00033 brcase LARGE : *this = TabletDesc(B9600, 7, "", 15000);
00034 brcase SMALL : *this = TabletDesc(B9600, 7, "", 6000);
00035 brcase INTUOS : *this = TabletDesc(B9600, 9, "MT1\nID1\nIT0\n", 16240);
00036 }
00037 _type = t;
00038 }
00039
00040 Tablet::Tablet(
00041 FD_MANAGER *manager,
00042 TabletDesc::TabletType ttype,
00043 const char *dev,
00044 const char *name
00045 ) : TTYfd(manager, dev, name), _styl_buttons( &_stylus ), _desc(ttype)
00046 {
00047 if (!_dev[0])
00048 strcpy(_dev, DEV_DFLT_SERIAL_PORT);
00049 }
00050
00051 int
00052 Tablet::activate()
00053 {
00054 int ret = TTYfd::activate();
00055 if (ret) {
00056 set_speed (_desc._baud);
00057 set_stopbits(1);
00058 set_charsize(CS8);
00059 set_parity (TTY_NONE);
00060
00061 if (_desc._init_str != str_ptr()) {
00062 if (write(**_desc._init_str, strlen(**_desc._init_str), 20) < 0)
00063 perror("initializing tablet");
00064 }
00065 }
00066
00067 return ret;
00068 }
00069
00070
00071
00072
00073 void
00074 Tablet::mod_setting_bit( int bit_num, int value )
00075 {
00076
00077 if (_desc._type == TabletDesc::TINY ||
00078 _desc._type == TabletDesc::SMALL ||
00079 _desc._type == TabletDesc::LARGE ||
00080 _desc._type == TabletDesc::MULTI_MODE ||
00081 _desc._type == TabletDesc::LCD ||
00082 _desc._type == TabletDesc::INTUOS) {
00083 char buffer[256];
00084
00085 if (write("~R\n", 3, 20) < 0)
00086 perror("Tablet::mod_setting_bit(..)");
00087
00088 nread(buffer, strlen("~Rdddddddd,ddd,dd,dddd,dddd\n"), 20);
00089
00090 cerr << "buffer = '" << buffer << "'" << endl;
00091
00092 int byte = (bit_num / 8);
00093 int bit = (bit_num % 8);
00094
00095
00096
00097 assert(byte >= 0 && byte < 8);
00098
00099 if (value) {
00100
00101 buffer[byte+2] |= (1 << bit);
00102 } else {
00103 buffer[byte+2] &= ~(1 << bit);
00104 }
00105
00106 buffer[1] = '*';
00107 cerr << "buffer = '" << buffer << "'" << endl;
00108
00109 } else {
00110 cerr << "*** don't know how to 'mod_setting_bit' "
00111 << "for tablet in use.." << endl;
00112 }
00113 }
00114
00115 TabletEvent::TabletEvent(
00116 char *buf,
00117 TabletDesc *desc
00118 ):_desc(desc), _is_valid(1)
00119 {
00120 double yres = double(_desc->_yres);
00121
00122
00123 assert(BIT(7, buf[0]));
00124
00125
00126
00127 double rawx, rawy;
00128
00129 if (_desc->_type == TabletDesc::CROSS) {
00130 rawx = (((buf[2] & 0x7f)<<7) | (buf[1] & 0x7f));
00131 rawy = (((buf[4] & 0x7f)<<7) | (buf[3] & 0x7f));
00132 _pos[0] = 2*(rawx/ 7000.0 - 0.5);
00133 _pos[1] = 2*(rawy/ yres - 0.5);
00134 _buttons = buf[0] & 3;
00135 _device = STYLUS;
00136 _touching_tablet = BIT(5,buf[0]);
00137
00138 } else if(_desc->_type == TabletDesc::INTUOS) {
00139 _device = STYLUS;
00140 int dev = BIT(0,buf[0]);
00141 static int device_type[2];
00142 _is_eraser = ((device_type[dev]&0x7ff) != 0x0022);
00143
00144 if((buf[0] & 0xfc) == 0xc0) {
00145
00146 device_type[dev] = ((buf[1]&0x7f) << 5) | ((buf[2]&0x7c) >> 2);
00147 _is_valid = 0;
00148 }
00149 else if((buf[0] & 0xfe) == 0x80) {
00150
00151 _touching_tablet = 0;
00152 _is_valid = 0;
00153 }
00154 else if((buf[0]&0xb8) == 0xa0) {
00155
00156 rawx = (((buf[1] & 0x7f) << 9) | ((buf[2] & 0x7f) << 2)
00157 | ((buf[3] & 0x60) >> 5));
00158 rawy = (((buf[3] & 0x1f) << 11) | ((buf[4] & 0x7f) << 4)
00159 | ((buf[5] & 0x78) >> 3));
00160
00161
00162
00163
00164 double sizex = 20320;
00165 double sizey = yres;
00166
00167
00168
00169 static bool small_tablet = Config::get_var_bool("TABLET_SIZE_SMALL",false,true);
00170
00171 if (small_tablet) {
00172 sizex=12700.0;
00173 sizey=10360.0;
00174 }
00175
00176 _pos[0] = 2*(rawx/sizex - 0.5);
00177 _pos[1] = -2*(rawy/sizey - 0.5);
00178 _stylus_pressure = (((buf[5]&0x7)<<7) | (buf[6]&0x7f)) - 512;
00179 _buttons = ((buf[0] & 0x6) | (_stylus_pressure >= -480));
00180 _touching_tablet = BIT(6,buf[0]);
00181
00182 if (Config::get_var_bool("DBUG_PRESSURE",false,true))
00183 cerr << _stylus_pressure << endl;
00184
00185 }
00186 else {
00187 _is_valid = 0;
00188 fprintf(stderr, "Unknown tablet packet %02X\n", buf[0]);
00189 }
00190 } else {
00191
00192
00193
00194 _device = (BIT(5,buf[0])) ? STYLUS : PUCK;
00195
00196 rawx = (((buf[1] & 0x7f)<<7) | (buf[2] & 0x7f));
00197 rawy = (((buf[4] & 0x7f)<<7) | (buf[5] & 0x7f));
00198 if (_desc->_type == TabletDesc::LCD ||
00199 _desc->_type == TabletDesc::TINY) {
00200 _pos[0] = 2*(rawx/ (yres * (211.2/158.4)) - 0.5);
00201 _pos[1] = -2*(rawy/ yres - 0.5);
00202 } else {
00203 if (yres > 7000)
00204 _pos[0] = 2*(rawx/ yres - 0.5);
00205 else _pos[0] = 2*(rawx/ yres - 0.675);
00206 _pos[1] = -2*(rawy/ yres - 0.5);
00207 }
00208 _buttons = (buf[3] >> 3) & 15;
00209
00210 _touching_tablet = BIT(6,buf[0]);
00211
00212 _stylus_pressure = (int(buf[6]) & 0x3f) << 1 | ((int(buf[3]) >> 2) & 0x01);
00213 if (!BIT(6,buf[6]))
00214 _stylus_pressure += 127;
00215
00216 if (Config::get_var_bool("DBUG_PRESSURE",false,true))
00217 cerr << _stylus_pressure << endl;
00218
00219 if (_device == PUCK) {
00220 _pos[0] += 0.2;
00221 _pos[1] += 0.2;
00222 }
00223 }
00224
00225 _pos[0] += Config::get_var_dbl("TABLET_OFFSET_X",0.0,true);
00226 _pos[1] += Config::get_var_dbl("TABLET_OFFSET_Y",0.0,true);
00227 }
00228
00229 void
00230 TabletQueue::do_enqueue(
00231 TabletEvent &event
00232 )
00233 {
00234 _queue[_tail] = event;
00235
00236 if (_tail == _length-1)
00237 _tail = 0;
00238 else
00239 _tail++;
00240
00241 if (_tail==_head)
00242 cerr << "*** ERROR: Queue overflow!" << char(7) << endl;
00243 }
00244
00245 void
00246 TabletQueue::enqueue(
00247 TabletEvent &event
00248 )
00249 {
00250 if (empty())
00251 do_enqueue(event);
00252 else {
00253
00254 int last_event_index = ((_tail - 1) == -1) ? _length-1 : (_tail-1);
00255
00256
00257
00258 if ( (event.get_buttons() != _queue[last_event_index].get_buttons()) )
00259 do_enqueue(event);
00260 else {
00261
00262
00263 if (event.touching_tablet() !=
00264 _queue[last_event_index].touching_tablet())
00265 do_enqueue(event);
00266 else
00267 _queue[last_event_index] = event;
00268 }
00269 }
00270 }
00271
00272 TabletEvent
00273 TabletQueue::dequeue()
00274 {
00275 assert(!empty());
00276
00277 TabletEvent event = _queue[_head];
00278
00279 if( _head == _length-1 )
00280 _head = 0;
00281 else
00282 _head++;
00283
00284 return event;
00285 }
00286
00287 TabletMultimode::TabletMultimode(
00288 FD_MANAGER *mgr,
00289 TabletDesc::TabletType ttype,
00290 const char *tty,
00291 const char *name
00292 ) : Tablet(mgr, ttype, tty, name), _puck_buttons(&_puck),
00293 _using_stylus_eraser(0)
00294 {
00295 _num_bytes_left_from_last_read = 0;
00296
00297 _stylus_queue.reset();
00298 _puck_queue .reset();
00299 }
00300
00301 void
00302 TabletMultimode::enqueue_available_tablet_events()
00303 {
00304
00305
00306 int bytes_read = nread(_tablet_data_buffer + _num_bytes_left_from_last_read,
00307
00308 24 - _num_bytes_left_from_last_read,
00309 _timeout);
00310
00311 if ( bytes_read < 0 ) {
00312
00313 if (debug) {
00314 cerr << "** WARNING: TabletMultimode could not read any" << endl;
00315 cerr << " data from the tablet." << endl;
00316 cerr << " (bytes_read = " << bytes_read << ")" << endl;
00317 }
00318 return;
00319 }
00320
00321
00322
00323 int bytes_in_buffer = (bytes_read + _num_bytes_left_from_last_read);
00324
00325
00326
00327
00328 if (! BIT(7, _tablet_data_buffer[0]) ) {
00329
00330
00331 int offset = 1;
00332
00333 for (; !BIT(7, _tablet_data_buffer[offset]) && offset < bytes_in_buffer; offset++)
00334 ;
00335
00336 if (offset == _desc._rec_len) {
00337 cerr << "** ERROR: Cannot find start of tablet record!" << endl;
00338
00339 }
00340
00341 for (int i = offset; i < bytes_in_buffer; i++)
00342 _tablet_data_buffer[i-offset] = _tablet_data_buffer[i];
00343
00344 bytes_in_buffer -= offset;
00345
00346 if (debug)
00347 cerr << "** Finding tablet record start (skipped "
00348 << offset << " bytes)" << endl;
00349 }
00350
00351
00352 int num_complete_records = (bytes_in_buffer / _desc._rec_len);
00353
00354
00355 for (int i=0; i < num_complete_records; i++) {
00356 if (BIT(7, _tablet_data_buffer[i*_desc._rec_len])) {
00357
00358 TabletEvent event(_tablet_data_buffer+i*_desc._rec_len, &_desc);
00359
00360 if(event.is_valid()) {
00361
00362 if (event.get_device() == TabletEvent::STYLUS)
00363 _stylus_queue.enqueue(event);
00364 else _puck_queue .enqueue(event);
00365 }
00366 } else
00367 if (debug)
00368 cerr << "** WARNING: bad record read from tablet (#" <<i<<" )"
00369 << endl;
00370 }
00371
00372
00373
00374
00375 _num_bytes_left_from_last_read = (bytes_in_buffer % _desc._rec_len);
00376 for (int b=0; b<_num_bytes_left_from_last_read; b++)
00377 _tablet_data_buffer[b] = _tablet_data_buffer[bytes_in_buffer-
00378 _num_bytes_left_from_last_read + b];
00379 }
00380
00381 void
00382 TabletMultimode::sample()
00383 {
00384
00385 enqueue_available_tablet_events();
00386
00387 TabletEvent event;
00388
00389
00390
00391 if (!_stylus_queue.empty() && !_puck_queue.empty()) {
00392 if (_device_to_report == PUCK) {
00393 _device_to_report = STYLUS;
00394
00395 event = _puck_queue.dequeue();
00396 }
00397 else {
00398 _device_to_report = PUCK;
00399
00400 event = _stylus_queue.dequeue();
00401 }
00402 }
00403 else {
00404 if (!_stylus_queue.empty())
00405 event = _stylus_queue.dequeue();
00406 else if( !_puck_queue.empty() )
00407 event = _puck_queue.dequeue();
00408 else
00409 return;
00410 }
00411
00412 Evd::DEVmod mods = DEVmod_gen::mods();
00413 DEVice_buttons &old_buttons= event.get_device() == TabletEvent::PUCK ?
00414 _puck_buttons : _styl_buttons;
00415
00416 if(_desc._type == TabletDesc::INTUOS) {
00417
00418 int bit;
00419 if(event.is_eraser()) bit = 3;
00420 else bit = 0;
00421 if(BIT(0, event.get_buttons()) != old_buttons.get(bit)) {
00422 if(BIT(0, event.get_buttons())) {
00423 old_buttons.event(bit, DEVice_buttons::DOWN, mods);
00424 }
00425 else old_buttons.event(bit, DEVice_buttons::UP, mods);
00426 }
00427 for(bit = 1; bit < 3; bit++) {
00428 int state = BIT(bit, event.get_buttons()) ? 1 : 0;
00429 if(state != old_buttons.get(bit)) {
00430 if(state) old_buttons.event(bit, DEVice_buttons::DOWN, mods);
00431 else old_buttons.event(bit, DEVice_buttons::UP, mods);
00432 }
00433 }
00434 if(event.is_eraser()) bit = 7;
00435 else bit = 8;
00436 if(event.touching_tablet() != old_buttons.get(bit)) {
00437 if(event.touching_tablet()) {
00438 old_buttons.event(bit, DEVice_buttons::DOWN, mods);
00439 }
00440 else old_buttons.event(bit, DEVice_buttons::UP, mods);
00441 }
00442 if (event.get_device() == TabletEvent::PUCK) {
00443 _puck .event(XYpt(event.get_pos()[0],
00444 event.get_pos()[1]), mods);
00445 }
00446 else {
00447 _stylus_pressure = event.stylus_pressure();
00448 _stylus.set_pressure((_stylus_pressure + 511)/1024.0);
00449 _stylus.event(XYpt(event.get_pos()[0],
00450 event.get_pos()[1]), mods);
00451 }
00452 }
00453 else {
00454
00455
00456
00457
00458 if (event.get_device() == TabletEvent::STYLUS &&
00459 BIT(2,event.get_buttons()) &&
00460 !old_buttons.get(2) &&
00461 event.touching_tablet() &&
00462 !old_buttons.get(8)) {
00463 _using_stylus_eraser = true;
00464 old_buttons.event(7, DEVice_buttons::DOWN, mods);
00465 for (int i = 0; i < 2; i++) {
00466 int state = BIT(i,event.get_buttons()) ? 1 : 0;
00467 if (state != old_buttons.get(i)) {
00468 if (state) {
00469 if (i != 0) {
00470 old_buttons.event(i, DEVice_buttons::DOWN, mods);
00471 }
00472 } else {
00473 old_buttons.event(i, DEVice_buttons::UP , mods);
00474 }
00475 }
00476 }
00477 }
00478
00479
00480 if (event.get_device() == TabletEvent::STYLUS && _using_stylus_eraser) {
00481
00482
00483
00484 const int eraser_bit = 3;
00485
00486 int state = BIT(0, event.get_buttons()) ? 1 : 0;
00487 if (state != old_buttons.get(eraser_bit)) {
00488 if (state)
00489 old_buttons.event(eraser_bit, DEVice_buttons::DOWN, mods);
00490 else old_buttons.event(eraser_bit, DEVice_buttons::UP , mods);
00491 }
00492 }
00493 else {
00494 if (event.touching_tablet()) {
00495
00496 for (int i = 0; i < 3; i++) {
00497 int state = BIT(i,event.get_buttons()) ? 1 : 0;
00498 if (state != old_buttons.get(i)) {
00499 if (state)
00500 old_buttons.event(i, DEVice_buttons::DOWN, mods);
00501 else old_buttons.event(i, DEVice_buttons::UP , mods);
00502 }
00503 }
00504 }
00505 }
00506
00507
00508 int touching(event.touching_tablet() ? 1 : 0);
00509 if (touching != old_buttons.get(8)) {
00510 if (touching)
00511 old_buttons.event(8, DEVice_buttons::DOWN, mods);
00512 else old_buttons.event(8, DEVice_buttons::UP , mods);
00513 }
00514
00515 if (event.get_device() == TabletEvent::PUCK) {
00516 _puck .event(XYpt(event.get_pos()[0],
00517 event.get_pos()[1]), mods);
00518 } else {
00519 _stylus_pressure = event.stylus_pressure();
00520 _stylus.event(XYpt(event.get_pos()[0],
00521 event.get_pos()[1]), mods);
00522 }
00523
00524
00525
00526
00527
00528 if ((!event.touching_tablet() || !BIT(2,event.get_buttons())) &&
00529 _using_stylus_eraser) {
00530 old_buttons.event(7, DEVice_buttons::UP, mods);
00531 _using_stylus_eraser = false;
00532 }
00533 }
00534 }