Ignore:
File:
1 edited

Legend:

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

    rd420b22 rdd8ab1c  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2017 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    3031 */
    3132/** @file
    32  * @brief ps2 mouse driver.
     33 * @brief PS/2 mouse driver.
    3334 */
    3435
    3536#include <stdbool.h>
    3637#include <errno.h>
     38#include <str_error.h>
    3739#include <ddf/log.h>
    3840#include <io/keycode.h>
     
    7072#define PS2_BUTTON_MASK(button) (1 << button)
    7173
    72 #define MOUSE_READ_BYTE_TEST(sess, value_) \
     74#define MOUSE_READ_BYTE_TEST(mouse, value_) \
    7375do { \
    7476        uint8_t value = (value_); \
    7577        uint8_t data = 0; \
    76         const ssize_t size = chardev_read(sess, &data, 1); \
    77         if (size != 1) { \
    78                 ddf_msg(LVL_ERROR, "Failed reading byte: %zd)", size);\
    79                 return size < 0 ? size : EIO; \
     78        size_t nread; \
     79        const int rc = chardev_read((mouse)->chardev, &data, 1, &nread); \
     80        if (rc != EOK) { \
     81                ddf_msg(LVL_ERROR, "Failed reading byte: %s", str_error_name(rc));\
     82                return rc; \
    8083        } \
    8184        if (data != value) { \
     
    8689} while (0)
    8790
    88 #define MOUSE_WRITE_BYTE(sess, value_) \
     91#define MOUSE_WRITE_BYTE(mouse, value_) \
    8992do { \
    9093        uint8_t value = (value_); \
    9194        uint8_t data = (value); \
    92         const ssize_t size = chardev_write(sess, &data, 1); \
    93         if (size < 0 ) { \
    94                 ddf_msg(LVL_ERROR, "Failed writing byte: %hhx", value); \
    95                 return size; \
     95        size_t nwr; \
     96        const int rc = chardev_write((mouse)->chardev, &data, 1, &nwr); \
     97        if (rc != EOK) { \
     98                ddf_msg(LVL_ERROR, "Failed writing byte: %s", str_error_name(rc)); \
     99                return rc; \
    96100        } \
    97101} while (0)
     
    99103static int polling_ps2(void *);
    100104static int polling_intellimouse(void *);
    101 static int probe_intellimouse(async_exch_t *, bool);
     105static int probe_intellimouse(ps2_mouse_t *, bool);
    102106static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
    103107
     
    108112
    109113/** Initialize mouse driver structure.
     114 *
     115 * Connects to parent, creates keyboard function, starts polling fibril.
     116 *
    110117 * @param kbd Mouse driver structure to initialize.
    111118 * @param dev DDF device structure.
    112119 *
    113  * Connects to parent, creates keyboard function, starts polling fibril.
     120 * @return EOK on success or non-zero error code
    114121 */
    115122int ps2_mouse_init(ps2_mouse_t *mouse, ddf_dev_t *dev)
    116123{
     124        async_sess_t *parent_sess;
     125        bool bound = false;
     126        int rc;
     127
    117128        mouse->client_sess = NULL;
    118         mouse->parent_sess = ddf_dev_parent_sess_get(dev);
    119         if (!mouse->parent_sess)
    120                 return ENOMEM;
     129
     130        parent_sess = ddf_dev_parent_sess_get(dev);
     131        if (parent_sess == NULL) {
     132                ddf_msg(LVL_ERROR, "Failed getting parent session.");
     133                rc = ENOMEM;
     134                goto error;
     135        }
     136
     137        rc = chardev_open(parent_sess, &mouse->chardev);
     138        if (rc != EOK) {
     139                ddf_msg(LVL_ERROR, "Failed opening character device.");
     140                goto error;
     141        }
    121142
    122143        mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse");
    123         if (!mouse->mouse_fun) {
    124                 return ENOMEM;
    125         }
     144        if (mouse->mouse_fun == NULL) {
     145                ddf_msg(LVL_ERROR, "Error creating mouse function.");
     146                rc = ENOMEM;
     147                goto error;
     148        }
     149
    126150        ddf_fun_set_ops(mouse->mouse_fun, &mouse_ops);
    127151
    128         int ret = ddf_fun_bind(mouse->mouse_fun);
    129         if (ret != EOK) {
    130                 ddf_fun_destroy(mouse->mouse_fun);
    131                 return ENOMEM;
    132         }
    133 
    134         ret = ddf_fun_add_to_category(mouse->mouse_fun, "mouse");
    135         if (ret != EOK) {
    136                 ddf_fun_unbind(mouse->mouse_fun);
    137                 ddf_fun_destroy(mouse->mouse_fun);
    138                 return ENOMEM;
    139         }
     152        rc = ddf_fun_bind(mouse->mouse_fun);
     153        if (rc != EOK) {
     154                ddf_msg(LVL_ERROR, "Failed binding mouse function.");
     155                goto error;
     156        }
     157
     158        bound = true;
     159
     160        rc = ddf_fun_add_to_category(mouse->mouse_fun, "mouse");
     161        if (rc != EOK) {
     162                ddf_msg(LVL_ERROR, "Failed adding mouse function to category.");
     163                goto error;
     164        }
     165
    140166        /* Probe IntelliMouse extensions. */
    141167        int (*polling_f)(void*) = polling_ps2;
    142         async_exch_t *exch = async_exchange_begin(mouse->parent_sess);
    143         if (probe_intellimouse(exch, false) == EOK) {
     168        if (probe_intellimouse(mouse, false) == EOK) {
    144169                ddf_msg(LVL_NOTE, "Enabled IntelliMouse extensions");
    145170                polling_f = polling_intellimouse;
    146                 if (probe_intellimouse(exch, true) == EOK)
     171                if (probe_intellimouse(mouse, true) == EOK)
    147172                        ddf_msg(LVL_NOTE, "Enabled 4th and 5th button.");
    148173        }
     174
    149175        /* Enable mouse data reporting. */
    150176        uint8_t report = PS2_MOUSE_ENABLE_DATA_REPORT;
    151         ssize_t size = chardev_write(exch, &report, 1);
    152         if (size != 1) {
     177        size_t nwr;
     178        rc = chardev_write(mouse->chardev, &report, 1, &nwr);
     179        if (rc != EOK) {
    153180                ddf_msg(LVL_ERROR, "Failed to enable data reporting.");
    154                 async_exchange_end(exch);
    155                 ddf_fun_unbind(mouse->mouse_fun);
    156                 ddf_fun_destroy(mouse->mouse_fun);
    157                 return EIO;
    158         }
    159 
    160         size = chardev_read(exch, &report, 1);
    161         async_exchange_end(exch);
    162         if (size != 1 || report != PS2_MOUSE_ACK) {
     181                rc = EIO;
     182                goto error;
     183        }
     184
     185        size_t nread;
     186        rc = chardev_read(mouse->chardev, &report, 1, &nread);
     187        if (rc != EOK || report != PS2_MOUSE_ACK) {
    163188                ddf_msg(LVL_ERROR, "Failed to confirm data reporting: %hhx.",
    164189                    report);
     190                rc = EIO;
     191                goto error;
     192        }
     193
     194        mouse->polling_fibril = fibril_create(polling_f, mouse);
     195        if (mouse->polling_fibril == 0) {
     196                rc = ENOMEM;
     197                goto error;
     198        }
     199
     200        fibril_add_ready(mouse->polling_fibril);
     201        return EOK;
     202error:
     203        if (bound)
    165204                ddf_fun_unbind(mouse->mouse_fun);
     205        if (mouse->mouse_fun != NULL) {
    166206                ddf_fun_destroy(mouse->mouse_fun);
    167                 return EIO;
    168         }
    169 
    170         mouse->polling_fibril = fibril_create(polling_f, mouse);
    171         if (!mouse->polling_fibril) {
    172                 ddf_fun_unbind(mouse->mouse_fun);
    173                 ddf_fun_destroy(mouse->mouse_fun);
    174                 return ENOMEM;
    175         }
    176         fibril_add_ready(mouse->polling_fibril);
     207                mouse->mouse_fun = NULL;
     208        }
     209
     210        chardev_close(mouse->chardev);
     211        mouse->chardev = NULL;
     212        return rc;
     213}
     214
     215/** Read fixed-size mouse packet.
     216 *
     217 * Continue reading until entire packet is received.
     218 *
     219 * @param mouse Mouse device
     220 * @param pbuf Buffer for storing packet
     221 * @param psize Packet size
     222 *
     223 * @return EOK on success or non-zero error code
     224 */
     225static int ps2_mouse_read_packet(ps2_mouse_t *mouse, void *pbuf, size_t psize)
     226{
     227        int rc;
     228        size_t pos;
     229        size_t nread;
     230
     231        pos = 0;
     232        while (pos < psize) {
     233                rc = chardev_read(mouse->chardev, pbuf + pos, psize - pos,
     234                    &nread);
     235                if (rc != EOK) {
     236                        ddf_msg(LVL_WARN, "Error reading packet.");
     237                        return rc;
     238                }
     239
     240                pos += nread;
     241        }
     242
    177243        return EOK;
    178244}
     
    184250int polling_ps2(void *arg)
    185251{
    186         assert(arg);
    187         const ps2_mouse_t *mouse = arg;
    188 
    189         assert(mouse->parent_sess);
     252        ps2_mouse_t *mouse = (ps2_mouse_t *) arg;
     253        int rc;
     254
    190255        bool buttons[PS2_BUTTON_COUNT] = {};
    191         async_exch_t *parent_exch = async_exchange_begin(mouse->parent_sess);
    192256        while (1) {
    193 
    194257                uint8_t packet[PS2_BUFSIZE] = {};
    195                 const ssize_t size =
    196                     chardev_read(parent_exch, packet, PS2_BUFSIZE);
    197 
    198                 if (size != PS2_BUFSIZE) {
    199                         ddf_msg(LVL_WARN, "Incorrect packet size: %zd.", size);
     258                rc = ps2_mouse_read_packet(mouse, packet, PS2_BUFSIZE);
     259                if (rc != EOK)
    200260                        continue;
    201                 }
     261
    202262                ddf_msg(LVL_DEBUG2, "Got packet: %hhx:%hhx:%hhx.",
    203263                    packet[0], packet[1], packet[2]);
     
    232292                async_exchange_end(exch);
    233293        }
    234         async_exchange_end(parent_exch);
     294
     295        return 0;
    235296}
    236297
     
    241302static int polling_intellimouse(void *arg)
    242303{
    243         assert(arg);
    244         const ps2_mouse_t *mouse = arg;
    245 
    246         assert(mouse->parent_sess);
     304        ps2_mouse_t *mouse = (ps2_mouse_t *) arg;
     305        int rc;
     306
    247307        bool buttons[INTELLIMOUSE_BUTTON_COUNT] = {};
    248         async_exch_t *parent_exch = NULL;
    249308        while (1) {
    250                 if (!parent_exch)
    251                         parent_exch = async_exchange_begin(mouse->parent_sess);
    252 
    253309                uint8_t packet[INTELLIMOUSE_BUFSIZE] = {};
    254                 const ssize_t size = chardev_read(
    255                     parent_exch, packet, INTELLIMOUSE_BUFSIZE);
    256 
    257                 if (size != INTELLIMOUSE_BUFSIZE) {
    258                         ddf_msg(LVL_WARN, "Incorrect packet size: %zd.", size);
     310                rc = ps2_mouse_read_packet(mouse, packet, INTELLIMOUSE_BUFSIZE);
     311                if (rc != EOK)
    259312                        continue;
    260                 }
     313
    261314                ddf_msg(LVL_DEBUG2, "Got packet: %hhx:%hhx:%hhx:%hhx.",
    262315                    packet[0], packet[1], packet[2], packet[3]);
     
    310363                async_exchange_end(exch);
    311364        }
    312         async_exchange_end(parent_exch);
     365
     366        return 0;
    313367}
    314368
     
    319373 * See http://www.computer-engineering.org/ps2mouse/ for details.
    320374 */
    321 static int probe_intellimouse(async_exch_t *exch, bool buttons)
    322 {
    323         assert(exch);
    324 
    325         MOUSE_WRITE_BYTE(exch, PS2_MOUSE_SET_SAMPLE_RATE);
    326         MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
    327         MOUSE_WRITE_BYTE(exch, 200);
    328         MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
    329 
    330         MOUSE_WRITE_BYTE(exch, PS2_MOUSE_SET_SAMPLE_RATE);
    331         MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
    332         MOUSE_WRITE_BYTE(exch, buttons ? 200 : 100);
    333         MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
    334 
    335         MOUSE_WRITE_BYTE(exch, PS2_MOUSE_SET_SAMPLE_RATE);
    336         MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
    337         MOUSE_WRITE_BYTE(exch, 80);
    338         MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
    339 
    340         MOUSE_WRITE_BYTE(exch, PS2_MOUSE_GET_DEVICE_ID);
    341         MOUSE_READ_BYTE_TEST(exch, PS2_MOUSE_ACK);
    342         MOUSE_READ_BYTE_TEST(exch, buttons ? 4 : 3);
     375static int probe_intellimouse(ps2_mouse_t *mouse, bool buttons)
     376{
     377        MOUSE_WRITE_BYTE(mouse, PS2_MOUSE_SET_SAMPLE_RATE);
     378        MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
     379        MOUSE_WRITE_BYTE(mouse, 200);
     380        MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
     381
     382        MOUSE_WRITE_BYTE(mouse, PS2_MOUSE_SET_SAMPLE_RATE);
     383        MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
     384        MOUSE_WRITE_BYTE(mouse, buttons ? 200 : 100);
     385        MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
     386
     387        MOUSE_WRITE_BYTE(mouse, PS2_MOUSE_SET_SAMPLE_RATE);
     388        MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
     389        MOUSE_WRITE_BYTE(mouse, 80);
     390        MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
     391
     392        MOUSE_WRITE_BYTE(mouse, PS2_MOUSE_GET_DEVICE_ID);
     393        MOUSE_READ_BYTE_TEST(mouse, PS2_MOUSE_ACK);
     394        MOUSE_READ_BYTE_TEST(mouse, buttons ? 4 : 3);
    343395
    344396        return EOK;
Note: See TracChangeset for help on using the changeset viewer.