Changeset 6e09bee in mainline for uspace/app/wacomdump/wacomdump.c


Ignore:
Timestamp:
2012-08-12T21:31:32Z (12 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
91ecaa10
Parents:
5bf6bc70
Message:

Interpret wacom events in more depth

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/wacomdump/wacomdump.c

    r5bf6bc70 r6e09bee  
    3333#include <stdio.h>
    3434
    35 #define BUF_SIZE 32
     35#define BUF_SIZE 64
    3636
    3737#define START_OF_PACKET 128
     
    4949#define CMD_QUERY_TOUCH '%'
    5050
    51 /* packet_consumer_fn(uint8_t *packet, size_t size)
     51typedef struct isdv4_event isdv4_event_t;
     52
     53typedef void (*isdv4_event_fn)(const isdv4_event_t *);
     54
     55typedef struct {
     56        /* Stylus information */
     57        unsigned int stylus_max_x;
     58        unsigned int stylus_max_y;
     59        unsigned int stylus_max_pressure;
     60        unsigned int stylus_max_xtilt;
     61        unsigned int stylus_max_ytilt;
     62        bool stylus_tilt_supported;
     63
     64        /* Touch information */
     65        unsigned int touch_type;
     66        unsigned int touch_max_x;
     67        unsigned int touch_max_y;
     68
     69        /* Event state */
     70        bool stylus_in_proximity;
     71        bool stylus_is_eraser;
     72        bool button1_pressed;
     73        bool button2_pressed;
     74
     75        /* Session to the serial device */
     76        async_sess_t *sess;
     77
     78        /* Receive buffer state */
     79        uint8_t *buf;
     80        size_t buf_size;
     81        size_t buf_end;
     82
     83        /* Callbacks */
     84        isdv4_event_fn emit_event_fn;
     85} isdv4_state_t;
     86
     87typedef enum {
     88        UNKNOWN, PRESS, RELEASE, PROXIMITY_IN, PROXIMITY_OUT, MOVE
     89} isdv4_event_type_t;
     90
     91typedef enum {
     92        STYLUS_TIP, STYLUS_ERASER, TOUCH
     93} isdv4_source_type_t;
     94
     95typedef struct isdv4_event {
     96        isdv4_event_type_t type;
     97        isdv4_source_type_t source;
     98        unsigned int x;
     99        unsigned int y;
     100        unsigned int pressure;
     101        unsigned int button;
     102} isdv4_event_t;
     103
     104static void isdv4_event_init(isdv4_event_t *event)
     105{
     106        memset(event, 0, sizeof(isdv4_event_t));
     107}
     108
     109/* packet_consumer_fn(uint8_t *packet, size_t size, isdv4_state_t *state)
    52110   return true if reading of packets should continue */
    53 typedef bool (*packet_consumer_fn)(uint8_t *, size_t);
     111typedef bool (*packet_consumer_fn)(uint8_t *, size_t, isdv4_state_t *);
    54112
    55113static void syntax_print(void)
     
    58116}
    59117
    60 static bool parse_packet(uint8_t *packet, size_t size)
     118static void print_event(const isdv4_event_t *event)
     119{
     120        const char *type = NULL;
     121        switch (event->type) {
     122                case PRESS:
     123                        type = "PRESS";
     124                        break;
     125                case RELEASE:
     126                        type = "RELEASE";
     127                        break;
     128                case PROXIMITY_IN:
     129                        type = "PROXIMITY IN";
     130                        break;
     131                case PROXIMITY_OUT:
     132                        type = "PROXIMITY OUT";
     133                        break;
     134                case MOVE:
     135                        type = "MOVE";
     136                        return;
     137                case UNKNOWN:
     138                        type = "UNKNOWN";
     139                        break;
     140        }
     141       
     142        const char *source = NULL;
     143        switch (event->source) {
     144                case STYLUS_TIP:
     145                        source = "stylus tip";
     146                        break;
     147                case STYLUS_ERASER:
     148                        source = "stylus eraser";
     149                        break;
     150                case TOUCH:
     151                        source = "touch";
     152                        break;
     153        }
     154       
     155        const char *buttons = "none";
     156        switch (event->button) {
     157                case 1:
     158                        buttons = "button1";
     159                        break;
     160                case 2:
     161                        buttons = "button2";
     162                        break;
     163                case 3:
     164                        buttons = "both";
     165                        break;
     166        }
     167       
     168        printf("%s %s %u %u %u %s\n", type, source, event->x, event->y,
     169            event->pressure, buttons);
     170}
     171
     172static bool parse_event(uint8_t *packet, size_t size, isdv4_state_t *state)
    61173{
    62174        if (size < 1) {
    63                 printf("Invalid packet size");
     175                printf("Invalid packet size\n");
    64176                return false;
    65177        }
    66 
    67178        bool control_packet = ((packet[0] & CONTROL_PACKET) > 0);
    68         if (!control_packet) {
    69                 /* This is an event initiated by the device */
    70                 printf("Event");
    71                 if (size == 5 || size == 7) {
    72                         printf(" touch");
    73                         if (packet[0] & FINGER1) {
    74                                 printf(" finger1");
    75                         }
    76                         if (packet[0] & FINGER2) {
    77                                 printf(" finger2");
    78                         }
    79                         int x = ((packet[1] & 127) << 7) | (packet[2] & 127);
    80                         int y = ((packet[3] & 127) << 7) | (packet[4] & 127);
    81                         printf(" x=%d y=%d", x, y);
    82                 }
    83                 else if (size == 9) {
    84                         printf(" stylus");
    85                         if (packet[0] & TIP) {
    86                                 printf(" tip");
    87                         }
    88                         if (packet[0] & BUTTON1) {
    89                                 printf(" button1");
    90                         }
    91                         if (packet[0] & BUTTON2) {
    92                                 printf(" button2");
    93                         }
    94                         if (packet[0] & PROXIMITY) {
    95                                 printf(" proximity");
    96                         }
    97                         int x = ((packet[1] & 127) << 7) | (packet[2] & 124) | ((packet[6] >> 5) & 3);
    98                         int y = ((packet[3] & 127) << 7) | (packet[4] & 124) | ((packet[6] >> 3) & 3);
    99                         int xtilt = (packet[8] & 127);
    100                         int ytilt = (packet[7] & 127);
    101                         printf(" x=%d y=%d xtilt=%d ytilt=%d", x, y, xtilt, ytilt);
    102                 }
    103         }
    104         else {
    105                 printf("Response");
    106         }
    107 
    108         printf("\n");
     179        if (control_packet) {
     180                printf("This is not an event packet\n");
     181                return true;
     182        }
     183
     184        /* This is an event initiated by the device */
     185        isdv4_event_t event;
     186        isdv4_event_init(&event);
     187
     188/*      size_t dbg_ctr;*/
     189/*      printf("Packet: ");*/
     190/*      for (dbg_ctr = 0; dbg_ctr < size; dbg_ctr++) {*/
     191/*              printf("%02hhx ", packet[dbg_ctr]);*/
     192/*      }*/
     193/*      printf("\n");*/
     194
     195        if (size == 5 || size == 7) {
     196                /* This is a touch event */
     197                bool finger1 = (packet[0] & FINGER1) > 0;
     198                event.x = ((packet[1] & 127) << 7) | (packet[2] & 127);
     199                event.y = ((packet[3] & 127) << 7) | (packet[4] & 127);
     200                event.source = TOUCH;
     201                printf("TOUCH finger finger1=%d x=%u y=%u\n", finger1, event.x, event.y);
     202
     203                if (!state->stylus_in_proximity) {
     204                        if (!finger1 && state->button1_pressed) {
     205                                state->button1_pressed = false;
     206
     207                                event.type = RELEASE;
     208                                event.button = 1;
     209                                state->emit_event_fn(&event);
     210                        }
     211                        else if (finger1 && !state->button1_pressed) {
     212                                state->button1_pressed = true;
     213
     214                                event.type = PRESS;
     215                                event.button = 1;
     216                                state->emit_event_fn(&event);
     217                        }
     218                        else {
     219                                event.type = MOVE;
     220                                event.button = 1;
     221                                state->emit_event_fn(&event);
     222                        }
     223                }
     224        }
     225        else if (size == 9) {
     226                /* This is a stylus event */
     227                bool tip = packet[0] & TIP;
     228                bool button1 = packet[0] & BUTTON1;
     229                bool button2 = packet[0] & BUTTON2;
     230                bool proximity = packet[0] & PROXIMITY;
     231                event.x = ((packet[1] & 127) << 7) | (packet[2] & 124) | ((packet[6] >> 5) & 3);
     232                event.y = ((packet[3] & 127) << 7) | (packet[4] & 124) | ((packet[6] >> 3) & 3);
     233                event.pressure = (packet[5] & 127) | ((packet[6] & 7) << 7);
     234
     235                bool eraser = !tip && button2;
     236                printf("STYLUS tip=%d button1=%d button2=%d proximity=%d x=%u y=%u p=%u\n",
     237                    tip, button1, button2, proximity, event.x, event.y, event.pressure);
     238
     239                if (proximity && !state->stylus_in_proximity) {
     240                        /* Stylus came into proximity */
     241                        state->stylus_in_proximity = true;
     242                        state->stylus_is_eraser = eraser;
     243                        event.source = (state->stylus_is_eraser ? STYLUS_ERASER : STYLUS_TIP);
     244                        event.type = PROXIMITY_IN;
     245                        state->emit_event_fn(&event);
     246                }
     247                else if (!proximity && state->stylus_in_proximity) {
     248                        /* Stylus came out of proximity */
     249                        state->stylus_in_proximity = false;
     250                        event.source = (state->stylus_is_eraser ? STYLUS_ERASER : STYLUS_TIP);
     251                        event.type = PROXIMITY_OUT;
     252                        state->emit_event_fn(&event);
     253                }
     254                else {
     255                        /* Proximity state didn't change, but we need to check if it is still eraser */
     256                        if (eraser != state->stylus_is_eraser) {
     257                                event.type = PROXIMITY_OUT;
     258                                event.source = eraser ? STYLUS_TIP : STYLUS_ERASER;
     259                                state->emit_event_fn(&event);
     260                                event.type = PROXIMITY_IN;
     261                                event.source = eraser ? STYLUS_ERASER : STYLUS_TIP;
     262                                state->emit_event_fn(&event);
     263                                state->stylus_is_eraser = eraser;
     264                        }
     265                }
     266               
     267                if (!state->stylus_is_eraser) {
     268                        if (button1 && !state->button1_pressed) {
     269                                state->button1_pressed = true;
     270                                event.type = PRESS;
     271                                event.source = STYLUS_TIP;
     272                                event.button = 1;
     273                                state->emit_event_fn(&event);
     274                        }
     275                        else if (!button1 && state->button1_pressed) {
     276                                state->button1_pressed = false;
     277                                event.type = RELEASE;
     278                                event.source = STYLUS_TIP;
     279                                event.button = 1;
     280                                state->emit_event_fn(&event);
     281                        }
     282                        if (button2 && !state->button2_pressed) {
     283                                state->button2_pressed = true;
     284                                event.type = PRESS;
     285                                event.source = STYLUS_TIP;
     286                                event.button = 2;
     287                                state->emit_event_fn(&event);
     288                        }
     289                        else if (!button2 && state->button2_pressed) {
     290                                state->button2_pressed = false;
     291                                event.type = RELEASE;
     292                                event.source = STYLUS_TIP;
     293                                event.button = 2;
     294                                state->emit_event_fn(&event);
     295                        }
     296                        event.type = MOVE;
     297                        event.source = STYLUS_TIP;
     298                        event.button = (button1 ? 1 : 0) | (button2 ? 2 : 0);
     299                        state->emit_event_fn(&event);
     300                }
     301                else {
     302                        if (button1 && !state->button1_pressed) {
     303                                state->button1_pressed = true;
     304                                event.type = PRESS;
     305                                event.source = STYLUS_ERASER;
     306                                event.button = 1;
     307                                state->emit_event_fn(&event);
     308                        }
     309                        else if (!button1 && state->button1_pressed) {
     310                                state->button1_pressed = false;
     311                                event.type = RELEASE;
     312                                event.source = STYLUS_ERASER;
     313                                event.button = 1;
     314                                state->emit_event_fn(&event);
     315                        }
     316                        event.type = MOVE;
     317                        event.source = STYLUS_ERASER;
     318                        event.button = (button1 ? 1 : 0);
     319                        state->emit_event_fn(&event);
     320                }
     321                //int xtilt = (packet[8] & 127);
     322                //int ytilt = (packet[7] & 127);
     323        }
     324
    109325        return true;
    110326}
    111327
    112 static bool parse_response_stylus(uint8_t *packet, size_t size)
     328static bool parse_response_stylus(uint8_t *packet, size_t size,
     329    isdv4_state_t *state)
    113330{
    114331        if (size != 11) {
     
    158375}
    159376
    160 static bool parse_response_touch(uint8_t *packet, size_t size)
     377static bool parse_response_touch(uint8_t *packet, size_t size,
     378    isdv4_state_t *state)
    161379{
    162380        if (size != 11) {
     
    170388        }
    171389
    172         unsigned int data_id = (packet[0] & 63);
     390        state->touch_type = (packet[0] & 63);
    173391        unsigned int version = ((packet[9] & 127) << 7) | (packet[10] & 127);
    174392
    175393        unsigned int touch_resolution = packet[1] & 127;
    176         unsigned int sensor_id = packet[2] & 7;
    177         unsigned int max_x = ((packet[2] >> 5) & 3) | ((packet[3] & 127) << 7) |
     394        state->touch_max_x = ((packet[2] >> 5) & 3) | ((packet[3] & 127) << 7) |
    178395            (packet[4] & 124);
    179         unsigned int max_y = ((packet[2] >> 3) & 3) | ((packet[5] & 127) << 7) |
     396        state->touch_max_y = ((packet[2] >> 3) & 3) | ((packet[5] & 127) << 7) |
    180397            (packet[6] & 124);
    181         unsigned int capacitance_res = packet[7] & 127;
    182 
     398       
    183399        if (touch_resolution == 0)
    184400                touch_resolution = 10;
    185401
    186         if (max_x == 0 || max_y == 0) {
    187                 max_x = (1 << touch_resolution);
    188                 max_y = (1 << touch_resolution);
    189         }
    190 
    191         printf("Touch info: data_id=%u (%s) version=%u sensor_id=%u max_x=%u "
    192             "max_y=%u capacitance_res=%u\n", data_id, touch_type(data_id), version,
    193             sensor_id, max_x, max_y, capacitance_res);
     402        if (state->touch_max_x == 0 || state->touch_max_y == 0) {
     403                state->touch_max_x = (1 << touch_resolution);
     404                state->touch_max_y = (1 << touch_resolution);
     405        }
     406
     407        printf("Touch info: data_id=%u (%s) version=%u max_x=%u "
     408            "max_y=%u\n", state->touch_type, touch_type(state->touch_type), version,
     409            state->touch_max_x, state->touch_max_y);
    194410        return false;
    195411}
    196412
    197 static void read_packets(async_sess_t *sess, packet_consumer_fn consumer)
    198 {
    199         uint8_t buf[BUF_SIZE];
    200         ssize_t buf_end = 0;
    201        
    202         while (true) {
    203                 ssize_t read = char_dev_read(sess, buf + buf_end, BUF_SIZE - buf_end);
     413static void read_packets(isdv4_state_t *state, packet_consumer_fn consumer)
     414{
     415        bool reading = true;
     416        bool silence = true;
     417        while (reading) {
     418                ssize_t read = char_dev_read(state->sess, state->buf + state->buf_end,
     419                    state->buf_size - state->buf_end);
    204420                if (read < 0) {
    205421                        fprintf(stderr, "Failed reading from serial device\n");
    206422                        return;
    207423                }
    208                 buf_end += read;
    209                
    210                 ssize_t i = 0;
     424                state->buf_end += read;
     425               
     426                if (!silence && read == 0) {
     427                        silence = true;
     428                        usleep(100000); /* 100 ms */
     429                        continue;
     430                }
     431                else if (read > 0) {
     432                        silence = false;
     433                }
     434               
     435                size_t i = 0;
    211436               
    212437                /* Skip data until a start of packet is found */
    213                 while (i < buf_end && (buf[i] & START_OF_PACKET) == 0) i++;
    214                
    215                 ssize_t start = i;
    216                 ssize_t end = i;
    217                 ssize_t processed_end = i;
     438                while (i < state->buf_end && (state->buf[i] & START_OF_PACKET) == 0) i++;
     439               
     440                size_t start = i;
     441                size_t end = i;
     442                size_t processed_end = i;
    218443               
    219444                /* Process packets one by one */
    220                 while (i < buf_end) {
     445                while (reading && i < state->buf_end) {
    221446                        /* Find a start of next packet */
    222447                        i++; /* We need to skip the first byte with START_OF_PACKET set */
    223                         while (i < buf_end && (buf[i] & START_OF_PACKET) == 0) i++;
     448                        while (i < state->buf_end && (state->buf[i] & START_OF_PACKET) == 0) i++;
    224449                        end = i;
    225450                       
    226451                        /* If we have whole packet, process it */
    227                         if (end - start > 0 && (end != buf_end || read == 0)) {
    228                                 if (!consumer(buf + start, end - start)) {
    229                                         return;
    230                                 }
     452                        if (end > start && (end != state->buf_end || read == 0)) {
     453                                reading = consumer(state->buf + start, end - start, state);
    231454                                start = end;
    232455                                processed_end = end;
     
    234457                }
    235458               
    236                 if (processed_end == 0 && buf_end == BUF_SIZE) {
     459                if (processed_end == 0 && state->buf_end == BUF_SIZE) {
    237460                        fprintf(stderr, "Buffer overflow detected, discarding contents\n");
    238                         buf_end = 0;
     461                        state->buf_end = 0;
    239462                }
    240463               
    241464                /* Shift the buffer contents to the left */
    242                 size_t unprocessed_len = buf_end - processed_end;
    243                 memcpy(buf, buf + processed_end, unprocessed_len);
    244                 buf_end = unprocessed_len;
    245         }
    246        
    247         /* not reached */
     465                size_t unprocessed_len = state->buf_end - processed_end;
     466                memcpy(state->buf, state->buf + processed_end, unprocessed_len);
     467                state->buf_end = unprocessed_len;
     468        }
    248469}
    249470static bool write_command(async_sess_t *sess, uint8_t command)
    250471{
    251472        return char_dev_write(sess, &command, 1) == 1;
     473}
     474
     475static void isdv4_init(isdv4_state_t *state, async_sess_t *sess,
     476    uint8_t *buf, size_t buf_size, isdv4_event_fn event_fn)
     477{
     478        memset(state, 0, sizeof(isdv4_state_t));
     479        state->sess = sess;
     480        state->buf = buf;
     481        state->buf_size = buf_size;
     482        state->emit_event_fn = event_fn;
     483}
     484
     485static void isdv4_init_tablet(isdv4_state_t *state)
     486{
     487        write_command(state->sess, CMD_STOP);
     488        usleep(250000); /* 250 ms */
     489        while (char_dev_read(state->sess, state->buf, state->buf_size) > 0);
     490        write_command(state->sess, CMD_QUERY_STYLUS);
     491        read_packets(state, parse_response_stylus);
     492        write_command(state->sess, CMD_QUERY_TOUCH);
     493        read_packets(state, parse_response_touch);
     494        write_command(state->sess, CMD_START);
    252495}
    253496
     
    338581        }
    339582       
    340         write_command(sess, CMD_STOP);
    341         usleep(250000); /* 250 ms */
    342583        uint8_t buf[BUF_SIZE];
    343         while (char_dev_read(sess, buf, BUF_SIZE) > 0);
    344         write_command(sess, CMD_QUERY_STYLUS);
    345         read_packets(sess, parse_response_stylus);
    346         write_command(sess, CMD_QUERY_TOUCH);
    347         read_packets(sess, parse_response_touch);
    348         write_command(sess, CMD_START);
    349         read_packets(sess, parse_packet);
     584       
     585        isdv4_state_t state;
     586        isdv4_init(&state, sess, buf, BUF_SIZE, print_event);
     587        isdv4_init_tablet(&state);
     588       
     589        read_packets(&state, parse_event);
    350590       
    351591        return 0;
Note: See TracChangeset for help on using the changeset viewer.