source: mainline/uspace/app/mkbd/main.c@ 07b7c48

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 07b7c48 was 07b7c48, checked in by Jiri Svoboda <jiri@…>, 12 years ago

Extend console library API to support different event types.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Copyright (c) 2011 Lubos Slovak
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/** @addtogroup mkbd
30 * @{
31 */
32/**
33 * @file
34 * Sample application using the data from multimedia keys on keyboard
35 */
36
37#include <inttypes.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <errno.h>
41#include <str_error.h>
42#include <stdbool.h>
43#include <getopt.h>
44#include <devman.h>
45#include <loc.h>
46#include <usb/dev/hub.h>
47#include <usb/hid/iface.h>
48#include <usb/dev/pipes.h>
49#include <async.h>
50#include <usb/dev.h>
51#include <usb/hid/usages/core.h>
52#include <usb/hid/hidparser.h>
53#include <usb/hid/hiddescriptor.h>
54#include <usb/hid/usages/consumer.h>
55#include <io/console.h>
56#include <io/keycode.h>
57#include <assert.h>
58
59#define NAME "mkbd"
60
61static async_sess_t *dev_sess = NULL;
62
63static int initialize_report_parser(async_sess_t *dev_sess,
64 usb_hid_report_t **report)
65{
66 *report = (usb_hid_report_t *) malloc(sizeof(usb_hid_report_t));
67 if (*report == NULL)
68 return ENOMEM;
69
70 int rc = usb_hid_report_init(*report);
71 if (rc != EOK) {
72 usb_hid_report_deinit(*report);
73 *report = NULL;
74 return rc;
75 }
76
77 /* Get the report descriptor length from the device */
78 size_t report_desc_size;
79 rc = usbhid_dev_get_report_descriptor_length(dev_sess,
80 &report_desc_size);
81 if (rc != EOK) {
82 usb_hid_report_deinit(*report);
83 *report = NULL;
84 return rc;
85 }
86
87 if (report_desc_size == 0) {
88 usb_hid_report_deinit(*report);
89 *report = NULL;
90 // TODO: other error code?
91 return EINVAL;
92 }
93
94 uint8_t *desc = (uint8_t *) malloc(report_desc_size);
95 if (desc == NULL) {
96 usb_hid_report_deinit(*report);
97 *report = NULL;
98 return ENOMEM;
99 }
100
101 /* Get the report descriptor from the device */
102 size_t actual_size;
103 rc = usbhid_dev_get_report_descriptor(dev_sess, desc, report_desc_size,
104 &actual_size);
105 if (rc != EOK) {
106 usb_hid_report_deinit(*report);
107 *report = NULL;
108 free(desc);
109 return rc;
110 }
111
112 if (actual_size != report_desc_size) {
113 usb_hid_report_deinit(*report);
114 *report = NULL;
115 free(desc);
116 // TODO: other error code?
117 return EINVAL;
118 }
119
120 /* Initialize the report parser */
121
122 rc = usb_hid_parse_report_descriptor(*report, desc, report_desc_size);
123 free(desc);
124
125 if (rc != EOK) {
126 free(desc);
127 return rc;
128 }
129
130 return EOK;
131}
132
133static void print_key(uint8_t *buffer, size_t size, usb_hid_report_t *report)
134{
135 assert(buffer != NULL);
136 assert(report != NULL);
137
138 uint8_t report_id;
139 int rc = usb_hid_parse_report(report, buffer, size, &report_id);
140 if (rc != EOK)
141 return;
142
143 usb_hid_report_path_t *path = usb_hid_report_path();
144 if (path == NULL) {
145 return;
146 }
147
148 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
149
150 usb_hid_report_path_set_report_id(path, report_id);
151
152 usb_hid_report_field_t *field = usb_hid_report_get_sibling(
153 report, NULL, path, USB_HID_PATH_COMPARE_END
154 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
155 USB_HID_REPORT_TYPE_INPUT);
156
157 while (field != NULL) {
158 if (field->value != 0) {
159 const char *key_str =
160 usbhid_multimedia_usage_to_str(field->usage);
161 printf("Pressed key: %s\n", key_str);
162 }
163
164 field = usb_hid_report_get_sibling(
165 report, field, path, USB_HID_PATH_COMPARE_END
166 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
167 USB_HID_REPORT_TYPE_INPUT);
168 }
169
170 usb_hid_report_path_free(path);
171}
172
173static int wait_for_quit_fibril(void *arg)
174{
175 console_ctrl_t *con = console_init(stdin, stdout);
176
177 printf("Press <ESC> to quit the application.\n");
178
179 while (1) {
180 cons_event_t ev;
181 bool ok = console_get_event(con, &ev);
182 if (!ok) {
183 printf("Connection with console broken: %s.\n",
184 str_error(errno));
185 break;
186 }
187
188 if (ev.type == CEV_KEY && ev.ev.key.type == KEY_PRESS &&
189 ev.ev.key.key == KC_ESCAPE) {
190 break;
191 }
192 }
193
194 console_done(con);
195
196 exit(0);
197
198 return EOK;
199}
200
201#define MAX_PATH_LENGTH 1024
202
203static void print_usage(char *app_name)
204{
205#define _INDENT " "
206 printf(NAME ": Print out what multimedia keys were pressed.\n\n");
207 printf("Usage: %s device\n", app_name);
208 printf(_INDENT "The device is a devman path to the device.\n");
209#undef _OPTION
210#undef _INDENT
211}
212
213int main(int argc, char *argv[])
214{
215 int act_event = -1;
216
217 if (argc <= 1) {
218 print_usage(argv[0]);
219 return -1;
220 }
221
222 char *devpath = argv[1];
223
224 devman_handle_t dev_handle = 0;
225
226 int rc = usb_resolve_device_handle(devpath, NULL, NULL, &dev_handle);
227 if (rc != EOK) {
228 printf("Device not found or not of USB kind: %s.\n",
229 str_error(rc));
230 return rc;
231 }
232
233 async_sess_t *sess = devman_device_connect(EXCHANGE_SERIALIZE,
234 dev_handle, 0);
235 if (!sess) {
236 printf(NAME ": failed to connect to the device (handle %"
237 PRIun "): %s.\n", dev_handle, str_error(errno));
238 return errno;
239 }
240
241 dev_sess = sess;
242
243 char path[MAX_PATH_LENGTH];
244 rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
245 if (rc != EOK) {
246 return ENOMEM;
247 }
248
249 printf("Device path: %s\n", path);
250
251
252 usb_hid_report_t *report = NULL;
253 rc = initialize_report_parser(dev_sess, &report);
254 if (rc != EOK) {
255 printf("Failed to initialize report parser: %s\n",
256 str_error(rc));
257 return rc;
258 }
259
260 assert(report != NULL);
261
262 size_t size;
263 rc = usbhid_dev_get_event_length(dev_sess, &size);
264 if (rc != EOK) {
265 printf("Failed to get event length: %s.\n", str_error(rc));
266 return rc;
267 }
268
269 uint8_t *event = (uint8_t *)malloc(size);
270 if (event == NULL) {
271 // TODO: hangup phone?
272 return ENOMEM;
273 }
274
275 fid_t quit_fibril = fibril_create(wait_for_quit_fibril, NULL);
276 if (quit_fibril == 0) {
277 printf("Failed to start extra fibril.\n");
278 return -1;
279 }
280 fibril_add_ready(quit_fibril);
281
282 size_t actual_size;
283 int event_nr;
284
285 while (true) {
286 /** @todo Try blocking call. */
287 rc = usbhid_dev_get_event(dev_sess, event, size, &actual_size,
288 &event_nr, 0);
289 if (rc != EOK) {
290 // TODO: hangup phone?
291 printf("Error in getting event from the HID driver:"
292 "%s.\n", str_error(rc));
293 break;
294 }
295
296 if (event_nr > act_event) {
297 print_key(event, size, report);
298 act_event = event_nr;
299 }
300
301 async_usleep(10000);
302 }
303
304 return 0;
305}
306
307/** @}
308 */
Note: See TracBrowser for help on using the repository browser.