source: mainline/uspace/app/mkbd/main.c@ 764d71e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 764d71e was 2176ed6, checked in by Lubos Slovak <lubos.slovak@…>, 15 years ago

Fixes in HID (subdriver matching, multimedi key mapping, etc.)

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