source: mainline/uspace/lib/usb/hcd.c@ 23cb44b

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

Update of libusb/HC methods

  • Property mode set to 100644
File size: 8.8 KB
Line 
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
29/** @addtogroup libusb usb
30 * @{
31 */
32/** @file
33 * @brief USB Host Controller Driver (implementation).
34 */
35#include "hcd.h"
36#include <devmap.h>
37#include <fcntl.h>
38#include <vfs/vfs.h>
39#include <errno.h>
40
41
42#define NAMESPACE "usb"
43
44/** String representation for USB transfer type. */
45const char * usb_str_transfer_type(usb_transfer_type_t t)
46{
47 switch (t) {
48 case USB_TRANSFER_ISOCHRONOUS:
49 return "isochronous";
50 case USB_TRANSFER_INTERRUPT:
51 return "interrupt";
52 case USB_TRANSFER_CONTROL:
53 return "control";
54 case USB_TRANSFER_BULK:
55 return "bulk";
56 default:
57 return "unknown";
58 }
59}
60
61/** String representation of USB transaction outcome. */
62const char * usb_str_transaction_outcome(usb_transaction_outcome_t o)
63{
64 switch (o) {
65 case USB_OUTCOME_OK:
66 return "ok";
67 case USB_OUTCOME_CRCERROR:
68 return "CRC error";
69 case USB_OUTCOME_BABBLE:
70 return "babble";
71 default:
72 return "unknown";
73 }
74}
75
76/** Create necessary phones for comunicating with HCD.
77 * This function wraps following calls:
78 * -# open <code>/dev/usb/<i>hcd_path</i></code> for reading
79 * -# access phone of file opened in previous step
80 * -# create callback through just opened phone
81 * -# set handler for this callback
82 * -# return the (outgoing) phone
83 *
84 * @warning This function is wrapper for several actions and therefore
85 * it is not possible - in case of error - to determine at which point
86 * error occured.
87 *
88 * @param hcd_path HCD identification under devfs
89 * (without <code>/dev/usb/</code>).
90 * @param callback_connection Handler for callbacks from HCD.
91 * @return Phone for comunicating with HCD or error code from errno.h.
92 */
93int usb_hcd_create_phones(const char * hcd_path,
94 async_client_conn_t callback_connection)
95{
96 char dev_path[DEVMAP_NAME_MAXLEN + 1];
97 snprintf(dev_path, DEVMAP_NAME_MAXLEN,
98 "/dev/%s/%s", NAMESPACE, hcd_path);
99
100 int fd = open(dev_path, O_RDONLY);
101 if (fd < 0) {
102 return fd;
103 }
104
105 int hcd_phone = fd_phone(fd);
106
107 if (hcd_phone < 0) {
108 return hcd_phone;
109 }
110
111 ipcarg_t phonehash;
112 int rc = ipc_connect_to_me(hcd_phone, 0, 0, 0, &phonehash);
113 if (rc != EOK) {
114 return rc;
115 }
116 async_new_connection(phonehash, 0, NULL, callback_connection);
117
118 return hcd_phone;
119}
120
121/** Send data from USB host to a function.
122 *
123 * @param hcd_phone Connected phone to HCD.
124 * @param target USB function address.
125 * @param transfer_type USB transfer type.
126 * @param buffer Buffer with data to be sent.
127 * @param len Buffer @p buffer size.
128 * @param[out] transaction_handle Handle of created transaction (NULL to ignore).
129 * @return Error status.
130 * @retval EOK Everything OK, buffer transfered to HCD and queued there.
131 * @retval EINVAL Invalid phone.
132 * @retval EINVAL @p buffer is NULL.
133 */
134int usb_hcd_send_data_to_function(int hcd_phone,
135 usb_target_t target, usb_transfer_type_t transfer_type,
136 void * buffer, size_t len,
137 usb_transaction_handle_t * transaction_handle)
138{
139 if (hcd_phone < 0) {
140 return EINVAL;
141 }
142 if (buffer == NULL) {
143 return EINVAL;
144 }
145
146 ipc_call_t answer_data;
147 ipcarg_t answer_rc;
148 aid_t req;
149 int rc;
150
151 req = async_send_4(hcd_phone,
152 IPC_M_USB_HCD_SEND_DATA,
153 target.address, target.endpoint,
154 transfer_type, 0,
155 &answer_data);
156
157 rc = async_data_write_start(hcd_phone, buffer, len);
158 if (rc != EOK) {
159 async_wait_for(req, NULL);
160 return rc;
161 }
162
163 async_wait_for(req, &answer_rc);
164 rc = (int)answer_rc;
165 if (rc != EOK) {
166 return rc;
167 }
168
169 if (transaction_handle != NULL) {
170 *transaction_handle = IPC_GET_ARG1(answer_data);
171 }
172
173 return EOK;
174}
175
176
177/** Inform HCD about data reception.
178 * The actual reception is handled in callback.
179 *
180 * @param hcd_phone Connected phone to HCD.
181 * @param target USB function address.
182 * @param transfer_type USB transfer type.
183 * @param len Maximum accepted packet size.
184 * @param[out] transaction_handle Handle of created transaction (NULL to ignore).
185 * @return Error status.
186 */
187int usb_hcd_prepare_data_reception(int hcd_phone,
188 usb_target_t target, usb_transfer_type_t transfer_type,
189 size_t len,
190 usb_transaction_handle_t * transaction_handle)
191{
192 if (hcd_phone < 0) {
193 return EINVAL;
194 }
195
196 usb_transaction_handle_t handle;
197
198 int rc = ipc_call_sync_5_1(hcd_phone, IPC_M_USB_HCD_RECEIVE_DATA,
199 target.address, target.endpoint,
200 transfer_type, len, 0, &handle);
201
202 if (rc != EOK) {
203 return rc;
204 }
205
206 if (transaction_handle != NULL) {
207 *transaction_handle = handle;
208 }
209
210 return EOK;
211}
212
213
214static int send_buffer(int phone, ipcarg_t method, usb_target_t target,
215 void *buffer, size_t size, usb_transaction_handle_t * transaction_handle)
216{
217 if (phone < 0) {
218 return EINVAL;
219 }
220
221 if ((buffer == NULL) && (size > 0)) {
222 return EINVAL;
223 }
224
225 ipc_call_t answer_data;
226 ipcarg_t answer_rc;
227 aid_t req;
228 int rc;
229
230 req = async_send_3(phone,
231 method,
232 target.address, target.endpoint,
233 size,
234 &answer_data);
235
236 if (size > 0) {
237 rc = async_data_write_start(phone, buffer, size);
238 if (rc != EOK) {
239 async_wait_for(req, NULL);
240 return rc;
241 }
242 }
243
244 async_wait_for(req, &answer_rc);
245 rc = (int)answer_rc;
246 if (rc != EOK) {
247 return rc;
248 }
249
250 if (transaction_handle != NULL) {
251 *transaction_handle = IPC_GET_ARG1(answer_data);
252 }
253
254 return EOK;
255}
256
257
258static int prep_receive_data(int phone, ipcarg_t method, usb_target_t target,
259 size_t size, usb_transaction_handle_t * transaction_handle)
260{
261 if (phone < 0) {
262 return EINVAL;
263 }
264
265 usb_transaction_handle_t handle;
266
267 int rc = ipc_call_sync_3_1(phone,
268 method,
269 target.address, target.endpoint,
270 size,
271 &handle);
272
273 if (rc != EOK) {
274 return rc;
275 }
276
277 if (transaction_handle != NULL) {
278 *transaction_handle = handle;
279 }
280
281 return EOK;
282}
283
284
285int usb_hcd_transfer_interrupt_out(int hcd_phone, usb_target_t target,
286 void *buffer, size_t size, usb_transaction_handle_t *handle)
287{
288 return send_buffer(hcd_phone, IPC_M_USB_HCD_INTERRUPT_OUT,
289 target, buffer, size, handle);
290}
291
292int usb_hcd_transfer_interrupt_in(int hcd_phone, usb_target_t target,
293 size_t size, usb_transaction_handle_t *handle)
294{
295 return prep_receive_data(hcd_phone, IPC_M_USB_HCD_INTERRUPT_IN,
296 target, size, handle);
297}
298
299int usb_hcd_transfer_control_write_setup(int hcd_phone, usb_target_t target,
300 void *buffer, size_t size, usb_transaction_handle_t *handle)
301{
302 return send_buffer(hcd_phone, IPC_M_USB_HCD_CONTROL_WRITE_SETUP,
303 target, buffer, size, handle);
304}
305
306int usb_hcd_transfer_control_write_data(int hcd_phone, usb_target_t target,
307 void *buffer, size_t size, usb_transaction_handle_t *handle)
308{
309 return send_buffer(hcd_phone, IPC_M_USB_HCD_CONTROL_WRITE_DATA,
310 target, buffer, size, handle);
311
312}
313int usb_hcd_transfer_control_write_status(int hcd_phone, usb_target_t target,
314 usb_transaction_handle_t *handle)
315{
316 return prep_receive_data(hcd_phone, IPC_M_USB_HCD_CONTROL_WRITE_STATUS,
317 target, 0, handle);
318}
319
320int usb_hcd_transfer_control_read_setup(int hcd_phone, usb_target_t target,
321 void *buffer, size_t size, usb_transaction_handle_t *handle)
322{
323 return send_buffer(hcd_phone, IPC_M_USB_HCD_CONTROL_READ_SETUP,
324 target, buffer, size, handle);
325}
326int usb_hcd_transfer_control_read_data(int hcd_phone, usb_target_t target,
327 size_t size, usb_transaction_handle_t *handle)
328{
329 return prep_receive_data(hcd_phone, IPC_M_USB_HCD_CONTROL_READ_DATA,
330 target, size, handle);
331}
332int usb_hcd_transfer_control_read_status(int hcd_phone, usb_target_t target,
333 usb_transaction_handle_t *handle)
334{
335 return send_buffer(hcd_phone, IPC_M_USB_HCD_CONTROL_READ_STATUS,
336 target, NULL, 0, handle);
337}
338
339
340
341/**
342 * @}
343 */
Note: See TracBrowser for help on using the repository browser.