source: mainline/uspace/drv/hid/adb-mouse/adb-mouse.c@ 09ab0a9a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 09ab0a9a was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Copyright (c) 2011 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file
30 * @brief ADB mouse driver
31 */
32
33#include <async.h>
34#include <ddf/log.h>
35#include <errno.h>
36#include <ipc/adb.h>
37#include <ipc/mouseev.h>
38#include <loc.h>
39#include <stdio.h>
40
41#include "adb-mouse.h"
42
43static void adb_mouse_conn(ipc_call_t *, void *);
44
45static void adb_mouse_event_button(adb_mouse_t *mouse, int bnum, int bpress)
46{
47 async_exch_t *exch = async_exchange_begin(mouse->client_sess);
48 async_msg_2(exch, MOUSEEV_BUTTON_EVENT, bnum, bpress);
49 async_exchange_end(exch);
50}
51
52static void adb_mouse_event_move(adb_mouse_t *mouse, int dx, int dy, int dz)
53{
54 async_exch_t *exch = async_exchange_begin(mouse->client_sess);
55 async_msg_3(exch, MOUSEEV_MOVE_EVENT, dx, dy, dz);
56 async_exchange_end(exch);
57}
58
59/** Process mouse data */
60static void adb_mouse_data(adb_mouse_t *mouse, sysarg_t data)
61{
62 bool b1, b2;
63 uint16_t udx, udy;
64 int dx, dy;
65
66 /* Extract fields. */
67 b1 = ((data >> 15) & 1) == 0;
68 udy = (data >> 8) & 0x7f;
69 b2 = ((data >> 7) & 1) == 0;
70 udx = data & 0x7f;
71
72 /* Decode 7-bit two's complement signed values. */
73 dx = (udx & 0x40) ? (udx - 0x80) : udx;
74 dy = (udy & 0x40) ? (udy - 0x80) : udy;
75
76 if (b1 != mouse->b1_pressed) {
77 adb_mouse_event_button(mouse, 1, b1);
78 mouse->b1_pressed = b1;
79 }
80
81 if (b2 != mouse->b2_pressed) {
82 adb_mouse_event_button(mouse, 2, b2);
83 mouse->b2_pressed = b2;
84 }
85
86 if (dx != 0 || dy != 0)
87 adb_mouse_event_move(mouse, dx, dy, 0);
88}
89
90static void adb_mouse_events(ipc_call_t *icall, void *arg)
91{
92 adb_mouse_t *mouse = (adb_mouse_t *) arg;
93
94 /* Ignore parameters, the connection is already opened */
95 while (true) {
96 ipc_call_t call;
97 async_get_call(&call);
98
99 errno_t retval = EOK;
100
101 if (!IPC_GET_IMETHOD(call)) {
102 /* TODO: Handle hangup */
103 return;
104 }
105
106 switch (IPC_GET_IMETHOD(call)) {
107 case ADB_REG_NOTIF:
108 adb_mouse_data(mouse, IPC_GET_ARG1(call));
109 break;
110 default:
111 retval = ENOENT;
112 }
113
114 async_answer_0(&call, retval);
115 }
116}
117
118/** Add ADB mouse device */
119errno_t adb_mouse_add(adb_mouse_t *mouse)
120{
121 errno_t rc;
122 bool bound = false;
123
124 mouse->fun = ddf_fun_create(mouse->dev, fun_exposed, "a");
125 if (mouse->fun == NULL) {
126 ddf_msg(LVL_ERROR, "Error creating function");
127 rc = ENOMEM;
128 goto error;
129 }
130
131 mouse->parent_sess = ddf_dev_parent_sess_get(mouse->dev);
132 if (mouse->parent_sess == NULL) {
133 ddf_msg(LVL_ERROR, "Error connecting parent driver");
134 rc = EIO;
135 goto error;
136 }
137
138 async_exch_t *exch = async_exchange_begin(mouse->parent_sess);
139 if (exch == NULL) {
140 ddf_msg(LVL_ERROR, "Error starting exchange with parent");
141 rc = ENOMEM;
142 goto error;
143 }
144
145 port_id_t port;
146 rc = async_create_callback_port(exch, INTERFACE_ADB_CB, 0, 0,
147 adb_mouse_events, mouse, &port);
148
149 async_exchange_end(exch);
150 if (rc != EOK) {
151 ddf_msg(LVL_ERROR, "Error creating callback from device");
152 goto error;
153 }
154
155 ddf_fun_set_conn_handler(mouse->fun, adb_mouse_conn);
156
157 rc = ddf_fun_bind(mouse->fun);
158 if (rc != EOK) {
159 ddf_msg(LVL_ERROR, "Error binding function");
160 goto error;
161 }
162
163 bound = true;
164
165 rc = ddf_fun_add_to_category(mouse->fun, "mouse");
166 if (rc != EOK) {
167 ddf_msg(LVL_ERROR, "Error adding function to category");
168 goto error;
169 }
170
171 return EOK;
172error:
173 if (bound)
174 ddf_fun_unbind(mouse->fun);
175
176 if (mouse->parent_sess != NULL) {
177 async_hangup(mouse->parent_sess);
178 mouse->parent_sess = NULL;
179 }
180
181 if (mouse->fun != NULL) {
182 ddf_fun_destroy(mouse->fun);
183 mouse->fun = NULL;
184 }
185
186 return rc;
187}
188
189/** Remove ADB mouse device */
190errno_t adb_mouse_remove(adb_mouse_t *con)
191{
192 return ENOTSUP;
193}
194
195/** ADB mouse device gone */
196errno_t adb_mouse_gone(adb_mouse_t *con)
197{
198 return ENOTSUP;
199}
200
201/** Handle client connection */
202static void adb_mouse_conn(ipc_call_t *icall, void *arg)
203{
204 ipc_call_t call;
205 sysarg_t method;
206 adb_mouse_t *mouse;
207
208 /*
209 * Answer the first IPC_M_CONNECT_ME_TO call.
210 */
211 async_answer_0(icall, EOK);
212
213 mouse = (adb_mouse_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
214
215 while (true) {
216 async_get_call(&call);
217 method = IPC_GET_IMETHOD(call);
218
219 if (!method) {
220 /* The other side has hung up. */
221 async_answer_0(&call, EOK);
222 return;
223 }
224
225 async_sess_t *sess =
226 async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
227 if (sess != NULL) {
228 mouse->client_sess = sess;
229 async_answer_0(&call, EOK);
230 } else {
231 async_answer_0(&call, EINVAL);
232 }
233 }
234}
235
236/**
237 * @}
238 */
Note: See TracBrowser for help on using the repository browser.