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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b4b534ac was b4b534ac, checked in by Jakub Jermar <jakub@…>, 9 years ago

Merge from lp:~jan.vesely/helenos/usb

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