source: mainline/uspace/lib/usb/src/usbdrvreq.c@ 62066b4

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 62066b4 was 3b77628, checked in by Vojtech Horky <vojtechhorky@…>, 14 years ago

Doxygen comment fixes

Mainly proper subgrouping and some missing @param comments.

  • Property mode set to 100644
File size: 15.4 KB
RevLine 
[f995350]1/*
2 * Copyright (c) 2010 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
[3b77628]29/** @addtogroup libusb
[f995350]30 * @{
31 */
32/** @file
33 * @brief USB driver - standard USB requests (implementation).
34 */
35#include <usb/usbdrv.h>
36#include <errno.h>
37
[863d45e]38/** Prepare USB target for control endpoint.
39 *
40 * @param name Variable name with the USB target.
41 * @param target_address Target USB address.
42 */
[276aeda]43#define PREPARE_TARGET(name, target_address) \
44 usb_target_t name = { \
45 .address = target_address, \
46 .endpoint = 0 \
47 }
48
[863d45e]49/** Prepare setup packet.
50 *
51 * @param name Variable name with the setup packet.
52 * @param p_direction Data transfer direction.
53 * @param p_type Request type (standard/class/vendor)
54 * @param p_recipient Recipient of the request.
55 * @param p_request Request.
56 * @param p_value wValue field of setup packet.
57 * @param p_index wIndex field of setup packet.
58 * @param p_length Length of extra data.
59 */
60#define PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
61 p_request, p_value, p_index, p_length) \
[00c2d035]62 usb_device_request_setup_packet_t name = { \
[276aeda]63 .request_type = \
64 ((p_direction) == USB_DIRECTION_IN ? 128 : 0) \
65 | ((p_type) << 5) \
66 | (p_recipient), \
67 .request = (p_request), \
68 { .value = (p_value) }, \
69 .index = (p_index), \
70 .length = (p_length) \
71 }
72
[863d45e]73/** Prepare setup packet.
74 *
75 * @param name Variable name with the setup packet.
76 * @param p_direction Data transfer direction.
77 * @param p_type Request type (standard/class/vendor)
78 * @param p_recipient Recipient of the request.
79 * @param p_request Request.
80 * @param p_value_low wValue field of setup packet (low byte).
81 * @param p_value_high wValue field of setup packet (high byte).
82 * @param p_index wIndex field of setup packet.
83 * @param p_length Length of extra data.
84 */
85#define PREPARE_SETUP_PACKET_LOHI(name, p_direction, p_type, p_recipient, \
86 p_request, p_value_low, p_value_high, p_index, p_length) \
[276aeda]87 PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
88 p_request, (p_value_low) | ((p_value_high) << 8), \
89 p_index, p_length)
90
91/** Retrieve status of a USB device.
92 *
[863d45e]93 * @param[in] hc_phone Open phone to HC driver.
94 * @param[in] address Device address.
95 * @param[in] recipient Recipient of the request.
96 * @param[in] recipient_index Index of @p recipient.
97 * @param[out] status Status (see figure 9-4 in USB 1.1 specification).
98 * @return Error code.
[276aeda]99 */
100int usb_drv_req_get_status(int hc_phone, usb_address_t address,
101 usb_request_recipient_t recipient, uint16_t recipient_index,
102 uint16_t *status)
103{
104 if (status == NULL) {
105 return EBADMEM;
106 }
107
108 PREPARE_TARGET(target, address);
109
110 PREPARE_SETUP_PACKET(setup_packet,
111 USB_DIRECTION_IN, USB_REQUEST_TYPE_STANDARD,
112 recipient, USB_DEVREQ_GET_STATUS, 0, recipient_index, 2);
113
114 size_t transfered;
115 uint16_t tmp_status;
116 int rc = usb_drv_psync_control_read(hc_phone, target,
117 &setup_packet, sizeof(setup_packet), &tmp_status, 2, &transfered);
118 if (rc != EOK) {
119 return rc;
120 }
121 if (transfered != 2) {
122 return ERANGE;
123 }
124
125 *status = tmp_status;
126
127 return EOK;
128}
129
130/** Clear or disable USB device feature.
131 *
[863d45e]132 * @param[in] hc_phone Open phone to HC driver.
133 * @param[in] address Device address.
134 * @param[in] recipient Recipient of the request.
135 * @param[in] selector Feature selector.
136 * @param[in] index Index of @p recipient.
137 * @return Error code.
[276aeda]138 */
139int usb_drv_req_clear_feature(int hc_phone, usb_address_t address,
140 usb_request_recipient_t recipient,
141 uint16_t selector, uint16_t index)
142{
143 PREPARE_TARGET(target, address);
144
145 PREPARE_SETUP_PACKET(setup_packet,
146 USB_DIRECTION_OUT, USB_REQUEST_TYPE_STANDARD,
147 recipient, USB_DEVREQ_CLEAR_FEATURE, selector, index, 0);
148
149 int rc = usb_drv_psync_control_write(hc_phone, target,
150 &setup_packet, sizeof(setup_packet), NULL, 0);
151
152 return rc;
153}
154
155/** Set or enable USB device feature.
156 *
[863d45e]157 * @param[in] hc_phone Open phone to HC driver.
158 * @param[in] address Device address.
159 * @param[in] recipient Recipient of the request.
160 * @param[in] selector Feature selector.
161 * @param[in] index Index of @p recipient.
162 * @return Error code.
[276aeda]163 */
164int usb_drv_req_set_feature(int hc_phone, usb_address_t address,
165 usb_request_recipient_t recipient,
166 uint16_t selector, uint16_t index)
167{
168 PREPARE_TARGET(target, address);
169
170 PREPARE_SETUP_PACKET(setup_packet,
171 USB_DIRECTION_OUT, USB_REQUEST_TYPE_STANDARD,
172 recipient, USB_DEVREQ_SET_FEATURE, selector, index, 0);
173
174 int rc = usb_drv_psync_control_write(hc_phone, target,
175 &setup_packet, sizeof(setup_packet), NULL, 0);
176
177 return rc;
178}
179
[f995350]180/** Change address of connected device.
181 *
182 * @see usb_drv_reserve_default_address
183 * @see usb_drv_release_default_address
184 * @see usb_drv_request_address
185 * @see usb_drv_release_address
186 * @see usb_drv_bind_address
187 *
[863d45e]188 * @param[in] phone Open phone to HC driver.
189 * @param[in] old_address Current address.
[3b77628]190 * @param[in] new_address Address to be set.
[f995350]191 * @return Error code.
192 */
193int usb_drv_req_set_address(int phone, usb_address_t old_address,
194 usb_address_t new_address)
195{
[263a9f19]196 PREPARE_TARGET(target, old_address);
[f995350]197
[263a9f19]198 PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_OUT,
199 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
200 USB_DEVREQ_SET_ADDRESS, new_address, 0, 0);
[f995350]201
[f5e39475]202 int rc = usb_drv_psync_control_write(phone, target,
203 &setup_packet, sizeof(setup_packet), NULL, 0);
[f995350]204
[f5e39475]205 return rc;
[f995350]206}
207
[97bfba1]208/** Retrieve USB descriptor of connected USB device.
209 *
210 * @param[in] hc_phone Open phone to HC driver.
[863d45e]211 * @param[in] address Device address.
[97bfba1]212 * @param[in] request_type Request type (standard/class/vendor).
213 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
214 * @param[in] descriptor_index Descriptor index.
[409dce5]215 * @param[in] language Language index.
[97bfba1]216 * @param[out] buffer Buffer where to store the retrieved descriptor.
217 * @param[in] size Size of the @p buffer.
218 * @param[out] actual_size Number of bytes actually transferred.
219 * @return Error code.
220 */
221int usb_drv_req_get_descriptor(int hc_phone, usb_address_t address,
222 usb_request_type_t request_type,
223 uint8_t descriptor_type, uint8_t descriptor_index,
224 uint16_t language,
225 void *buffer, size_t size, size_t *actual_size)
226{
[409dce5]227 if (buffer == NULL) {
228 return EBADMEM;
229 }
230 if (size == 0) {
231 return EINVAL;
232 }
233
[263a9f19]234 // FIXME: check that size is not too big
235
236 PREPARE_TARGET(target, address);
237
238 PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_IN,
239 request_type, USB_REQUEST_RECIPIENT_DEVICE,
240 USB_DEVREQ_GET_DESCRIPTOR, descriptor_index, descriptor_type,
241 language, size);
[97bfba1]242
243 int rc = usb_drv_psync_control_read(hc_phone, target,
244 &setup_packet, sizeof(setup_packet),
245 buffer, size, actual_size);
246
247 return rc;
248}
249
[9501cced]250/** Retrieve device descriptor of connected USB device.
251 *
252 * @param[in] phone Open phone to HC driver.
[863d45e]253 * @param[in] address Device address.
[9501cced]254 * @param[out] descriptor Storage for the device descriptor.
255 * @return Error code.
256 * @retval EBADMEM @p descriptor is NULL.
257 */
258int usb_drv_req_get_device_descriptor(int phone, usb_address_t address,
259 usb_standard_device_descriptor_t *descriptor)
260{
261 if (descriptor == NULL) {
262 return EBADMEM;
263 }
[9b95dbcf]264
[9501cced]265 size_t actually_transferred = 0;
266 usb_standard_device_descriptor_t descriptor_tmp;
[9b95dbcf]267 int rc = usb_drv_req_get_descriptor(phone, address,
268 USB_REQUEST_TYPE_STANDARD,
269 USB_DESCTYPE_DEVICE, 0,
270 0,
271 &descriptor_tmp, sizeof(descriptor_tmp),
272 &actually_transferred);
[f5e39475]273
[9501cced]274 if (rc != EOK) {
275 return rc;
276 }
277
[f5e39475]278 /* Verify that all data has been transferred. */
279 if (actually_transferred < sizeof(descriptor_tmp)) {
[9501cced]280 return ELIMIT;
281 }
282
[f5e39475]283 /* Everything is okay, copy the descriptor. */
[9501cced]284 memcpy(descriptor, &descriptor_tmp,
[f5e39475]285 sizeof(descriptor_tmp));
[9501cced]286
287 return EOK;
288}
289
290
[2c5cefa]291/** Retrieve configuration descriptor of connected USB device.
292 *
293 * The function does not retrieve additional data binded with configuration
294 * descriptor (such as its interface and endpoint descriptors) - use
295 * usb_drv_req_get_full_configuration_descriptor() instead.
296 *
297 * @param[in] phone Open phone to HC driver.
[863d45e]298 * @param[in] address Device address.
[2c5cefa]299 * @param[in] index Configuration descriptor index.
300 * @param[out] descriptor Storage for the configuration descriptor.
301 * @return Error code.
302 * @retval EBADMEM @p descriptor is NULL.
303 */
304int usb_drv_req_get_bare_configuration_descriptor(int phone,
305 usb_address_t address, int index,
306 usb_standard_configuration_descriptor_t *descriptor)
307{
308 if (descriptor == NULL) {
309 return EBADMEM;
310 }
[9b95dbcf]311
[2c5cefa]312 size_t actually_transferred = 0;
313 usb_standard_configuration_descriptor_t descriptor_tmp;
[9b95dbcf]314 int rc = usb_drv_req_get_descriptor(phone, address,
315 USB_REQUEST_TYPE_STANDARD,
316 USB_DESCTYPE_CONFIGURATION, 0,
317 0,
318 &descriptor_tmp, sizeof(descriptor_tmp),
319 &actually_transferred);
[2c5cefa]320
321 if (rc != EOK) {
322 return rc;
323 }
324
325 /* Verify that all data has been transferred. */
326 if (actually_transferred < sizeof(descriptor_tmp)) {
327 return ELIMIT;
328 }
329
330 /* Everything is okay, copy the descriptor. */
331 memcpy(descriptor, &descriptor_tmp,
332 sizeof(descriptor_tmp));
333
334 return EOK;
335}
336
337/** Retrieve full configuration descriptor of connected USB device.
338 *
339 * @warning The @p buffer might be touched (i.e. its contents changed)
[863d45e]340 * even when error occurs.
[2c5cefa]341 *
342 * @param[in] phone Open phone to HC driver.
[863d45e]343 * @param[in] address Device address.
[2c5cefa]344 * @param[in] index Configuration descriptor index.
345 * @param[out] buffer Buffer for the whole configuration descriptor.
346 * @param[in] buffer_size Size of the prepared @p buffer.
347 * @param[out] actual_buffer_size Bytes actually transfered.
348 * @return Error code.
349 * @retval EBADMEM @p descriptor is NULL.
350 */
351int usb_drv_req_get_full_configuration_descriptor(int phone,
352 usb_address_t address, int index,
353 void *buffer, size_t buffer_size, size_t *actual_buffer_size)
354{
[9b95dbcf]355 int rc = usb_drv_req_get_descriptor(phone, address,
356 USB_REQUEST_TYPE_STANDARD,
357 USB_DESCTYPE_CONFIGURATION, 0,
358 0,
359 buffer, buffer_size,
360 actual_buffer_size);
[2c5cefa]361
362 return rc;
363}
364
[276aeda]365/** Update existing descriptor of a USB device.
366 *
[863d45e]367 * @param[in] hc_phone Open phone to HC driver.
368 * @param[in] address Device address.
369 * @param[in] descriptor_type Descriptor type (device/configuration/...).
370 * @param[in] descriptor_index Descriptor index.
371 * @param[in] language Language index.
372 * @param[in] descriptor Actual descriptor data.
373 * @param[in] descriptor_size Descriptor size.
374 * @return Error code.
[276aeda]375 */
376int usb_drv_req_set_descriptor(int hc_phone, usb_address_t address,
377 uint8_t descriptor_type, uint8_t descriptor_index,
378 uint16_t language,
379 void *descriptor, size_t descriptor_size)
380{
[863d45e]381 // FIXME: check that descriptor is not too big
382
[276aeda]383 PREPARE_TARGET(target, address);
384
385 PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
386 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
387 USB_DEVREQ_SET_DESCRIPTOR, descriptor_index, descriptor_type,
388 language, descriptor_size);
389
390 int rc = usb_drv_psync_control_write(hc_phone, target,
391 &setup_packet, sizeof(setup_packet),
392 descriptor, descriptor_size);
393
394 return rc;
395}
396
397/** Determine current configuration value of USB device.
398 *
[863d45e]399 * @param[in] hc_phone Open phone to HC driver.
400 * @param[in] address Device address.
401 * @param[out] configuration_value Current configuration value.
402 * @return Error code.
[276aeda]403 */
404int usb_drv_req_get_configuration(int hc_phone, usb_address_t address,
405 uint8_t *configuration_value)
406{
407 if (configuration_value == NULL) {
408 return EBADMEM;
409 }
410
411 PREPARE_TARGET(target, address);
412
413 PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_IN,
414 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
415 USB_DEVREQ_GET_CONFIGURATION, 0, 0, 1);
416
417 uint8_t value;
418 size_t transfered;
419 int rc = usb_drv_psync_control_read(hc_phone, target,
420 &setup_packet, sizeof(setup_packet), &value, 1, &transfered);
421
422 if (rc != EOK) {
423 return rc;
424 }
425
426 if (transfered != 1) {
427 return ERANGE;
428 }
429
430 *configuration_value = value;
431
432 return EOK;
433}
434
435/** Set configuration of USB device.
436 *
[863d45e]437 * @param[in] hc_phone Open phone to HC driver.
438 * @param[in] address Device address.
439 * @param[in] configuration_value New configuration value.
440 * @return Error code.
[276aeda]441 */
442int usb_drv_req_set_configuration(int hc_phone, usb_address_t address,
443 uint8_t configuration_value)
444{
445 PREPARE_TARGET(target, address);
446
447 PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
448 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
449 USB_DEVREQ_SET_CONFIGURATION, configuration_value, 0,
450 0, 0);
451
452 int rc = usb_drv_psync_control_write(hc_phone, target,
453 &setup_packet, sizeof(setup_packet), NULL, 0);
454
455 return rc;
456}
457
458/** Determine alternate setting of USB device interface.
459 *
[863d45e]460 * @param[in] hc_phone Open phone to HC driver.
461 * @param[in] address Device address.
462 * @param[in] interface_index Interface index.
463 * @param[out] alternate_setting Value of alternate setting.
464 * @return Error code.
[276aeda]465 */
466int usb_drv_req_get_interface(int hc_phone, usb_address_t address,
467 uint16_t interface_index, uint8_t *alternate_setting)
468{
469 if (alternate_setting == NULL) {
470 return EBADMEM;
471 }
472
473 PREPARE_TARGET(target, address);
474
475 PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_IN,
476 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
477 USB_DEVREQ_GET_INTERFACE, 0, interface_index, 1);
478
479 uint8_t alternate;
480 size_t transfered;
481 int rc = usb_drv_psync_control_read(hc_phone, target,
482 &setup_packet, sizeof(setup_packet), &alternate, 1, &transfered);
483
484 if (rc != EOK) {
485 return rc;
486 }
487
488 if (transfered != 1) {
489 return ERANGE;
490 }
491
492 *alternate_setting = alternate;
493
494 return EOK;
495}
496
497/** Select an alternate setting of USB device interface.
498 *
[863d45e]499 * @param[in] hc_phone Open phone to HC driver.
500 * @param[in] address Device address.
501 * @param[in] interface_index Interface index.
502 * @param[in] alternate_setting Value of alternate setting.
503 * @return Error code.
[276aeda]504 */
505int usb_drv_req_set_interface(int hc_phone, usb_address_t address,
506 uint16_t interface_index, uint8_t alternate_setting)
507{
508 PREPARE_TARGET(target, address);
509
510 PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
511 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
512 USB_DEVREQ_SET_INTERFACE, alternate_setting, 0,
513 0, 0);
514
515 int rc = usb_drv_psync_control_write(hc_phone, target,
516 &setup_packet, sizeof(setup_packet), NULL, 0);
517
518 return rc;
519}
[9501cced]520
[f995350]521/**
522 * @}
523 */
Note: See TracBrowser for help on using the repository browser.