source: mainline/uspace/lib/usb/src/hidreq.c@ 85c47729

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 85c47729 was 476b71ff, checked in by Lubos Slovak <lubos.slovak@…>, 14 years ago

Finished renaming kbd driver to usbkbd

  • Property mode set to 100644
File size: 12.8 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 drvusbhid
30 * @{
31 */
32/** @file
33 * HID class-specific requests.
34 */
35
36#include <stdint.h>
37#include <errno.h>
38#include <str_error.h>
39
40#include <usb/classes/hid.h>
41#include <usb/debug.h>
42#include <usb/request.h>
43#include <usb/pipes.h>
44
45#include <usb/classes/hidreq.h>
46
47/*----------------------------------------------------------------------------*/
48/**
49 * Send Set Report request to the HID device.
50 *
51 * @param hid_dev HID device to send the request to.
52 * @param type Type of the report.
53 * @param buffer Report data.
54 * @param buf_size Report data size (in bytes).
55 *
56 * @retval EOK if successful.
57 * @retval EINVAL if no HID device is given.
58 * @return Other value inherited from one of functions
59 * usb_pipe_start_session(), usb_pipe_end_session(),
60 * usb_control_request_set().
61 */
62int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
63 usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size)
64{
65 if (ctrl_pipe == NULL) {
66 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
67 return EINVAL;
68 }
69
70 if (iface_no < 0) {
71 usb_log_warning("usbhid_req_set_report(): no interface given."
72 "\n");
73 return EINVAL;
74 }
75
76 /*
77 * No need for checking other parameters, as they are checked in
78 * the called function (usb_control_request_set()).
79 */
80
81 int rc, sess_rc;
82
83 sess_rc = usb_pipe_start_session(ctrl_pipe);
84 if (sess_rc != EOK) {
85 usb_log_warning("Failed to start a session: %s.\n",
86 str_error(sess_rc));
87 return sess_rc;
88 }
89
90 uint16_t value = 0;
91 value |= (type << 8);
92
93 usb_log_debug("Sending Set_Report request to the device.\n");
94
95 rc = usb_control_request_set(ctrl_pipe,
96 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
97 USB_HIDREQ_SET_REPORT, value, iface_no, buffer, buf_size);
98
99 sess_rc = usb_pipe_end_session(ctrl_pipe);
100
101 if (rc != EOK) {
102 usb_log_warning("Error sending output report to the keyboard: "
103 "%s.\n", str_error(rc));
104 return rc;
105 }
106
107 if (sess_rc != EOK) {
108 usb_log_warning("Error closing session: %s.\n",
109 str_error(sess_rc));
110 return sess_rc;
111 }
112
113 return EOK;
114}
115
116/*----------------------------------------------------------------------------*/
117/**
118 * Send Set Protocol request to the HID device.
119 *
120 * @param hid_dev HID device to send the request to.
121 * @param protocol Protocol to set.
122 *
123 * @retval EOK if successful.
124 * @retval EINVAL if no HID device is given.
125 * @return Other value inherited from one of functions
126 * usb_pipe_start_session(), usb_pipe_end_session(),
127 * usb_control_request_set().
128 */
129int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
130 usb_hid_protocol_t protocol)
131{
132 if (ctrl_pipe == NULL) {
133 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
134 return EINVAL;
135 }
136
137 if (iface_no < 0) {
138 usb_log_warning("usbhid_req_set_report(): no interface given."
139 "\n");
140 return EINVAL;
141 }
142
143 /*
144 * No need for checking other parameters, as they are checked in
145 * the called function (usb_control_request_set()).
146 */
147
148 int rc, sess_rc;
149
150 sess_rc = usb_pipe_start_session(ctrl_pipe);
151 if (sess_rc != EOK) {
152 usb_log_warning("Failed to start a session: %s.\n",
153 str_error(sess_rc));
154 return sess_rc;
155 }
156
157 usb_log_debug("Sending Set_Protocol request to the device ("
158 "protocol: %d, iface: %d).\n", protocol, iface_no);
159
160 rc = usb_control_request_set(ctrl_pipe,
161 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
162 USB_HIDREQ_SET_PROTOCOL, protocol, iface_no, NULL, 0);
163
164 sess_rc = usb_pipe_end_session(ctrl_pipe);
165
166 if (rc != EOK) {
167 usb_log_warning("Error sending output report to the keyboard: "
168 "%s.\n", str_error(rc));
169 return rc;
170 }
171
172 if (sess_rc != EOK) {
173 usb_log_warning("Error closing session: %s.\n",
174 str_error(sess_rc));
175 return sess_rc;
176 }
177
178 return EOK;
179}
180
181/*----------------------------------------------------------------------------*/
182/**
183 * Send Set Idle request to the HID device.
184 *
185 * @param hid_dev HID device to send the request to.
186 * @param duration Duration value (is multiplicated by 4 by the device to
187 * get real duration in miliseconds).
188 *
189 * @retval EOK if successful.
190 * @retval EINVAL if no HID device is given.
191 * @return Other value inherited from one of functions
192 * usb_pipe_start_session(), usb_pipe_end_session(),
193 * usb_control_request_set().
194 */
195int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration)
196{
197 if (ctrl_pipe == NULL) {
198 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
199 return EINVAL;
200 }
201
202 if (iface_no < 0) {
203 usb_log_warning("usbhid_req_set_report(): no interface given."
204 "\n");
205 return EINVAL;
206 }
207
208 /*
209 * No need for checking other parameters, as they are checked in
210 * the called function (usb_control_request_set()).
211 */
212
213 int rc, sess_rc;
214
215 sess_rc = usb_pipe_start_session(ctrl_pipe);
216 if (sess_rc != EOK) {
217 usb_log_warning("Failed to start a session: %s.\n",
218 str_error(sess_rc));
219 return sess_rc;
220 }
221
222 usb_log_debug("Sending Set_Idle request to the device ("
223 "duration: %u, iface: %d).\n", duration, iface_no);
224
225 uint16_t value = duration << 8;
226
227 rc = usb_control_request_set(ctrl_pipe,
228 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
229 USB_HIDREQ_SET_IDLE, value, iface_no, NULL, 0);
230
231 sess_rc = usb_pipe_end_session(ctrl_pipe);
232
233 if (rc != EOK) {
234 usb_log_warning("Error sending output report to the keyboard: "
235 "%s.\n", str_error(rc));
236 return rc;
237 }
238
239 if (sess_rc != EOK) {
240 usb_log_warning("Error closing session: %s.\n",
241 str_error(sess_rc));
242 return sess_rc;
243 }
244
245 return EOK;
246}
247
248/*----------------------------------------------------------------------------*/
249/**
250 * Send Get Report request to the HID device.
251 *
252 * @param[in] hid_dev HID device to send the request to.
253 * @param[in] type Type of the report.
254 * @param[in][out] buffer Buffer for the report data.
255 * @param[in] buf_size Size of the buffer (in bytes).
256 * @param[out] actual_size Actual size of report received from the device
257 * (in bytes).
258 *
259 * @retval EOK if successful.
260 * @retval EINVAL if no HID device is given.
261 * @return Other value inherited from one of functions
262 * usb_pipe_start_session(), usb_pipe_end_session(),
263 * usb_control_request_set().
264 */
265int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no,
266 usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size,
267 size_t *actual_size)
268{
269 if (ctrl_pipe == NULL) {
270 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
271 return EINVAL;
272 }
273
274 if (iface_no < 0) {
275 usb_log_warning("usbhid_req_set_report(): no interface given."
276 "\n");
277 return EINVAL;
278 }
279
280 /*
281 * No need for checking other parameters, as they are checked in
282 * the called function (usb_control_request_set()).
283 */
284
285 int rc, sess_rc;
286
287 sess_rc = usb_pipe_start_session(ctrl_pipe);
288 if (sess_rc != EOK) {
289 usb_log_warning("Failed to start a session: %s.\n",
290 str_error(sess_rc));
291 return sess_rc;
292 }
293
294 uint16_t value = 0;
295 value |= (type << 8);
296
297 usb_log_debug("Sending Get_Report request to the device.\n");
298
299 rc = usb_control_request_get(ctrl_pipe,
300 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
301 USB_HIDREQ_GET_REPORT, value, iface_no, buffer, buf_size,
302 actual_size);
303
304 sess_rc = usb_pipe_end_session(ctrl_pipe);
305
306 if (rc != EOK) {
307 usb_log_warning("Error sending output report to the keyboard: "
308 "%s.\n", str_error(rc));
309 return rc;
310 }
311
312 if (sess_rc != EOK) {
313 usb_log_warning("Error closing session: %s.\n",
314 str_error(sess_rc));
315 return sess_rc;
316 }
317
318 return EOK;
319}
320
321/*----------------------------------------------------------------------------*/
322/**
323 * Send Get Protocol request to the HID device.
324 *
325 * @param[in] hid_dev HID device to send the request to.
326 * @param[out] protocol Current protocol of the device.
327 *
328 * @retval EOK if successful.
329 * @retval EINVAL if no HID device is given.
330 * @return Other value inherited from one of functions
331 * usb_pipe_start_session(), usb_pipe_end_session(),
332 * usb_control_request_set().
333 */
334int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
335 usb_hid_protocol_t *protocol)
336{
337 if (ctrl_pipe == NULL) {
338 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
339 return EINVAL;
340 }
341
342 if (iface_no < 0) {
343 usb_log_warning("usbhid_req_set_report(): no interface given."
344 "\n");
345 return EINVAL;
346 }
347
348 /*
349 * No need for checking other parameters, as they are checked in
350 * the called function (usb_control_request_set()).
351 */
352
353 int rc, sess_rc;
354
355 sess_rc = usb_pipe_start_session(ctrl_pipe);
356 if (sess_rc != EOK) {
357 usb_log_warning("Failed to start a session: %s.\n",
358 str_error(sess_rc));
359 return sess_rc;
360 }
361
362 usb_log_debug("Sending Get_Protocol request to the device ("
363 "iface: %d).\n", iface_no);
364
365 uint8_t buffer[1];
366 size_t actual_size = 0;
367
368 rc = usb_control_request_get(ctrl_pipe,
369 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
370 USB_HIDREQ_GET_PROTOCOL, 0, iface_no, buffer, 1, &actual_size);
371
372 sess_rc = usb_pipe_end_session(ctrl_pipe);
373
374 if (rc != EOK) {
375 usb_log_warning("Error sending output report to the keyboard: "
376 "%s.\n", str_error(rc));
377 return rc;
378 }
379
380 if (sess_rc != EOK) {
381 usb_log_warning("Error closing session: %s.\n",
382 str_error(sess_rc));
383 return sess_rc;
384 }
385
386 if (actual_size != 1) {
387 usb_log_warning("Wrong data size: %zu, expected: 1.\n",
388 actual_size);
389 return ELIMIT;
390 }
391
392 *protocol = buffer[0];
393
394 return EOK;
395}
396
397/*----------------------------------------------------------------------------*/
398/**
399 * Send Get Idle request to the HID device.
400 *
401 * @param[in] hid_dev HID device to send the request to.
402 * @param[out] duration Duration value (multiplicate by 4 to get real duration
403 * in miliseconds).
404 *
405 * @retval EOK if successful.
406 * @retval EINVAL if no HID device is given.
407 * @return Other value inherited from one of functions
408 * usb_pipe_start_session(), usb_pipe_end_session(),
409 * usb_control_request_set().
410 */
411int usbhid_req_get_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t *duration)
412{
413 if (ctrl_pipe == NULL) {
414 usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
415 return EINVAL;
416 }
417
418 if (iface_no < 0) {
419 usb_log_warning("usbhid_req_set_report(): no interface given."
420 "\n");
421 return EINVAL;
422 }
423
424 /*
425 * No need for checking other parameters, as they are checked in
426 * the called function (usb_control_request_set()).
427 */
428
429 int rc, sess_rc;
430
431 sess_rc = usb_pipe_start_session(ctrl_pipe);
432 if (sess_rc != EOK) {
433 usb_log_warning("Failed to start a session: %s.\n",
434 str_error(sess_rc));
435 return sess_rc;
436 }
437
438 usb_log_debug("Sending Get_Idle request to the device ("
439 "iface: %d).\n", iface_no);
440
441 uint16_t value = 0;
442 uint8_t buffer[1];
443 size_t actual_size = 0;
444
445 rc = usb_control_request_get(ctrl_pipe,
446 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
447 USB_HIDREQ_GET_IDLE, value, iface_no, buffer, 1,
448 &actual_size);
449
450 sess_rc = usb_pipe_end_session(ctrl_pipe);
451
452 if (rc != EOK) {
453 usb_log_warning("Error sending output report to the keyboard: "
454 "%s.\n", str_error(rc));
455 return rc;
456 }
457
458 if (sess_rc != EOK) {
459 usb_log_warning("Error closing session: %s.\n",
460 str_error(sess_rc));
461 return sess_rc;
462 }
463
464 if (actual_size != 1) {
465 usb_log_warning("Wrong data size: %zu, expected: 1.\n",
466 actual_size);
467 return ELIMIT;
468 }
469
470 *duration = buffer[0];
471
472 return EOK;
473}
474
475/*----------------------------------------------------------------------------*/
476
477/**
478 * @}
479 */
Note: See TracBrowser for help on using the repository browser.