Changeset c322fd6 in mainline for uspace/drv/char/ps2mouse/ps2mouse.c


Ignore:
Timestamp:
2011-12-31T16:06:11Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1dea6d7
Parents:
c637571
Message:

ps2mouse: Ad support for 4th and 5th button IntelliMouse extension.

Works on VirtualBox, qemu won't send events for those buttons.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/char/ps2mouse/ps2mouse.c

    rc637571 rc322fd6  
    5353#define INTELLIMOUSE_BUFSIZE 4
    5454
    55 #define Z_SIGN (1 << 3)
    56 #define X_SIGN (1 << 4)
    57 #define Y_SIGN (1 << 5)
    58 #define X_OVERFLOW (1 << 6)
    59 #define Y_OVERFLOW (1 << 7)
     55#define Z_SIGN (1 << 3) /* 4th byte */
     56#define X_SIGN (1 << 4) /* 1st byte */
     57#define Y_SIGN (1 << 5) /* 1st byte */
     58#define X_OVERFLOW (1 << 6) /* 1st byte */
     59#define Y_OVERFLOW (1 << 7) /* 1st byte */
    6060
    6161#define BUTTON_LEFT   0
     
    6363#define BUTTON_MIDDLE   2
    6464#define PS2_BUTTON_COUNT   3
     65
     66#define INTELLIMOUSE_ALWAYS_ZERO (0xc0)
     67#define INTELLIMOUSE_BUTTON_4 (1 << 4) /* 4th byte */
     68#define INTELLIMOUSE_BUTTON_5 (1 << 5) /* 4th byte */
    6569#define INTELLIMOUSE_BUTTON_COUNT 5
    6670
     
    7579                return size < 0 ? size : EIO; \
    7680        } \
    77         if (data != value) { \
     81        if (data != (value)) { \
    7882                ddf_msg(LVL_ERROR, "Failed testing byte: got %hhx vs. %hhx)", \
    79                     data, value); \
     83                    data, (value)); \
    8084                return EIO; \
    8185        } \
     
    8387#define MOUSE_WRITE_BYTE(sess, value) \
    8488do { \
    85         uint8_t data = value; \
     89        uint8_t data = (value); \
    8690        const ssize_t size = char_dev_write(session, &data, 1); \
    8791        if (size < 0 ) { \
     
    9397static int polling_ps2(void *);
    9498static int polling_intellimouse(void *);
    95 static int probe_intellimouse(async_sess_t *);
     99static int probe_intellimouse(async_sess_t *, bool);
    96100static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
    97101/*----------------------------------------------------------------------------*/
     
    143147        /* Probe IntelliMouse extensions. */
    144148        int (*polling_f)(void*) = polling_ps2;
    145         if (probe_intellimouse(mouse->parent_sess) == EOK) {
     149        if (probe_intellimouse(mouse->parent_sess, false) == EOK) {
    146150                ddf_msg(LVL_NOTE, "Enabled IntelliMouse extensions");
    147151                polling_f = polling_intellimouse;
     152                if (probe_intellimouse(mouse->parent_sess, true) == EOK)
     153                        ddf_msg(LVL_NOTE, "Enabled 4th and 5th button.");
    148154        }
    149155        /* Enable mouse data reporting. */
     
    237243}
    238244/*----------------------------------------------------------------------------*/
    239 /** Get data and parse ps2 protocol with intellimouse extension packets.
     245/** Get data and parse ps2 protocol with IntelliMouse extension packets.
    240246 * @param arg Pointer to ps2_mouse_t structure.
    241247 * @return Never.
     
    268274                        continue;
    269275                }
    270                 /* ps/2 Buttons */
    271                 for (unsigned i = 0; i < PS2_BUTTON_COUNT; ++i) {
    272                         const bool status = (packet[0] & PS2_BUTTON_MASK(i));
    273                         if (buttons[i] != status) {
    274                                 buttons[i] = status;
     276
     277                /* Buttons */
     278                /* NOTE: Parsing 4th and 5th button works even if this extension
     279                 * is not supported and whole 4th byte should be interpreted
     280                 * as Z-axis movement. the upper 4 bits are just a sign
     281                 * extension then. + sign is interpreted as "button up"
     282                 * (i.e no change since that is the default) and - sign fails
     283                 * the "imb" condition. Thus 4th and 5th buttons are never
     284                 * down on wheel only extension. */
     285                const bool imb = (packet[3] & INTELLIMOUSE_ALWAYS_ZERO) == 0;
     286                const bool status[] = {
     287                        [0] = packet[0] & PS2_BUTTON_MASK(0),
     288                        [1] = packet[0] & PS2_BUTTON_MASK(1),
     289                        [2] = packet[0] & PS2_BUTTON_MASK(2),
     290                        [3] = (packet[3] & INTELLIMOUSE_BUTTON_4) && imb,
     291                        [4] = (packet[3] & INTELLIMOUSE_BUTTON_5) && imb,
     292                };
     293                for (unsigned i = 0; i < INTELLIMOUSE_BUTTON_COUNT; ++i) {
     294                        if (buttons[i] != status[i]) {
     295                                buttons[i] = status[i];
    275296                                async_msg_2(exch, MOUSEEV_BUTTON_EVENT, i + 1,
    276297                                    buttons[i]);
     
    296317}
    297318/*----------------------------------------------------------------------------*/
    298 static int probe_intellimouse(async_sess_t *session)
     319/** Send magic sequence to initialize IntelliMouse extensions.
     320 * @param session IPC session to the parent device.
     321 * @param buttons True selects magic sequence for 4th and 5th button,
     322 * false selects wheel support magic sequence.
     323 * See http://www.computer-engineering.org/ps2mouse/ for details.
     324 */
     325static int probe_intellimouse(async_sess_t *session, bool buttons)
    299326{
    300327        assert(session);
     
    307334        MOUSE_WRITE_BYTE(session, PS2_MOUSE_SET_SAMPLE_RATE);
    308335        MOUSE_READ_BYTE_TEST(session, PS2_MOUSE_ACK);
    309         MOUSE_WRITE_BYTE(session, 100);
     336        MOUSE_WRITE_BYTE(session, buttons ? 200 : 100);
    310337        MOUSE_READ_BYTE_TEST(session, PS2_MOUSE_ACK);
    311338
     
    317344        MOUSE_WRITE_BYTE(session, PS2_MOUSE_GET_DEVICE_ID);
    318345        MOUSE_READ_BYTE_TEST(session, PS2_MOUSE_ACK);
    319         MOUSE_READ_BYTE_TEST(session, 3);
     346        MOUSE_READ_BYTE_TEST(session, buttons ? 4 : 3);
    320347
    321348        return EOK;
Note: See TracChangeset for help on using the changeset viewer.