source: mainline/uspace/lib/usbhid/src/hidiface.c@ 50b581d

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

Replace the async_wait_for(msg, NULL) pattern in the error paths with
async_forget(msg).

  • Property mode set to 100644
File size: 6.1 KB
Line 
1/*
2 * Copyright (c) 2011 Vojtech Horky
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 libusbhid
30 * @{
31 */
32/** @file
33 * Client functions for accessing USB HID interface (implementation).
34 */
35#include <dev_iface.h>
36#include <usbhid_iface.h>
37#include <usb/hid/iface.h>
38#include <errno.h>
39#include <str_error.h>
40#include <async.h>
41#include <assert.h>
42
43/** Ask for event array length.
44 *
45 * @param dev_sess Session to DDF device providing USB HID interface.
46 *
47 * @return Number of usages returned or negative error code.
48 *
49 */
50int usbhid_dev_get_event_length(async_sess_t *dev_sess, size_t *size)
51{
52 if (!dev_sess)
53 return EINVAL;
54
55 async_exch_t *exch = async_exchange_begin(dev_sess);
56
57 sysarg_t len;
58 int rc = async_req_1_1(exch, DEV_IFACE_ID(USBHID_DEV_IFACE),
59 IPC_M_USBHID_GET_EVENT_LENGTH, &len);
60
61 async_exchange_end(exch);
62
63 if (rc == EOK) {
64 if (size != NULL)
65 *size = (size_t) len;
66 }
67
68 return rc;
69}
70
71/** Request for next event from HID device.
72 *
73 * @param[in] dev_sess Session to DDF device providing USB HID interface.
74 * @param[out] usage_pages Where to store usage pages.
75 * @param[out] usages Where to store usages (actual data).
76 * @param[in] usage_count Length of @p usage_pages and @p usages buffer
77 * (in items, not bytes).
78 * @param[out] actual_usage_count Number of usages actually returned by the
79 * device driver.
80 * @param[in] flags Flags (see USBHID_IFACE_FLAG_*).
81 *
82 * @return Error code.
83 *
84 */
85int usbhid_dev_get_event(async_sess_t *dev_sess, uint8_t *buf,
86 size_t size, size_t *actual_size, int *event_nr, unsigned int flags)
87{
88 if (!dev_sess)
89 return EINVAL;
90
91 if ((buf == NULL))
92 return ENOMEM;
93
94 if (size == 0)
95 return EINVAL;
96
97 size_t buffer_size = size;
98 uint8_t *buffer = malloc(buffer_size);
99 if (buffer == NULL)
100 return ENOMEM;
101
102 async_exch_t *exch = async_exchange_begin(dev_sess);
103
104 ipc_call_t opening_request_call;
105 aid_t opening_request = async_send_2(exch,
106 DEV_IFACE_ID(USBHID_DEV_IFACE), IPC_M_USBHID_GET_EVENT,
107 flags, &opening_request_call);
108
109 if (opening_request == 0) {
110 async_exchange_end(exch);
111 free(buffer);
112 return ENOMEM;
113 }
114
115 ipc_call_t data_request_call;
116 aid_t data_request = async_data_read(exch, buffer, buffer_size,
117 &data_request_call);
118
119 async_exchange_end(exch);
120
121 if (data_request == 0) {
122 async_forget(opening_request);
123 free(buffer);
124 return ENOMEM;
125 }
126
127 sysarg_t data_request_rc;
128 sysarg_t opening_request_rc;
129 async_wait_for(data_request, &data_request_rc);
130 async_wait_for(opening_request, &opening_request_rc);
131
132 if (data_request_rc != EOK) {
133 /* Prefer return code of the opening request. */
134 if (opening_request_rc != EOK)
135 return (int) opening_request_rc;
136 else
137 return (int) data_request_rc;
138 }
139
140 if (opening_request_rc != EOK)
141 return (int) opening_request_rc;
142
143 size_t act_size = IPC_GET_ARG2(data_request_call);
144
145 /* Copy the individual items. */
146 memcpy(buf, buffer, act_size);
147
148 if (actual_size != NULL)
149 *actual_size = act_size;
150
151 if (event_nr != NULL)
152 *event_nr = IPC_GET_ARG1(opening_request_call);
153
154 return EOK;
155}
156
157int usbhid_dev_get_report_descriptor_length(async_sess_t *dev_sess,
158 size_t *size)
159{
160 if (!dev_sess)
161 return EINVAL;
162
163 async_exch_t *exch = async_exchange_begin(dev_sess);
164
165 sysarg_t arg_size;
166 int rc = async_req_1_1(exch, DEV_IFACE_ID(USBHID_DEV_IFACE),
167 IPC_M_USBHID_GET_REPORT_DESCRIPTOR_LENGTH, &arg_size);
168
169 async_exchange_end(exch);
170
171 if (rc == EOK) {
172 if (size != NULL)
173 *size = (size_t) arg_size;
174 }
175
176 return rc;
177}
178
179int usbhid_dev_get_report_descriptor(async_sess_t *dev_sess, uint8_t *buf,
180 size_t size, size_t *actual_size)
181{
182 if (!dev_sess)
183 return EINVAL;
184
185 if ((buf == NULL))
186 return ENOMEM;
187
188 if (size == 0)
189 return EINVAL;
190
191 async_exch_t *exch = async_exchange_begin(dev_sess);
192
193 aid_t opening_request = async_send_1(exch,
194 DEV_IFACE_ID(USBHID_DEV_IFACE), IPC_M_USBHID_GET_REPORT_DESCRIPTOR,
195 NULL);
196 if (opening_request == 0) {
197 async_exchange_end(exch);
198 return ENOMEM;
199 }
200
201 ipc_call_t data_request_call;
202 aid_t data_request = async_data_read(exch, buf, size,
203 &data_request_call);
204
205 async_exchange_end(exch);
206
207 if (data_request == 0) {
208 async_forget(opening_request);
209 return ENOMEM;
210 }
211
212 sysarg_t data_request_rc;
213 sysarg_t opening_request_rc;
214 async_wait_for(data_request, &data_request_rc);
215 async_wait_for(opening_request, &opening_request_rc);
216
217 if (data_request_rc != EOK) {
218 /* Prefer return code of the opening request. */
219 if (opening_request_rc != EOK)
220 return (int) opening_request_rc;
221 else
222 return (int) data_request_rc;
223 }
224
225 if (opening_request_rc != EOK)
226 return (int) opening_request_rc;
227
228 size_t act_size = IPC_GET_ARG2(data_request_call);
229
230 if (actual_size != NULL)
231 *actual_size = act_size;
232
233 return EOK;
234}
235
236/**
237 * @}
238 */
Note: See TracBrowser for help on using the repository browser.