Changeset a987832 in mainline
- Timestamp:
- 2012-08-14T21:58:56Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8a99c7e
- Parents:
- c92e30f
- Location:
- uspace/app/wacomdump
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/wacomdump/Makefile
rc92e30f ra987832 33 33 34 34 SOURCES = \ 35 wacomdump.c 35 wacomdump.c \ 36 isdv4.c 36 37 37 38 include $(USPACE_PREFIX)/Makefile.common -
uspace/app/wacomdump/wacomdump.c
rc92e30f ra987832 32 32 #include <loc.h> 33 33 #include <stdio.h> 34 #include <macros.h> 35 36 #define BUF_SIZE 64 37 38 #define START_OF_PACKET 128 39 #define CONTROL_PACKET 64 40 #define TOUCH_EVENT 16 41 #define FINGER1 1 42 #define FINGER2 2 43 #define TIP 1 44 #define BUTTON1 2 45 #define BUTTON2 4 46 #define PROXIMITY 32 47 48 #define CMD_START '1' 49 #define CMD_STOP '0' 50 #define CMD_QUERY_STYLUS '*' 51 #define CMD_QUERY_TOUCH '%' 52 53 typedef struct isdv4_event isdv4_event_t; 54 55 typedef void (*isdv4_event_fn)(const isdv4_event_t *); 56 57 typedef struct { 58 /* Stylus information */ 59 unsigned int stylus_max_x; 60 unsigned int stylus_max_y; 61 unsigned int stylus_max_pressure; 62 unsigned int stylus_max_xtilt; 63 unsigned int stylus_max_ytilt; 64 bool stylus_tilt_supported; 65 66 /* Touch information */ 67 unsigned int touch_type; 68 unsigned int touch_max_x; 69 unsigned int touch_max_y; 70 71 /* Event state */ 72 bool stylus_in_proximity; 73 bool stylus_is_eraser; 74 bool tip_pressed; /* Reported as stylus button 1 */ 75 bool button1_pressed; /* Reported as stylus button 2 */ 76 bool button2_pressed; /* Reported as stylus button 3 */ 77 bool finger1_pressed; /* Reported as touch button 1 */ 78 79 /* Session to the serial device */ 80 async_sess_t *sess; 81 82 /* Receive buffer state */ 83 uint8_t *buf; 84 size_t buf_size; 85 size_t buf_end; 86 87 /* Callbacks */ 88 isdv4_event_fn emit_event_fn; 89 } isdv4_state_t; 90 91 typedef enum { 92 UNKNOWN, PRESS, RELEASE, PROXIMITY_IN, PROXIMITY_OUT, MOVE 93 } isdv4_event_type_t; 94 95 typedef enum { 96 STYLUS_TIP, STYLUS_ERASER, TOUCH 97 } isdv4_source_type_t; 98 99 typedef struct isdv4_event { 100 isdv4_event_type_t type; 101 isdv4_source_type_t source; 102 unsigned int x; 103 unsigned int y; 104 unsigned int pressure; 105 unsigned int button; 106 } isdv4_event_t; 107 108 static void isdv4_event_init(isdv4_event_t *event) 109 { 110 memset(event, 0, sizeof(isdv4_event_t)); 111 } 112 113 /* packet_consumer_fn(uint8_t *packet, size_t size, isdv4_state_t *state) 114 return true if reading of packets should continue */ 115 typedef bool (*packet_consumer_fn)(uint8_t *, size_t, isdv4_state_t *); 34 35 #include "isdv4.h" 116 36 117 37 static void syntax_print(void) … … 143 63 break; 144 64 } 145 65 146 66 const char *source = NULL; 147 67 switch (event->source) { … … 156 76 break; 157 77 } 158 78 159 79 const char *buttons = "none"; 160 80 switch (event->button) { … … 169 89 break; 170 90 } 171 91 172 92 printf("%s %s %u %u %u %s\n", type, source, event->x, event->y, 173 93 event->pressure, buttons); 174 }175 176 static bool parse_event(uint8_t *packet, size_t size, isdv4_state_t *state)177 {178 if (size < 1) {179 printf("Invalid packet size\n");180 return false;181 }182 bool control_packet = ((packet[0] & CONTROL_PACKET) > 0);183 if (control_packet) {184 printf("This is not an event packet\n");185 return true;186 }187 188 /* This is an event initiated by the device */189 isdv4_event_t event;190 isdv4_event_init(&event);191 192 193 if (size == 5 || size == 7) {194 /* This is a touch event */195 bool finger1 = (packet[0] & FINGER1) > 0;196 event.x = ((packet[1] & 127) << 7) | (packet[2] & 127);197 event.y = ((packet[3] & 127) << 7) | (packet[4] & 127);198 event.source = TOUCH;199 200 if (!state->stylus_in_proximity) {201 if (!finger1 && state->finger1_pressed) {202 state->finger1_pressed = false;203 204 event.type = RELEASE;205 event.button = 1;206 state->emit_event_fn(&event);207 }208 else if (finger1 && !state->finger1_pressed) {209 state->finger1_pressed = true;210 211 event.type = PRESS;212 event.button = 1;213 state->emit_event_fn(&event);214 }215 else {216 event.type = MOVE;217 event.button = 1;218 state->emit_event_fn(&event);219 }220 }221 }222 else if (size == 9) {223 /* This is a stylus event */224 bool tip = packet[0] & TIP;225 bool button1 = packet[0] & BUTTON1;226 bool button2 = packet[0] & BUTTON2;227 bool proximity = packet[0] & PROXIMITY;228 event.x = ((packet[1] & 127) << 7) | (packet[2] & 124) | ((packet[6] >> 5) & 3);229 event.y = ((packet[3] & 127) << 7) | (packet[4] & 124) | ((packet[6] >> 3) & 3);230 event.pressure = (packet[5] & 127) | ((packet[6] & 7) << 7);231 232 if (proximity && !state->stylus_in_proximity) {233 /* Stylus came into proximity */234 state->stylus_in_proximity = true;235 state->stylus_is_eraser = !tip && button2;236 event.source = (state->stylus_is_eraser ? STYLUS_ERASER : STYLUS_TIP);237 event.type = PROXIMITY_IN;238 state->emit_event_fn(&event);239 }240 else if (!proximity && state->stylus_in_proximity) {241 /* Stylus came out of proximity */242 state->stylus_in_proximity = false;243 event.source = (state->stylus_is_eraser ? STYLUS_ERASER : STYLUS_TIP);244 event.type = PROXIMITY_OUT;245 state->emit_event_fn(&event);246 }247 else {248 /* Proximity state didn't change, but we need to check if it is still eraser */249 if (state->stylus_is_eraser && !button2) {250 event.type = PROXIMITY_OUT;251 event.source = STYLUS_ERASER;252 state->emit_event_fn(&event);253 event.type = PROXIMITY_IN;254 event.source = STYLUS_TIP;255 state->emit_event_fn(&event);256 state->stylus_is_eraser = false;257 }258 else if (!state->stylus_is_eraser && !tip && button2) {259 event.type = PROXIMITY_OUT;260 event.source = STYLUS_TIP;261 state->emit_event_fn(&event);262 event.type = PROXIMITY_IN;263 event.source = STYLUS_ERASER;264 state->emit_event_fn(&event);265 state->stylus_is_eraser = true;266 }267 }268 269 if (!state->stylus_is_eraser) {270 if (tip && !state->tip_pressed) {271 state->tip_pressed = true;272 event.type = PRESS;273 event.source = STYLUS_TIP;274 event.button = 1;275 state->emit_event_fn(&event);276 }277 else if (!tip && state->tip_pressed) {278 state->tip_pressed = false;279 event.type = RELEASE;280 event.source = STYLUS_TIP;281 event.button = 1;282 state->emit_event_fn(&event);283 }284 if (button1 && !state->button1_pressed) {285 state->button1_pressed = true;286 event.type = PRESS;287 event.source = STYLUS_TIP;288 event.button = 2;289 state->emit_event_fn(&event);290 }291 else if (!button1 && state->button1_pressed) {292 state->button1_pressed = false;293 event.type = RELEASE;294 event.source = STYLUS_TIP;295 event.button = 2;296 state->emit_event_fn(&event);297 }298 if (button2 && !state->button2_pressed) {299 state->button2_pressed = true;300 event.type = PRESS;301 event.source = STYLUS_TIP;302 event.button = 3;303 state->emit_event_fn(&event);304 }305 else if (!button2 && state->button2_pressed) {306 state->button2_pressed = false;307 event.type = RELEASE;308 event.source = STYLUS_TIP;309 event.button = 3;310 state->emit_event_fn(&event);311 }312 event.type = MOVE;313 event.source = STYLUS_TIP;314 event.button = (tip ? 1: 0) | (button1 ? 2 : 0) | (button2 ? 4 : 0);315 state->emit_event_fn(&event);316 }317 else {318 if (tip && !state->tip_pressed) {319 state->tip_pressed = true;320 event.type = PRESS;321 event.source = STYLUS_ERASER;322 event.button = 1;323 state->emit_event_fn(&event);324 }325 else if (!tip && state->tip_pressed) {326 state->tip_pressed = false;327 event.type = RELEASE;328 event.source = STYLUS_ERASER;329 event.button = 1;330 state->emit_event_fn(&event);331 }332 event.type = MOVE;333 event.source = STYLUS_ERASER;334 event.button = (tip ? 1 : 0);335 state->emit_event_fn(&event);336 }337 }338 339 return true;340 }341 342 static bool parse_response_stylus(uint8_t *packet, size_t size,343 isdv4_state_t *state)344 {345 if (size != 11) {346 fprintf(stderr, "Unexpected length of stylus response packet\n");347 return false;348 }349 bool control_packet = ((packet[0] & CONTROL_PACKET) > 0);350 if (!control_packet) {351 fprintf(stderr, "This is not a control packet\n");352 return false;353 }354 355 unsigned int data_id = (packet[0] & 63);356 unsigned int version = ((packet[9] & 127) << 7) | (packet[10] & 127);357 358 unsigned int max_x = ((packet[1] & 127) << 7) | (packet[2] & 124) |359 ((packet[6] >> 5) & 3);360 unsigned int max_y = ((packet[3] & 127) << 7) | (packet[4] & 124) |361 ((packet[6] >> 3) & 3);362 unsigned int max_pressure = (packet[5] & 63) | ((packet[6] & 7) << 7);363 unsigned int max_xtilt = packet[8] & 127;364 unsigned int max_ytilt = packet[7] & 127;365 366 printf("Stylus info: data_id=%u version=%u max_x=%u max_y=%u max_pressure=%u "367 "max_xtilt=%u max_ytilt=%u\n", data_id, version, max_x, max_y,368 max_pressure, max_xtilt, max_ytilt);369 370 return false;371 94 } 372 95 … … 389 112 } 390 113 391 static bool parse_response_touch(uint8_t *packet, size_t size,392 isdv4_state_t *state)393 {394 if (size != 11) {395 fprintf(stderr, "Unexpected length of touch response packet\n");396 return false;397 }398 bool control_packet = ((packet[0] & CONTROL_PACKET) > 0);399 if (!control_packet) {400 fprintf(stderr, "This is not a control packet\n");401 return false;402 }403 404 state->touch_type = (packet[0] & 63);405 unsigned int version = ((packet[9] & 127) << 7) | (packet[10] & 127);406 407 unsigned int touch_resolution = packet[1] & 127;408 state->touch_max_x = ((packet[2] >> 5) & 3) | ((packet[3] & 127) << 7) |409 (packet[4] & 124);410 state->touch_max_y = ((packet[2] >> 3) & 3) | ((packet[5] & 127) << 7) |411 (packet[6] & 124);412 413 if (touch_resolution == 0)414 touch_resolution = 10;415 416 if (state->touch_max_x == 0 || state->touch_max_y == 0) {417 state->touch_max_x = (1 << touch_resolution);418 state->touch_max_y = (1 << touch_resolution);419 }420 421 printf("Touch info: data_id=%u (%s) version=%u max_x=%u "422 "max_y=%u\n", state->touch_type, touch_type(state->touch_type), version,423 state->touch_max_x, state->touch_max_y);424 return false;425 }426 427 static void read_packets(isdv4_state_t *state, packet_consumer_fn consumer)428 {429 bool reading = true;430 size_t packet_remaining = 1;431 while (reading) {432 if (packet_remaining == 0) packet_remaining = 1;433 ssize_t read = char_dev_read(state->sess, state->buf + state->buf_end,434 state->buf_size - state->buf_end);435 if (read < 0) {436 fprintf(stderr, "Failed reading from serial device\n");437 return;438 }439 state->buf_end += read;440 441 size_t i = 0;442 443 /* Skip data until a start of packet is found */444 while (i < state->buf_end && (state->buf[i] & START_OF_PACKET) == 0) i++;445 446 size_t start = i;447 size_t end = i;448 size_t processed_end = i;449 450 /* Process packets one by one */451 while (reading && i < state->buf_end) {452 /* Determine the packet length */453 if (state->buf[i] & CONTROL_PACKET) {454 packet_remaining = 11;455 }456 else if (state->buf[i] & TOUCH_EVENT) {457 packet_remaining = 5;458 }459 else {460 packet_remaining = 9;461 }462 463 /* Find the end of the packet */464 i++; /* We need to skip the first byte with START_OF_PACKET set */465 packet_remaining--;466 while (packet_remaining > 0 && i < state->buf_end &&467 (state->buf[i] & START_OF_PACKET) == 0) {468 i++;469 packet_remaining--;470 }471 end = i;472 473 /* If we have whole packet, process it */474 if (end > start && packet_remaining == 0) {475 reading = consumer(state->buf + start, end - start, state);476 start = end;477 processed_end = end;478 }479 }480 481 if (processed_end == 0 && state->buf_end == BUF_SIZE) {482 fprintf(stderr, "Buffer overflow detected, discarding contents\n");483 state->buf_end = 0;484 }485 486 /* Shift the buffer contents to the left */487 size_t unprocessed_len = state->buf_end - processed_end;488 memcpy(state->buf, state->buf + processed_end, unprocessed_len);489 state->buf_end = unprocessed_len;490 }491 }492 static bool write_command(async_sess_t *sess, uint8_t command)493 {494 return char_dev_write(sess, &command, 1) == 1;495 }496 497 static void isdv4_init(isdv4_state_t *state, async_sess_t *sess,498 uint8_t *buf, size_t buf_size, isdv4_event_fn event_fn)499 {500 memset(state, 0, sizeof(isdv4_state_t));501 state->sess = sess;502 state->buf = buf;503 state->buf_size = buf_size;504 state->emit_event_fn = event_fn;505 }506 507 static void isdv4_init_tablet(isdv4_state_t *state)508 {509 write_command(state->sess, CMD_STOP);510 usleep(250000); /* 250 ms */511 // FIXME: Read all possible garbage before sending commands512 write_command(state->sess, CMD_QUERY_STYLUS);513 read_packets(state, parse_response_stylus);514 write_command(state->sess, CMD_QUERY_TOUCH);515 read_packets(state, parse_response_touch);516 write_command(state->sess, CMD_START);517 }518 519 114 int main(int argc, char **argv) 520 115 { 521 116 sysarg_t baud = 38400; 522 117 service_id_t svc_id; 523 118 524 119 int arg = 1; 525 120 int rc; 526 121 527 122 if (argc > arg && str_test_prefix(argv[arg], "--baud=")) { 528 123 size_t arg_offset = str_lsize(argv[arg], 7); … … 542 137 arg++; 543 138 } 544 139 545 140 if (argc > arg) { 546 141 rc = loc_service_get_id(argv[arg], &svc_id, 0); … … 554 149 else { 555 150 category_id_t serial_cat_id; 556 151 557 152 rc = loc_category_get_id("serial", &serial_cat_id, 0); 558 153 if (rc != EOK) { … … 561 156 return 1; 562 157 } 563 158 564 159 service_id_t *svc_ids; 565 160 size_t svc_count; 566 161 567 162 rc = loc_category_get_svcs(serial_cat_id, &svc_ids, &svc_count); if (rc != EOK) { 568 163 fprintf(stderr, "Failed getting list of services\n"); 569 164 return 1; 570 165 } 571 166 572 167 if (svc_count == 0) { 573 168 fprintf(stderr, "No service in category 'serial'\n"); … … 575 170 return 1; 576 171 } 577 172 578 173 svc_id = svc_ids[0]; 579 174 free(svc_ids); 580 175 } 581 176 582 177 if (argc > arg) { 583 178 fprintf(stderr, "Too many arguments\n"); … … 585 180 return 1; 586 181 } 587 588 182 589 183 async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE, svc_id, 590 184 IPC_FLAG_BLOCKING); … … 592 186 fprintf(stderr, "Failed connecting to service\n"); 593 187 } 594 188 595 189 async_exch_t *exch = async_exchange_begin(sess); 596 190 rc = async_req_4_0(exch, SERIAL_SET_COM_PROPS, baud, 597 191 SERIAL_NO_PARITY, 8, 1); 598 192 async_exchange_end(exch); 599 193 600 194 if (rc != EOK) { 601 195 fprintf(stderr, "Failed setting serial properties\n"); 602 196 return 2; 603 197 } 604 605 uint8_t buf[BUF_SIZE]; 606 198 607 199 isdv4_state_t state; 608 isdv4_init(&state, sess, buf, BUF_SIZE, print_event); 609 isdv4_init_tablet(&state); 610 611 read_packets(&state, parse_event); 612 200 rc = isdv4_init(&state, sess, print_event); 201 if (rc != EOK) { 202 fprintf(stderr, "Failed initializing isdv4 state"); 203 return 2; 204 } 205 206 rc = isdv4_init_tablet(&state); 207 if (rc != EOK) { 208 fprintf(stderr, "Failed initializing tablet"); 209 return 2; 210 } 211 212 printf("Tablet information:\n"); 213 printf(" Stylus: %ux%u pressure: %u tilt: ", state.stylus_max_x, 214 state.stylus_max_y, state.stylus_max_pressure); 215 if (state.stylus_tilt_supported) { 216 printf("%ux%u\n", state.stylus_max_xtilt, state.stylus_max_ytilt); 217 } 218 else { 219 printf("not supported\n"); 220 } 221 printf(" Touch: %ux%u type: %s\n", state.touch_max_x, state.touch_max_y, 222 touch_type(state.touch_type)); 223 224 rc = isdv4_read_events(&state); 225 if (rc != EOK) { 226 fprintf(stderr, "Failed reading events"); 227 return 2; 228 } 229 230 isdv4_fini(&state); 231 613 232 return 0; 614 233 }
Note:
See TracChangeset
for help on using the changeset viewer.