source: mainline/uspace/lib/usb/src/request.c@ a4a8cca

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

Add generic wrappers for standard control requests

  • Property mode set to 100644
File size: 7.9 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 libusb
30 * @{
31 */
32/** @file
33 * Standard USB requests (implementation).
34 */
35#include <usb/request.h>
36#include <usb/devreq.h>
37#include <errno.h>
38
39/** Prepare setup packet.
40 *
41 * @param name Variable name with the setup packet.
42 * @param p_direction Data transfer direction.
43 * @param p_type Request type (standard/class/vendor)
44 * @param p_recipient Recipient of the request.
45 * @param p_request Request.
46 * @param p_value wValue field of setup packet.
47 * @param p_index wIndex field of setup packet.
48 * @param p_length Length of extra data.
49 */
50#define PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
51 p_request, p_value, p_index, p_length) \
52 usb_device_request_setup_packet_t name = { \
53 .request_type = \
54 ((p_direction) == USB_DIRECTION_IN ? 128 : 0) \
55 | ((p_type) << 5) \
56 | (p_recipient), \
57 .request = (p_request), \
58 { .value = (p_value) }, \
59 .index = (p_index), \
60 .length = (p_length) \
61 }
62
63/** Prepare setup packet.
64 *
65 * @param name Variable name with the setup packet.
66 * @param p_direction Data transfer direction.
67 * @param p_type Request type (standard/class/vendor)
68 * @param p_recipient Recipient of the request.
69 * @param p_request Request.
70 * @param p_value_low wValue field of setup packet (low byte).
71 * @param p_value_high wValue field of setup packet (high byte).
72 * @param p_index wIndex field of setup packet.
73 * @param p_length Length of extra data.
74 */
75#define PREPARE_SETUP_PACKET_LOHI(name, p_direction, p_type, p_recipient, \
76 p_request, p_value_low, p_value_high, p_index, p_length) \
77 PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
78 p_request, (p_value_low) | ((p_value_high) << 8), \
79 p_index, p_length)
80
81#define MAX_DATA_LENGTH (~((uint16_t)0))
82
83/** Generic wrapper for SET requests using standard control request format.
84 *
85 * @see usb_endpoint_pipe_control_write
86 *
87 * @param pipe Pipe used for the communication.
88 * @param request_type Request type (standard/class/vendor).
89 * @param recipient Request recipient (e.g. device or endpoint).
90 * @param request Actual request (e.g. GET_DESCRIPTOR).
91 * @param value Value of @c wValue field of setup packet
92 * (must be in USB endianness).
93 * @param index Value of @c wIndex field of setup packet
94 * (must be in USB endianness).
95 * @param data Data to be sent during DATA stage
96 * (expected to be in USB endianness).
97 * @param data_size Size of the @p data buffer (in native endianness).
98 * @return Error code.
99 * @retval EBADMEM @p pipe is NULL.
100 * @retval EBADMEM @p data is NULL and @p data_size is not zero.
101 * @retval ERANGE Data buffer too large.
102 */
103int usb_control_request_set(usb_endpoint_pipe_t *pipe,
104 usb_request_type_t request_type, usb_request_recipient_t recipient,
105 uint8_t request,
106 uint16_t value, uint16_t index,
107 void *data, size_t data_size)
108{
109 if (pipe == NULL) {
110 return EBADMEM;
111 }
112
113 if (data_size > MAX_DATA_LENGTH) {
114 return ERANGE;
115 }
116
117 if ((data_size > 0) && (data == NULL)) {
118 return EBADMEM;
119 }
120
121 /*
122 * TODO: check that @p request_type and @p recipient are
123 * within ranges.
124 */
125
126 usb_device_request_setup_packet_t setup_packet;
127 setup_packet.request_type = (request_type << 5) | recipient;
128 setup_packet.request = request;
129 setup_packet.value = value;
130 setup_packet.index = index;
131 setup_packet.length = (uint16_t) data_size;
132
133 int rc = usb_endpoint_pipe_control_write(pipe,
134 &setup_packet, sizeof(setup_packet),
135 data, data_size);
136
137 return rc;
138}
139
140 /** Generic wrapper for GET requests using standard control request format.
141 *
142 * @see usb_endpoint_pipe_control_read
143 *
144 * @param pipe Pipe used for the communication.
145 * @param request_type Request type (standard/class/vendor).
146 * @param recipient Request recipient (e.g. device or endpoint).
147 * @param request Actual request (e.g. GET_DESCRIPTOR).
148 * @param value Value of @c wValue field of setup packet
149 * (must be in USB endianness).
150 * @param index Value of @c wIndex field of setup packet
151 * (must be in USB endianness).
152 * @param data Buffer where to store data accepted during the DATA stage.
153 * (they will come in USB endianess).
154 * @param data_size Size of the @p data buffer
155 * (in native endianness).
156 * @param actual_data_size Actual size of transfered data
157 * (in native endianness).
158 * @return Error code.
159 * @retval EBADMEM @p pipe is NULL.
160 * @retval EBADMEM @p data is NULL and @p data_size is not zero.
161 * @retval ERANGE Data buffer too large.
162 */
163int usb_control_request_get(usb_endpoint_pipe_t *pipe,
164 usb_request_type_t request_type, usb_request_recipient_t recipient,
165 uint8_t request,
166 uint16_t value, uint16_t index,
167 void *data, size_t data_size, size_t *actual_data_size)
168{
169 if (pipe == NULL) {
170 return EBADMEM;
171 }
172
173 if (data_size > MAX_DATA_LENGTH) {
174 return ERANGE;
175 }
176
177 if ((data_size > 0) && (data == NULL)) {
178 return EBADMEM;
179 }
180
181 /*
182 * TODO: check that @p request_type and @p recipient are
183 * within ranges.
184 */
185
186 usb_device_request_setup_packet_t setup_packet;
187 setup_packet.request_type = 128 | (request_type << 5) | recipient;
188 setup_packet.request = request;
189 setup_packet.value = value;
190 setup_packet.index = index;
191 setup_packet.length = (uint16_t) data_size;
192
193 int rc = usb_endpoint_pipe_control_read(pipe,
194 &setup_packet, sizeof(setup_packet),
195 data, data_size, actual_data_size);
196
197 return rc;
198}
199
200
201/** Retrieve USB descriptor of a USB device.
202 *
203 * @param[in] pipe Control endpoint pipe (session must be already started).
204 * @param[in] request_type Request type (standard/class/vendor).
205 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
206 * @param[in] descriptor_index Descriptor index.
207 * @param[in] language Language index.
208 * @param[out] buffer Buffer where to store the retrieved descriptor.
209 * @param[in] size Size of the @p buffer.
210 * @param[out] actual_size Number of bytes actually transferred.
211 * @return Error code.
212 */
213int usb_request_get_descriptor(usb_endpoint_pipe_t *pipe,
214 usb_request_type_t request_type,
215 uint8_t descriptor_type, uint8_t descriptor_index,
216 uint16_t language,
217 void *buffer, size_t size, size_t *actual_size)
218{
219 if (buffer == NULL) {
220 return EBADMEM;
221 }
222 if (size == 0) {
223 return EINVAL;
224 }
225
226 PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_IN,
227 request_type, USB_REQUEST_RECIPIENT_DEVICE,
228 USB_DEVREQ_GET_DESCRIPTOR, descriptor_index, descriptor_type,
229 language, size);
230
231 int rc = usb_endpoint_pipe_control_read(pipe,
232 &setup_packet, sizeof(setup_packet),
233 buffer, size, actual_size);
234
235 return rc;
236}
237
238/**
239 * @}
240 */
Note: See TracBrowser for help on using the repository browser.