Changes in uspace/drv/hid/ps2mouse/ps2mouse.c [dd8ab1c:d420b22] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/hid/ps2mouse/ps2mouse.c
rdd8ab1c rd420b22 1 1 /* 2 2 * Copyright (c) 2011 Jan Vesely 3 * Copyright (c) 2017 Jiri Svoboda4 3 * All rights reserved. 5 4 * … … 31 30 */ 32 31 /** @file 33 * @brief PS/2 mouse driver.32 * @brief ps2 mouse driver. 34 33 */ 35 34 36 35 #include <stdbool.h> 37 36 #include <errno.h> 38 #include <str_error.h>39 37 #include <ddf/log.h> 40 38 #include <io/keycode.h> … … 72 70 #define PS2_BUTTON_MASK(button) (1 << button) 73 71 74 #define MOUSE_READ_BYTE_TEST( mouse, value_) \72 #define MOUSE_READ_BYTE_TEST(sess, value_) \ 75 73 do { \ 76 74 uint8_t value = (value_); \ 77 75 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; \ 83 80 } \ 84 81 if (data != value) { \ … … 89 86 } while (0) 90 87 91 #define MOUSE_WRITE_BYTE( mouse, value_) \88 #define MOUSE_WRITE_BYTE(sess, value_) \ 92 89 do { \ 93 90 uint8_t value = (value_); \ 94 91 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; \ 100 96 } \ 101 97 } while (0) … … 103 99 static int polling_ps2(void *); 104 100 static int polling_intellimouse(void *); 105 static int probe_intellimouse( ps2_mouse_t *, bool);101 static int probe_intellimouse(async_exch_t *, bool); 106 102 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); 107 103 … … 112 108 113 109 /** Initialize mouse driver structure. 114 *115 * Connects to parent, creates keyboard function, starts polling fibril.116 *117 110 * @param kbd Mouse driver structure to initialize. 118 111 * @param dev DDF device structure. 119 112 * 120 * @return EOK on success or non-zero error code113 * Connects to parent, creates keyboard function, starts polling fibril. 121 114 */ 122 115 int ps2_mouse_init(ps2_mouse_t *mouse, ddf_dev_t *dev) 123 116 { 124 async_sess_t *parent_sess;125 bool bound = false;126 int rc;127 128 117 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; 142 121 143 122 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 } 150 126 ddf_fun_set_ops(mouse->mouse_fun, &mouse_ops); 151 127 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 } 166 140 /* Probe IntelliMouse extensions. */ 167 141 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) { 169 144 ddf_msg(LVL_NOTE, "Enabled IntelliMouse extensions"); 170 145 polling_f = polling_intellimouse; 171 if (probe_intellimouse( mouse, true) == EOK)146 if (probe_intellimouse(exch, true) == EOK) 172 147 ddf_msg(LVL_NOTE, "Enabled 4th and 5th button."); 173 148 } 174 175 149 /* Enable mouse data reporting. */ 176 150 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) { 180 153 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) { 188 163 ddf_msg(LVL_ERROR, "Failed to confirm data reporting: %hhx.", 189 164 report); 190 rc = EIO; 191 goto error; 165 ddf_fun_unbind(mouse->mouse_fun); 166 ddf_fun_destroy(mouse->mouse_fun); 167 return EIO; 192 168 } 193 169 194 170 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 } 200 176 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 device220 * @param pbuf Buffer for storing packet221 * @param psize Packet size222 *223 * @return EOK on success or non-zero error code224 */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 243 177 return EOK; 244 178 } … … 250 184 int polling_ps2(void *arg) 251 185 { 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); 255 190 bool buttons[PS2_BUTTON_COUNT] = {}; 191 async_exch_t *parent_exch = async_exchange_begin(mouse->parent_sess); 256 192 while (1) { 193 257 194 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); 260 200 continue; 261 201 } 262 202 ddf_msg(LVL_DEBUG2, "Got packet: %hhx:%hhx:%hhx.", 263 203 packet[0], packet[1], packet[2]); … … 292 232 async_exchange_end(exch); 293 233 } 294 295 return 0; 234 async_exchange_end(parent_exch); 296 235 } 297 236 … … 302 241 static int polling_intellimouse(void *arg) 303 242 { 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); 307 247 bool buttons[INTELLIMOUSE_BUTTON_COUNT] = {}; 248 async_exch_t *parent_exch = NULL; 308 249 while (1) { 250 if (!parent_exch) 251 parent_exch = async_exchange_begin(mouse->parent_sess); 252 309 253 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); 312 259 continue; 313 260 } 314 261 ddf_msg(LVL_DEBUG2, "Got packet: %hhx:%hhx:%hhx:%hhx.", 315 262 packet[0], packet[1], packet[2], packet[3]); … … 363 310 async_exchange_end(exch); 364 311 } 365 366 return 0; 312 async_exchange_end(parent_exch); 367 313 } 368 314 … … 373 319 * See http://www.computer-engineering.org/ps2mouse/ for details. 374 320 */ 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); 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); 395 343 396 344 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.