source: mainline/uspace/drv/hid/adb-kbd/adb-kbd.c@ 5a6cc679

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5a6cc679 was 5a6cc679, checked in by Jenda <jenda.jzqk73@…>, 8 years ago

Merge commit '50f19b7ee8e94570b5c63896736c4eb49cfa18db' into forwardport

Not all ints are converted to errno_t in xhci tree yet, however it compiles and works :)

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/*
2 * Copyright (c) 2011 Jiri Svoboda
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 keyboard port driver.
31 */
32
33#include <async.h>
34#include <ddf/log.h>
35#include <errno.h>
36#include <io/console.h>
37#include <ipc/adb.h>
38#include <ipc/kbdev.h>
39#include <loc.h>
40#include <vfs/vfs.h>
41
42#include "adb-kbd.h"
43#include "ctl.h"
44
45static void adb_kbd_events(ipc_callid_t, ipc_call_t *, void *);
46static void adb_kbd_reg0_data(adb_kbd_t *, uint16_t);
47static void adb_kbd_conn(ipc_callid_t, ipc_call_t *, void *);
48
49/** Add ADB keyboard device */
50errno_t adb_kbd_add(adb_kbd_t *kbd)
51{
52 errno_t rc;
53 bool bound = false;
54
55 kbd->fun = ddf_fun_create(kbd->dev, fun_exposed, "a");
56 if (kbd->fun == NULL) {
57 ddf_msg(LVL_ERROR, "Error creating function");
58 rc = ENOMEM;
59 goto error;
60 }
61
62 kbd->parent_sess = ddf_dev_parent_sess_get(kbd->dev);
63 if (kbd->parent_sess == NULL) {
64 ddf_msg(LVL_ERROR, "Error connecting parent driver");
65 rc = EIO;
66 goto error;
67 }
68
69 async_exch_t *exch = async_exchange_begin(kbd->parent_sess);
70 if (exch == NULL) {
71 ddf_msg(LVL_ERROR, "Error starting exchange with parent");
72 rc = ENOMEM;
73 goto error;
74 }
75
76 port_id_t port;
77 rc = async_create_callback_port(exch, INTERFACE_ADB_CB, 0, 0,
78 adb_kbd_events, kbd, &port);
79
80 async_exchange_end(exch);
81 if (rc != EOK) {
82 ddf_msg(LVL_ERROR, "Error creating callback from device");
83 goto error;
84 }
85
86 ddf_fun_set_conn_handler(kbd->fun, adb_kbd_conn);
87
88 rc = ddf_fun_bind(kbd->fun);
89 if (rc != EOK) {
90 ddf_msg(LVL_ERROR, "Error binding function");
91 goto error;
92 }
93
94 bound = true;
95
96 rc = ddf_fun_add_to_category(kbd->fun, "keyboard");
97 if (rc != EOK) {
98 ddf_msg(LVL_ERROR, "Error adding function to category");
99 goto error;
100 }
101
102 return EOK;
103error:
104 if (bound)
105 ddf_fun_unbind(kbd->fun);
106
107 if (kbd->parent_sess != NULL) {
108 async_hangup(kbd->parent_sess);
109 kbd->parent_sess = NULL;
110 }
111
112 if (kbd->fun != NULL) {
113 ddf_fun_destroy(kbd->fun);
114 kbd->fun = NULL;
115 }
116
117 return rc;
118}
119
120/** Remove ADB keyboard device */
121errno_t adb_kbd_remove(adb_kbd_t *con)
122{
123 return ENOTSUP;
124}
125
126/** ADB keyboard device gone */
127errno_t adb_kbd_gone(adb_kbd_t *con)
128{
129 return ENOTSUP;
130}
131
132static void adb_kbd_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
133{
134 adb_kbd_t *kbd = (adb_kbd_t *) arg;
135
136 /* Ignore parameters, the connection is already opened */
137 while (true) {
138
139 ipc_call_t call;
140 ipc_callid_t callid = async_get_call(&call);
141
142 errno_t retval = EOK;
143
144 if (!IPC_GET_IMETHOD(call)) {
145 /* TODO: Handle hangup */
146 return;
147 }
148
149 switch (IPC_GET_IMETHOD(call)) {
150 case ADB_REG_NOTIF:
151 adb_kbd_reg0_data(kbd, IPC_GET_ARG1(call));
152 break;
153 default:
154 retval = ENOENT;
155 }
156 async_answer_0(callid, retval);
157 }
158}
159
160static void adb_kbd_data(adb_kbd_t *kbd, uint8_t b)
161{
162 kbd_event_type_t etype;
163 unsigned int key;
164 errno_t rc;
165
166 rc = adb_kbd_key_translate(b, &etype, &key);
167 if (rc != EOK)
168 return;
169
170 if (kbd->client_sess == NULL)
171 return;
172
173 async_exch_t *exch = async_exchange_begin(kbd->client_sess);
174 async_msg_4(exch, KBDEV_EVENT, etype, key, 0, 0);
175 async_exchange_end(exch);
176}
177
178static void adb_kbd_reg0_data(adb_kbd_t *kbd, uint16_t data)
179{
180 uint8_t b0 = (data >> 8) & 0xff;
181 uint8_t b1 = data & 0xff;
182
183 if (b0 != 0xff)
184 adb_kbd_data(kbd, b0);
185
186 if (b1 != 0xff)
187 adb_kbd_data(kbd, b1);
188 (void)b0; (void)b1;
189}
190
191/** Handle client connection */
192static void adb_kbd_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
193{
194 ipc_callid_t callid;
195 ipc_call_t call;
196 sysarg_t method;
197 adb_kbd_t *kbd;
198
199 /*
200 * Answer the first IPC_M_CONNECT_ME_TO call.
201 */
202 async_answer_0(iid, EOK);
203
204 kbd = (adb_kbd_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
205
206 while (true) {
207 callid = async_get_call(&call);
208 method = IPC_GET_IMETHOD(call);
209
210 if (!method) {
211 /* The other side has hung up. */
212 async_answer_0(callid, EOK);
213 return;
214 }
215
216 async_sess_t *sess =
217 async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
218 if (sess != NULL) {
219 kbd->client_sess = sess;
220 async_answer_0(callid, EOK);
221 } else {
222 async_answer_0(callid, EINVAL);
223 }
224 }
225}
226
227/**
228 * @}
229 */
Note: See TracBrowser for help on using the repository browser.