source: mainline/uspace/drv/hid/usbhid/main.c@ 7dddd7b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7dddd7b was 7dddd7b, checked in by Petr Manek <petr.manek@…>, 8 years ago

usbdev: refactor polling

Until now, device polling had to be executed by calling one of four
proxy functions, which served as a syntax sugar and had no clear
distinction between each other (not to mention misleading names and high
number of arguments).

In this commit, the four mentioned functions are discarded in favor of
one main function, which was proxied by them either way. The number of
arguments have decreased in favor of named struct fields in the auto
polling config structure.

Drivers, which make use of polling, such as usbhid and usbhub were
updated to the latest API design.

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2010 Vojtech Horky
3 * Copyright (c) 2011 Lubos Slovak
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup drvusbhid
31 * @{
32 */
33/**
34 * @file
35 * Main routines of USB HID driver.
36 */
37
38#include <ddf/driver.h>
39#include <usb/debug.h>
40#include <errno.h>
41#include <str_error.h>
42#include <fibril_synch.h>
43
44#include <usb/dev/driver.h>
45#include <usb/dev/poll.h>
46
47#include "usbhid.h"
48
49#define NAME "usbhid"
50
51/**
52 * Callback for passing a new device to the driver.
53 *
54 * @note Currently, only boot-protocol keyboards are supported by this driver.
55 *
56 * @param dev Structure representing the new device.
57 * @return Error code.
58 */
59static int usb_hid_device_add(usb_device_t *dev)
60{
61 usb_log_debug("%s\n", __FUNCTION__);
62
63 if (dev == NULL) {
64 usb_log_error("Wrong parameter given for add_device().\n");
65 return EINVAL;
66 }
67
68 if (usb_device_get_iface_number(dev) < 0) {
69 usb_log_error("Failed to add HID device: endpoints not found."
70 "\n");
71 return ENOTSUP;
72 }
73 usb_hid_dev_t *hid_dev =
74 usb_device_data_alloc(dev, sizeof(usb_hid_dev_t));
75 if (hid_dev == NULL) {
76 usb_log_error("Failed to create USB/HID device structure.\n");
77 return ENOMEM;
78 }
79
80 int rc = usb_hid_init(hid_dev, dev);
81 if (rc != EOK) {
82 usb_log_error("Failed to initialize USB/HID device.\n");
83 usb_hid_deinit(hid_dev);
84 return rc;
85 }
86
87 usb_log_debug("USB/HID device structure initialized.\n");
88
89 /* Start automated polling function.
90 * This will create a separate fibril that will query the device
91 * for the data continuously. */
92 const usb_device_auto_polling_t auto_polling = {
93 .debug = 1,
94 .auto_clear_halt = true,
95 .delay = -1,
96 .max_failures = 3,
97 .on_data = usb_hid_polling_callback,
98 .on_polling_end = usb_hid_polling_ended_callback,
99 .on_error = usb_hid_polling_error_callback,
100 .arg = hid_dev,
101 };
102
103 rc = usb_device_auto_polling(dev, hid_dev->poll_pipe_mapping,
104 &auto_polling, hid_dev->poll_pipe_mapping->pipe.desc.max_transfer_size);
105
106 if (rc != EOK) {
107 usb_log_error("Failed to start polling fibril for `%s'.\n",
108 usb_device_get_name(dev));
109 usb_hid_deinit(hid_dev);
110 return rc;
111 }
112 hid_dev->running = true;
113
114 usb_log_info("HID device `%s' ready.\n", usb_device_get_name(dev));
115
116 return EOK;
117}
118
119/**
120 * Callback for a device about to be removed from the driver.
121 *
122 * @param dev Structure representing the device.
123 * @return Error code.
124 */
125static int usb_hid_device_remove(usb_device_t *dev)
126{
127 assert(dev);
128 usb_hid_dev_t *hid_dev = usb_device_data_get(dev);
129 assert(hid_dev);
130
131 usb_log_info("%s will be removed, setting remove flag.\n", usb_device_get_name(dev));
132 usb_hid_prepare_deinit(hid_dev);
133
134 return EOK;
135}
136
137static int join_and_clean(usb_device_t *dev)
138{
139 assert(dev);
140 usb_hid_dev_t *hid_dev = usb_device_data_get(dev);
141 assert(hid_dev);
142
143 /* Join polling fibril. */
144 fibril_mutex_lock(&hid_dev->poll_guard);
145 while (hid_dev->running)
146 fibril_condvar_wait(&hid_dev->poll_cv, &hid_dev->poll_guard);
147 fibril_mutex_unlock(&hid_dev->poll_guard);
148
149 /* Clean up. */
150 usb_hid_deinit(hid_dev);
151 usb_log_info("%s destruction complete.\n", usb_device_get_name(dev));
152
153 return EOK;
154}
155
156/**
157 * Callback for when a device has just been from the driver.
158 *
159 * @param dev Structure representing the device.
160 * @return Error code.
161 */
162static int usb_hid_device_removed(usb_device_t *dev)
163{
164 assert(dev);
165 usb_hid_dev_t *hid_dev = usb_device_data_get(dev);
166 assert(hid_dev);
167
168 usb_log_info("%s endpoints unregistered, joining polling fibril.\n", usb_device_get_name(dev));
169 return join_and_clean(dev);
170}
171
172/**
173 * Callback for removing a device from the driver.
174 *
175 * @param dev Structure representing the device.
176 * @return Error code.
177 */
178static int usb_hid_device_gone(usb_device_t *dev)
179{
180 assert(dev);
181 usb_hid_dev_t *hid_dev = usb_device_data_get(dev);
182 assert(hid_dev);
183
184 usb_log_info("Device %s gone, joining the polling fibril.\n", usb_device_get_name(dev));
185 usb_hid_prepare_deinit(hid_dev);
186 return join_and_clean(dev);
187}
188
189/** USB generic driver callbacks */
190static const usb_driver_ops_t usb_hid_driver_ops = {
191 .device_add = usb_hid_device_add,
192 .device_remove = usb_hid_device_remove,
193 .device_removed = usb_hid_device_removed,
194 .device_gone = usb_hid_device_gone,
195};
196
197/** The driver itself. */
198static const usb_driver_t usb_hid_driver = {
199 .name = NAME,
200 .ops = &usb_hid_driver_ops,
201 .endpoints = usb_hid_endpoints
202};
203
204int main(int argc, char *argv[])
205{
206 printf(NAME ": HelenOS USB HID driver.\n");
207
208 log_init(NAME);
209
210 return usb_driver_main(&usb_hid_driver);
211}
212/**
213 * @}
214 */
Note: See TracBrowser for help on using the repository browser.