source: mainline/uspace/lib/usb/src/usbdrv.c@ cb59f787

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

Rename USB interface to USBHC

USB devices themselves could have their own interface for some
general querying. This name thus seems more apropriate.

  • Property mode set to 100644
File size: 8.0 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 driver (implementation).
34 */
35#include <usb/usbdrv.h>
36#include <usbhc_iface.h>
37#include <errno.h>
38
39/** Information about pending transaction on HC. */
40typedef struct {
41 /** Phone to host controller driver. */
42 int phone;
43 /** Data buffer. */
44 void *buffer;
45 /** Buffer size. */
46 size_t size;
47 /** Storage for actual number of bytes transferred. */
48 size_t *size_transferred;
49 /** Initial call replay data. */
50 ipc_call_t reply;
51 /** Initial call identifier. */
52 aid_t request;
53} transfer_info_t;
54
55/** Connect to host controller the device is physically attached to.
56 *
57 * @param handle Device handle.
58 * @param flags Connection flags (blocking connection).
59 * @return Phone to corresponding HC or error code.
60 */
61int usb_drv_hc_connect(device_t *dev, unsigned int flags)
62{
63 /*
64 * Call parent hub to obtain device handle of respective HC.
65 */
66 return ENOTSUP;
67}
68
69/** Tell USB address assigned to given device.
70 *
71 * @param phone Phone to my HC.
72 * @param dev Device in question.
73 * @return USB address or error code.
74 */
75usb_address_t usb_drv_get_my_address(int phone, device_t *dev)
76{
77 return ENOTSUP;
78}
79
80/** Send data to HCD.
81 *
82 * @param phone Phone to HC.
83 * @param method Method used for calling.
84 * @param target Targeted device.
85 * @param buffer Data buffer (NULL to skip data transfer phase).
86 * @param size Buffer size (must be zero when @p buffer is NULL).
87 * @param handle Storage for transaction handle (cannot be NULL).
88 * @return Error status.
89 * @retval EINVAL Invalid parameter.
90 * @retval ENOMEM Not enough memory to complete the operation.
91 */
92static int async_send_buffer(int phone, int method,
93 usb_target_t target,
94 void *buffer, size_t size,
95 usb_handle_t *handle)
96{
97 if (phone < 0) {
98 return EINVAL;
99 }
100
101 if ((buffer == NULL) && (size > 0)) {
102 return EINVAL;
103 }
104
105 if (handle == NULL) {
106 return EINVAL;
107 }
108
109 transfer_info_t *transfer
110 = (transfer_info_t *) malloc(sizeof(transfer_info_t));
111 if (transfer == NULL) {
112 return ENOMEM;
113 }
114
115 transfer->size_transferred = NULL;
116 transfer->buffer = NULL;
117 transfer->size = 0;
118 transfer->phone = phone;
119
120 int rc;
121
122 transfer->request = async_send_4(phone,
123 DEV_IFACE_ID(USBHC_DEV_IFACE),
124 method,
125 target.address, target.endpoint,
126 size,
127 &transfer->reply);
128
129 if (size > 0) {
130 rc = async_data_write_start(phone, buffer, size);
131 if (rc != EOK) {
132 async_wait_for(transfer->request, NULL);
133 return rc;
134 }
135 }
136
137 *handle = (usb_handle_t) transfer;
138
139 return EOK;
140}
141
142/** Prepare data retrieval.
143 *
144 * @param phone Opened phone to HCD.
145 * @param method Method used for calling.
146 * @param target Targeted device.
147 * @param buffer Buffer where to store retrieved data
148 * (NULL to skip data transfer phase).
149 * @param size Buffer size (must be zero when @p buffer is NULL).
150 * @param actual_size Storage where actual number of bytes transferred will
151 * be stored.
152 * @param handle Storage for transaction handle (cannot be NULL).
153 * @return Error status.
154 * @retval EINVAL Invalid parameter.
155 * @retval ENOMEM Not enough memory to complete the operation.
156 */
157static int async_recv_buffer(int phone, int method,
158 usb_target_t target,
159 void *buffer, size_t size, size_t *actual_size,
160 usb_handle_t *handle)
161{
162 if (phone < 0) {
163 return EINVAL;
164 }
165
166 if ((buffer == NULL) && (size > 0)) {
167 return EINVAL;
168 }
169
170 if (handle == NULL) {
171 return EINVAL;
172 }
173
174 transfer_info_t *transfer
175 = (transfer_info_t *) malloc(sizeof(transfer_info_t));
176 if (transfer == NULL) {
177 return ENOMEM;
178 }
179
180 transfer->size_transferred = actual_size;
181 transfer->buffer = buffer;
182 transfer->size = size;
183 transfer->phone = phone;
184
185 transfer->request = async_send_4(phone,
186 DEV_IFACE_ID(USBHC_DEV_IFACE),
187 method,
188 target.address, target.endpoint,
189 size,
190 &transfer->reply);
191
192 *handle = (usb_handle_t) transfer;
193
194 return EOK;
195}
196
197/** Read buffer from HCD.
198 *
199 * @param phone Opened phone to HCD.
200 * @param hash Buffer hash (obtained after completing IN transaction).
201 * @param buffer Buffer where to store data data.
202 * @param size Buffer size.
203 * @param actual_size Storage where actual number of bytes transferred will
204 * be stored.
205 * @return Error status.
206 */
207static int read_buffer_in(int phone, ipcarg_t hash,
208 void *buffer, size_t size, size_t *actual_size)
209{
210 ipc_call_t answer_data;
211 ipcarg_t answer_rc;
212 aid_t req;
213 int rc;
214
215 req = async_send_2(phone,
216 DEV_IFACE_ID(USBHC_DEV_IFACE),
217 IPC_M_USBHC_GET_BUFFER,
218 hash,
219 &answer_data);
220
221 rc = async_data_read_start(phone, buffer, size);
222 if (rc != EOK) {
223 async_wait_for(req, NULL);
224 return EINVAL;
225 }
226
227 async_wait_for(req, &answer_rc);
228 rc = (int)answer_rc;
229
230 if (rc != EOK) {
231 return rc;
232 }
233
234 *actual_size = IPC_GET_ARG1(answer_data);
235
236 return EOK;
237}
238
239/** Blocks caller until given USB transaction is finished.
240 * After the transaction is finished, the user can access all output data
241 * given to initial call function.
242 *
243 * @param handle Transaction handle.
244 * @return Error status.
245 * @retval EOK No error.
246 * @retval EBADMEM Invalid handle.
247 * @retval ENOENT Data buffer associated with transaction does not exist.
248 */
249int usb_drv_async_wait_for(usb_handle_t handle)
250{
251 if (handle == 0) {
252 return EBADMEM;
253 }
254
255 int rc = EOK;
256
257 transfer_info_t *transfer = (transfer_info_t *) handle;
258
259 ipcarg_t answer_rc;
260 async_wait_for(transfer->request, &answer_rc);
261
262 if (answer_rc != EOK) {
263 rc = (int) answer_rc;
264 goto leave;
265 }
266
267 /*
268 * If the buffer is not NULL, we must accept some data.
269 */
270 if ((transfer->buffer != NULL) && (transfer->size > 0)) {
271 /*
272 * The buffer hash identifies the data on the server
273 * side.
274 * We will use it when actually reading-in the data.
275 */
276 ipcarg_t buffer_hash = IPC_GET_ARG1(transfer->reply);
277 if (buffer_hash == 0) {
278 rc = ENOENT;
279 goto leave;
280 }
281
282 size_t actual_size;
283 rc = read_buffer_in(transfer->phone, buffer_hash,
284 transfer->buffer, transfer->size, &actual_size);
285
286 if (rc != EOK) {
287 goto leave;
288 }
289
290 if (transfer->size_transferred) {
291 *(transfer->size_transferred) = actual_size;
292 }
293 }
294
295leave:
296 free(transfer);
297
298 return rc;
299}
300
301/** Send interrupt data to device. */
302int usb_drv_async_interrupt_out(int phone, usb_target_t target,
303 void *buffer, size_t size,
304 usb_handle_t *handle)
305{
306 return async_send_buffer(phone,
307 IPC_M_USBHC_INTERRUPT_OUT,
308 target,
309 buffer, size,
310 handle);
311}
312
313/** Request interrupt data from device. */
314int usb_drv_async_interrupt_in(int phone, usb_target_t target,
315 void *buffer, size_t size, size_t *actual_size,
316 usb_handle_t *handle)
317{
318 return async_recv_buffer(phone,
319 IPC_M_USBHC_INTERRUPT_IN,
320 target,
321 buffer, size, actual_size,
322 handle);
323}
324
325/**
326 * @}
327 */
Note: See TracBrowser for help on using the repository browser.