Ignore:
File:
1 edited

Legend:

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

    rdd8ab1c rd420b22  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
    3  * Copyright (c) 2017 Jiri Svoboda
    43 * All rights reserved.
    54 *
     
    3130 */
    3231/** @file
    33  * @brief PS/2 mouse driver.
     32 * @brief ps2 mouse driver.
    3433 */
    3534
    3635#include <stdbool.h>
    3736#include <errno.h>
    38 #include <str_error.h>
    3937#include <ddf/log.h>
    4038#include <io/keycode.h>
     
    7270#define PS2_BUTTON_MASK(button) (1 << button)
    7371
    74 #define MOUSE_READ_BYTE_TEST(mouse, value_) \
     72#define MOUSE_READ_BYTE_TEST(sess, value_) \
    7573do { \
    7674        uint8_t value = (value_); \
    7775        uint8_t data = 0; \
    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; \
     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; \
    8380        } \
    8481        if (data != value) { \
     
    8986} while (0)
    9087
    91 #define MOUSE_WRITE_BYTE(mouse, value_) \
     88#define MOUSE_WRITE_BYTE(sess, value_) \
    9289do { \
    9390        uint8_t value = (value_); \
    9491        uint8_t data = (value); \
    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; \
     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; \
    10096        } \
    10197} while (0)
     
    10399static int polling_ps2(void *);
    104100static int polling_intellimouse(void *);
    105 static int probe_intellimouse(ps2_mouse_t *, bool);
     101static int probe_intellimouse(async_exch_t *, bool);
    106102static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
    107103
     
    112108
    113109/** Initialize mouse driver structure.
    114  *
    115  * Connects to parent, creates keyboard function, starts polling fibril.
    116  *
    117110 * @param kbd Mouse driver structure to initialize.
    118111 * @param dev DDF device structure.
    119112 *
    120  * @return EOK on success or non-zero error code
     113 * Connects to parent, creates keyboard function, starts polling fibril.
    121114 */
    122115int ps2_mouse_init(ps2_mouse_t *mouse, ddf_dev_t *dev)
    123116{
    124         async_sess_t *parent_sess;
    125         bool bound = false;
    126         int rc;
    127 
    128117        mouse->client_sess = NULL;
    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         }
     118        mouse->parent_sess = ddf_dev_parent_sess_get(dev);
     119        if (!mouse->parent_sess)
     120                return ENOMEM;
    142121
    143122        mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse");
    144         if (mouse->mouse_fun == NULL) {
    145                 ddf_msg(LVL_ERROR, "Error creating mouse function.");
    146                 rc = ENOMEM;
    147                 goto error;
    148         }
    149 
     123        if (!mouse->mouse_fun) {
     124                return ENOMEM;
     125        }
    150126        ddf_fun_set_ops(mouse->mouse_fun, &mouse_ops);
    151127
    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 
     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        }
    166140        /* Probe IntelliMouse extensions. */
    167141        int (*polling_f)(void*) = polling_ps2;
    168         if (probe_intellimouse(mouse, false) == EOK) {
     142        async_exch_t *exch = async_exchange_begin(mouse->parent_sess);
     143        if (probe_intellimouse(exch, false) == EOK) {
    169144                ddf_msg(LVL_NOTE, "Enabled IntelliMouse extensions");
    170145                polling_f = polling_intellimouse;
    171                 if (probe_intellimouse(mouse, true) == EOK)
     146                if (probe_intellimouse(exch, true) == EOK)
    172147                        ddf_msg(LVL_NOTE, "Enabled 4th and 5th button.");
    173148        }
    174 
    175149        /* Enable mouse data reporting. */
    176150        uint8_t report = PS2_MOUSE_ENABLE_DATA_REPORT;
    177         size_t nwr;
    178         rc = chardev_write(mouse->chardev, &report, 1, &nwr);
    179         if (rc != EOK) {
     151        ssize_t size = chardev_write(exch, &report, 1);
     152        if (size != 1) {
    180153                ddf_msg(LVL_ERROR, "Failed to enable data reporting.");
    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) {
     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) {
    188163                ddf_msg(LVL_ERROR, "Failed to confirm data reporting: %hhx.",
    189164                    report);
    190                 rc = EIO;
    191                 goto error;
     165                ddf_fun_unbind(mouse->mouse_fun);
     166                ddf_fun_destroy(mouse->mouse_fun);
     167                return EIO;
    192168        }
    193169
    194170        mouse->polling_fibril = fibril_create(polling_f, mouse);
    195         if (mouse->polling_fibril == 0) {
    196                 rc = ENOMEM;
    197                 goto error;
    198         }
    199 
     171        if (!mouse->polling_fibril) {
     172                ddf_fun_unbind(mouse->mouse_fun);
     173                ddf_fun_destroy(mouse->mouse_fun);
     174                return ENOMEM;
     175        }
    200176        fibril_add_ready(mouse->polling_fibril);
    201         return EOK;
    202 error:
    203         if (bound)
    204                 ddf_fun_unbind(mouse->mouse_fun);
    205         if (mouse->mouse_fun != NULL) {
    206                 ddf_fun_destroy(mouse->mouse_fun);
    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  */
    225 static 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 
    243177        return EOK;
    244178}
     
    250184int polling_ps2(void *arg)
    251185{
    252         ps2_mouse_t *mouse = (ps2_mouse_t *) arg;
    253         int rc;
    254 
     186        assert(arg);
     187        const ps2_mouse_t *mouse = arg;
     188
     189        assert(mouse->parent_sess);
    255190        bool buttons[PS2_BUTTON_COUNT] = {};
     191        async_exch_t *parent_exch = async_exchange_begin(mouse->parent_sess);
    256192        while (1) {
     193
    257194                uint8_t packet[PS2_BUFSIZE] = {};
    258                 rc = ps2_mouse_read_packet(mouse, packet, PS2_BUFSIZE);
    259                 if (rc != EOK)
     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);
    260200                        continue;
    261 
     201                }
    262202                ddf_msg(LVL_DEBUG2, "Got packet: %hhx:%hhx:%hhx.",
    263203                    packet[0], packet[1], packet[2]);
     
    292232                async_exchange_end(exch);
    293233        }
    294 
    295         return 0;
     234        async_exchange_end(parent_exch);
    296235}
    297236
     
    302241static int polling_intellimouse(void *arg)
    303242{
    304         ps2_mouse_t *mouse = (ps2_mouse_t *) arg;
    305         int rc;
    306 
     243        assert(arg);
     244        const ps2_mouse_t *mouse = arg;
     245
     246        assert(mouse->parent_sess);
    307247        bool buttons[INTELLIMOUSE_BUTTON_COUNT] = {};
     248        async_exch_t *parent_exch = NULL;
    308249        while (1) {
     250                if (!parent_exch)
     251                        parent_exch = async_exchange_begin(mouse->parent_sess);
     252
    309253                uint8_t packet[INTELLIMOUSE_BUFSIZE] = {};
    310                 rc = ps2_mouse_read_packet(mouse, packet, INTELLIMOUSE_BUFSIZE);
    311                 if (rc != EOK)
     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);
    312259                        continue;
    313 
     260                }
    314261                ddf_msg(LVL_DEBUG2, "Got packet: %hhx:%hhx:%hhx:%hhx.",
    315262                    packet[0], packet[1], packet[2], packet[3]);
     
    363310                async_exchange_end(exch);
    364311        }
    365 
    366         return 0;
     312        async_exchange_end(parent_exch);
    367313}
    368314
     
    373319 * See http://www.computer-engineering.org/ps2mouse/ for details.
    374320 */
    375 static 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);
     321static 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);
    395343
    396344        return EOK;
Note: See TracChangeset for help on using the changeset viewer.