source: mainline/uspace/app/mkbd/main.c@ b8b64a8

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

Avoid infinite loop when console communication is broken

Need to make sure callers of console_get_event_timeout() can distinguish
between timeout and I/O error. Fix all callers of console_get_event()
and console_get_event_timeout() not to enter infinite loop when console
connection is broken. Also avoid setting of errno variable.

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