2 * Copyright (c) 2010-2011 Vojtech Horky
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
29 /** @addtogroup libdrv
41 #include "usbhid_iface.h"
42 #include "ddf/driver.h"
44 /** IPC methods for USB HID device interface. */
46 /** Get number of events reported in single burst.
49 * - Size of one report in bytes.
51 IPC_M_USBHID_GET_EVENT_LENGTH
,
52 /** Get single event from the HID device.
53 * The word single refers to set of individual events that were
54 * available at particular point in time.
57 * The call is followed by data read expecting two concatenated
60 * - EOK - events returned
61 * - EAGAIN - no event ready (only in non-blocking mode)
63 * It is okay if the client requests less data. Extra data must
64 * be truncated by the driver.
66 * @todo Change this comment.
68 IPC_M_USBHID_GET_EVENT
,
70 /** Get the size of the report descriptor from the HID device.
75 * - EOK - method is implemented (expected always)
76 * Parameters of the answer:
77 * - Size of the report in bytes.
79 IPC_M_USBHID_GET_REPORT_DESCRIPTOR_LENGTH
,
81 /** Get the report descriptor from the HID device.
85 * The call is followed by data read expecting the descriptor itself.
87 * - EOK - report descriptor returned.
89 IPC_M_USBHID_GET_REPORT_DESCRIPTOR
90 } usbhid_iface_funcs_t
;
92 /** Ask for event array length.
94 * @param dev_sess Session to DDF device providing USB HID interface.
96 * @return Number of usages returned or an error code.
99 errno_t
usbhid_dev_get_event_length(async_sess_t
*dev_sess
, size_t *size
)
104 async_exch_t
*exch
= async_exchange_begin(dev_sess
);
107 errno_t rc
= async_req_1_1(exch
, DEV_IFACE_ID(USBHID_DEV_IFACE
),
108 IPC_M_USBHID_GET_EVENT_LENGTH
, &len
);
110 async_exchange_end(exch
);
114 *size
= (size_t) len
;
120 /** Request for next event from HID device.
122 * @param[in] dev_sess Session to DDF device providing USB HID interface.
123 * @param[out] usage_pages Where to store usage pages.
124 * @param[out] usages Where to store usages (actual data).
125 * @param[in] usage_count Length of @p usage_pages and @p usages buffer
126 * (in items, not bytes).
127 * @param[out] actual_usage_count Number of usages actually returned by the
129 * @param[in] flags Flags (see USBHID_IFACE_FLAG_*).
131 * @return Error code.
134 errno_t
usbhid_dev_get_event(async_sess_t
*dev_sess
, uint8_t *buf
,
135 size_t size
, size_t *actual_size
, int *event_nr
, unsigned int flags
)
146 size_t buffer_size
= size
;
147 uint8_t *buffer
= malloc(buffer_size
);
151 async_exch_t
*exch
= async_exchange_begin(dev_sess
);
153 ipc_call_t opening_request_call
;
154 aid_t opening_request
= async_send_2(exch
,
155 DEV_IFACE_ID(USBHID_DEV_IFACE
), IPC_M_USBHID_GET_EVENT
,
156 flags
, &opening_request_call
);
158 if (opening_request
== 0) {
159 async_exchange_end(exch
);
164 ipc_call_t data_request_call
;
165 aid_t data_request
= async_data_read(exch
, buffer
, buffer_size
,
168 async_exchange_end(exch
);
170 if (data_request
== 0) {
171 async_forget(opening_request
);
176 errno_t data_request_rc
;
177 errno_t opening_request_rc
;
178 async_wait_for(data_request
, &data_request_rc
);
179 async_wait_for(opening_request
, &opening_request_rc
);
181 if (data_request_rc
!= EOK
) {
182 /* Prefer return code of the opening request. */
183 if (opening_request_rc
!= EOK
)
184 return (errno_t
) opening_request_rc
;
186 return (errno_t
) data_request_rc
;
189 if (opening_request_rc
!= EOK
)
190 return (errno_t
) opening_request_rc
;
192 size_t act_size
= IPC_GET_ARG2(data_request_call
);
194 /* Copy the individual items. */
195 memcpy(buf
, buffer
, act_size
);
197 if (actual_size
!= NULL
)
198 *actual_size
= act_size
;
200 if (event_nr
!= NULL
)
201 *event_nr
= IPC_GET_ARG1(opening_request_call
);
206 errno_t
usbhid_dev_get_report_descriptor_length(async_sess_t
*dev_sess
,
212 async_exch_t
*exch
= async_exchange_begin(dev_sess
);
215 errno_t rc
= async_req_1_1(exch
, DEV_IFACE_ID(USBHID_DEV_IFACE
),
216 IPC_M_USBHID_GET_REPORT_DESCRIPTOR_LENGTH
, &arg_size
);
218 async_exchange_end(exch
);
222 *size
= (size_t) arg_size
;
228 errno_t
usbhid_dev_get_report_descriptor(async_sess_t
*dev_sess
, uint8_t *buf
,
229 size_t size
, size_t *actual_size
)
240 async_exch_t
*exch
= async_exchange_begin(dev_sess
);
242 aid_t opening_request
= async_send_1(exch
,
243 DEV_IFACE_ID(USBHID_DEV_IFACE
), IPC_M_USBHID_GET_REPORT_DESCRIPTOR
,
245 if (opening_request
== 0) {
246 async_exchange_end(exch
);
250 ipc_call_t data_request_call
;
251 aid_t data_request
= async_data_read(exch
, buf
, size
,
254 async_exchange_end(exch
);
256 if (data_request
== 0) {
257 async_forget(opening_request
);
261 errno_t data_request_rc
;
262 errno_t opening_request_rc
;
263 async_wait_for(data_request
, &data_request_rc
);
264 async_wait_for(opening_request
, &opening_request_rc
);
266 if (data_request_rc
!= EOK
) {
267 /* Prefer return code of the opening request. */
268 if (opening_request_rc
!= EOK
)
269 return (errno_t
) opening_request_rc
;
271 return (errno_t
) data_request_rc
;
274 if (opening_request_rc
!= EOK
)
275 return (errno_t
) opening_request_rc
;
277 size_t act_size
= IPC_GET_ARG2(data_request_call
);
279 if (actual_size
!= NULL
)
280 *actual_size
= act_size
;
285 static void remote_usbhid_get_event_length(ddf_fun_t
*, void *, ipc_call_t
*);
286 static void remote_usbhid_get_event(ddf_fun_t
*, void *, ipc_call_t
*);
287 static void remote_usbhid_get_report_descriptor_length(ddf_fun_t
*, void *, ipc_call_t
*);
288 static void remote_usbhid_get_report_descriptor(ddf_fun_t
*, void *, ipc_call_t
*);
290 /** Remote USB HID interface operations. */
291 static const remote_iface_func_ptr_t remote_usbhid_iface_ops
[] = {
292 [IPC_M_USBHID_GET_EVENT_LENGTH
] = remote_usbhid_get_event_length
,
293 [IPC_M_USBHID_GET_EVENT
] = remote_usbhid_get_event
,
294 [IPC_M_USBHID_GET_REPORT_DESCRIPTOR_LENGTH
] =
295 remote_usbhid_get_report_descriptor_length
,
296 [IPC_M_USBHID_GET_REPORT_DESCRIPTOR
] = remote_usbhid_get_report_descriptor
299 /** Remote USB HID interface structure.
301 const remote_iface_t remote_usbhid_iface
= {
302 .method_count
= ARRAY_SIZE(remote_usbhid_iface_ops
),
303 .methods
= remote_usbhid_iface_ops
306 void remote_usbhid_get_event_length(ddf_fun_t
*fun
, void *iface
,
309 printf("remote_usbhid_get_event_length()\n");
311 usbhid_iface_t
*hid_iface
= (usbhid_iface_t
*) iface
;
313 if (!hid_iface
->get_event_length
) {
314 printf("Get event length not set!\n");
315 async_answer_0(call
, ENOTSUP
);
319 size_t len
= hid_iface
->get_event_length(fun
);
320 async_answer_1(call
, EOK
, len
);
323 void remote_usbhid_get_event(ddf_fun_t
*fun
, void *iface
,
326 usbhid_iface_t
*hid_iface
= (usbhid_iface_t
*) iface
;
328 if (!hid_iface
->get_event
) {
329 async_answer_0(call
, ENOTSUP
);
333 unsigned int flags
= DEV_IPC_GET_ARG1(*call
);
337 if (!async_data_read_receive(&data
, &len
)) {
338 async_answer_0(call
, EPARTY
);
343 async_answer_0(&data
, EINVAL
);
344 async_answer_0(call
, EINVAL
);
350 uint8_t *event
= malloc(len
);
352 async_answer_0(&data
, ENOMEM
);
353 async_answer_0(call
, ENOMEM
);
359 rc
= hid_iface
->get_event(fun
, event
, len
, &act_length
, &event_nr
, flags
);
362 async_answer_0(&data
, rc
);
363 async_answer_0(call
, rc
);
366 if (act_length
>= len
) {
367 /* This shall not happen. */
368 // FIXME: how about an assert here?
372 async_data_read_finalize(&data
, event
, act_length
);
376 async_answer_1(call
, EOK
, event_nr
);
379 void remote_usbhid_get_report_descriptor_length(ddf_fun_t
*fun
, void *iface
,
382 usbhid_iface_t
*hid_iface
= (usbhid_iface_t
*) iface
;
384 if (!hid_iface
->get_report_descriptor_length
) {
385 async_answer_0(call
, ENOTSUP
);
389 size_t len
= hid_iface
->get_report_descriptor_length(fun
);
390 async_answer_1(call
, EOK
, (sysarg_t
) len
);
393 void remote_usbhid_get_report_descriptor(ddf_fun_t
*fun
, void *iface
,
396 usbhid_iface_t
*hid_iface
= (usbhid_iface_t
*) iface
;
398 if (!hid_iface
->get_report_descriptor
) {
399 async_answer_0(call
, ENOTSUP
);
405 if (!async_data_read_receive(&data
, &len
)) {
406 async_answer_0(call
, EINVAL
);
411 async_answer_0(&data
, EINVAL
);
412 async_answer_0(call
, EINVAL
);
416 uint8_t *descriptor
= malloc(len
);
417 if (descriptor
== NULL
) {
418 async_answer_0(&data
, ENOMEM
);
419 async_answer_0(call
, ENOMEM
);
424 errno_t rc
= hid_iface
->get_report_descriptor(fun
, descriptor
, len
,
431 async_answer_0(&data
, rc
);
432 async_answer_0(call
, rc
);
436 async_data_read_finalize(&data
, descriptor
, act_len
);
437 async_answer_0(call
, EOK
);