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