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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ae45201 was 79ae36dd, checked in by Martin Decky <martin@…>, 15 years ago

new async framework with integrated exchange tracking

  • strict isolation between low-level IPC and high-level async framework with integrated exchange tracking
    • each IPC connection is represented by an async_sess_t structure
    • each IPC exchange is represented by an async_exch_t structure
    • exchange management is either based on atomic messages (EXCHANGE_ATOMIC), locking (EXCHANGE_SERIALIZE) or connection cloning (EXCHANGE_CLONE)
  • async_obsolete: temporary compatibility layer to keep old async clients working (several pieces of code are currently broken, but only non-essential functionality)
  • IPC_M_PHONE_HANGUP is now method no. 0 (for elegant boolean evaluation)
  • IPC_M_DEBUG_ALL has been renamed to IPC_M_DEBUG
  • IPC_M_PING has been removed (VFS protocol now has VFS_IN_PING)
  • console routines in libc have been rewritten for better abstraction
  • additional use for libc-private header files (FILE structure opaque to the client)
  • various cstyle changes (typos, indentation, missing externs in header files, improved comments, etc.)
  • Property mode set to 100644
File size: 6.5 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 <bool.h>
43#include <getopt.h>
44#include <devman.h>
45#include <devmap.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/hid/usages/core.h>
51#include <usb/hid/hidparser.h>
52#include <usb/hid/hiddescriptor.h>
53#include <usb/hid/usages/consumer.h>
54#include <assert.h>
55
56#define NAME "mkbd"
57
58static async_sess_t *dev_sess = NULL;
59
60static int initialize_report_parser(async_sess_t *dev_sess,
61 usb_hid_report_t **report)
62{
63 *report = (usb_hid_report_t *) malloc(sizeof(usb_hid_report_t));
64 if (*report == NULL)
65 return ENOMEM;
66
67 int rc = usb_hid_report_init(*report);
68 if (rc != EOK) {
69 usb_hid_free_report(*report);
70 *report = NULL;
71 return rc;
72 }
73
74 /* Get the report descriptor length from the device */
75 size_t report_desc_size;
76 rc = usbhid_dev_get_report_descriptor_length(dev_sess,
77 &report_desc_size);
78 if (rc != EOK) {
79 usb_hid_free_report(*report);
80 *report = NULL;
81 return rc;
82 }
83
84 if (report_desc_size == 0) {
85 usb_hid_free_report(*report);
86 *report = NULL;
87 // TODO: other error code?
88 return EINVAL;
89 }
90
91 uint8_t *desc = (uint8_t *) malloc(report_desc_size);
92 if (desc == NULL) {
93 usb_hid_free_report(*report);
94 *report = NULL;
95 return ENOMEM;
96 }
97
98 /* Get the report descriptor from the device */
99 size_t actual_size;
100 rc = usbhid_dev_get_report_descriptor(dev_sess, desc, report_desc_size,
101 &actual_size);
102 if (rc != EOK) {
103 usb_hid_free_report(*report);
104 *report = NULL;
105 free(desc);
106 return rc;
107 }
108
109 if (actual_size != report_desc_size) {
110 usb_hid_free_report(*report);
111 *report = NULL;
112 free(desc);
113 // TODO: other error code?
114 return EINVAL;
115 }
116
117 /* Initialize the report parser */
118
119 rc = usb_hid_parse_report_descriptor(*report, desc, report_desc_size);
120 free(desc);
121
122 if (rc != EOK) {
123 free(desc);
124 return rc;
125 }
126
127 return EOK;
128}
129
130static void print_key(uint8_t *buffer, size_t size, usb_hid_report_t *report)
131{
132 assert(buffer != NULL);
133 assert(report != NULL);
134
135 uint8_t report_id;
136 int rc = usb_hid_parse_report(report, buffer, size, &report_id);
137 if (rc != EOK)
138 return;
139
140 usb_hid_report_path_t *path = usb_hid_report_path();
141 if (path == NULL) {
142 return;
143 }
144
145 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
146
147 usb_hid_report_path_set_report_id(path, report_id);
148
149 usb_hid_report_field_t *field = usb_hid_report_get_sibling(
150 report, NULL, path, USB_HID_PATH_COMPARE_END
151 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
152 USB_HID_REPORT_TYPE_INPUT);
153
154 while (field != NULL) {
155 if (field->value != 0) {
156 const char *key_str =
157 usbhid_multimedia_usage_to_str(field->usage);
158 printf("Pressed key: %s\n", key_str);
159 }
160
161 field = usb_hid_report_get_sibling(
162 report, field, path, USB_HID_PATH_COMPARE_END
163 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
164 USB_HID_REPORT_TYPE_INPUT);
165 }
166
167 usb_hid_report_path_free(path);
168}
169
170#define MAX_PATH_LENGTH 1024
171
172static void print_usage(char *app_name)
173{
174#define _INDENT " "
175 printf(NAME ": Print out what multimedia keys were pressed.\n\n");
176 printf("Usage: %s device\n", app_name);
177 printf(_INDENT "The device is a devman path to the device.\n");
178#undef _OPTION
179#undef _INDENT
180}
181
182int main(int argc, char *argv[])
183{
184 int act_event = -1;
185
186 if (argc <= 1) {
187 print_usage(argv[0]);
188 return -1;
189 }
190
191 char *devpath = argv[1];
192
193 devman_handle_t dev_handle = 0;
194
195 int rc = usb_resolve_device_handle(devpath, NULL, NULL, &dev_handle);
196 if (rc != EOK) {
197 printf("Device not found or not of USB kind: %s.\n",
198 str_error(rc));
199 return rc;
200 }
201
202 async_sess_t *sess = devman_device_connect(EXCHANGE_SERIALIZE,
203 dev_handle, 0);
204 if (!sess) {
205 printf(NAME ": failed to connect to the device (handle %"
206 PRIun "): %s.\n", dev_handle, str_error(errno));
207 return errno;
208 }
209
210 dev_sess = sess;
211
212 char path[MAX_PATH_LENGTH];
213 rc = devman_get_device_path(dev_handle, path, MAX_PATH_LENGTH);
214 if (rc != EOK) {
215 return ENOMEM;
216 }
217
218 printf("Device path: %s\n", path);
219
220
221 usb_hid_report_t *report = NULL;
222 rc = initialize_report_parser(dev_sess, &report);
223 if (rc != EOK) {
224 printf("Failed to initialize report parser: %s\n",
225 str_error(rc));
226 return rc;
227 }
228
229 assert(report != NULL);
230
231 size_t size;
232 rc = usbhid_dev_get_event_length(dev_sess, &size);
233 if (rc != EOK) {
234 printf("Failed to get event length: %s.\n", str_error(rc));
235 return rc;
236 }
237
238 uint8_t *event = (uint8_t *)malloc(size);
239 if (event == NULL) {
240 // TODO: hangup phone?
241 return ENOMEM;
242 }
243
244 size_t actual_size;
245 int event_nr;
246
247 while (true) {
248 /** @todo Try blocking call. */
249 rc = usbhid_dev_get_event(dev_sess, event, size, &actual_size,
250 &event_nr, 0);
251 if (rc != EOK) {
252 // TODO: hangup phone?
253 printf("Error in getting event from the HID driver:"
254 "%s.\n", str_error(rc));
255 break;
256 }
257
258 if (event_nr > act_event) {
259 print_key(event, size, report);
260 act_event = event_nr;
261 }
262
263 async_usleep(10000);
264 }
265
266 return 0;
267}
268
269/** @}
270 */
Note: See TracBrowser for help on using the repository browser.