source: mainline/uspace/lib/usbvirt/src/ipc_hc.c@ 764d71e

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

Virtual USB refactoring

Changes include

  • add missing comments
  • add function for virtual device disconnect
  • fix memory leak
  • support for bulks
  • checking of input parameters
  • Property mode set to 100644
File size: 7.8 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 libusbvirt
30 * @{
31 */
32/** @file
33 * IPC wrappers, host controller side.
34 */
35#include <errno.h>
36#include <str.h>
37#include <stdio.h>
38#include <assert.h>
39#include <async.h>
40#include <devman.h>
41#include <usbvirt/device.h>
42#include <usbvirt/ipc.h>
43#include <usb/debug.h>
44
45/** Send control read transfer to virtual USB device.
46 *
47 * @param phone IPC phone to the virtual device.
48 * @param ep Target endpoint number.
49 * @param setup_buffer Setup buffer.
50 * @param setup_buffer_size Setup buffer size in bytes.
51 * @param data_buffer Data buffer (DATA stage of control transfer).
52 * @param data_buffer_size Size of data buffer in bytes.
53 * @param data_transfered_size Number of actually transferred bytes.
54 * @return Error code.
55 */
56int usbvirt_ipc_send_control_read(int phone,
57 void *setup_buffer, size_t setup_buffer_size,
58 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
59{
60 if (phone < 0) {
61 return EINVAL;
62 }
63 if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
64 return EINVAL;
65 }
66 if ((data_buffer == NULL) || (data_buffer_size == 0)) {
67 return EINVAL;
68 }
69
70 aid_t opening_request = async_send_0(phone,
71 IPC_M_USBVIRT_CONTROL_READ, NULL);
72 if (opening_request == 0) {
73 return ENOMEM;
74 }
75
76 int rc = async_data_write_start(phone,
77 setup_buffer, setup_buffer_size);
78 if (rc != EOK) {
79 async_wait_for(opening_request, NULL);
80 return rc;
81 }
82
83 ipc_call_t data_request_call;
84 aid_t data_request = async_data_read(phone,
85 data_buffer, data_buffer_size,
86 &data_request_call);
87
88 if (data_request == 0) {
89 async_wait_for(opening_request, NULL);
90 return ENOMEM;
91 }
92
93 sysarg_t data_request_rc;
94 sysarg_t opening_request_rc;
95 async_wait_for(data_request, &data_request_rc);
96 async_wait_for(opening_request, &opening_request_rc);
97
98 if (data_request_rc != EOK) {
99 /* Prefer the return code of the opening request. */
100 if (opening_request_rc != EOK) {
101 return (int) opening_request_rc;
102 } else {
103 return (int) data_request_rc;
104 }
105 }
106 if (opening_request_rc != EOK) {
107 return (int) opening_request_rc;
108 }
109
110 if (data_transfered_size != NULL) {
111 *data_transfered_size = IPC_GET_ARG2(data_request_call);
112 }
113
114 return EOK;
115}
116
117/** Send control write transfer to virtual USB device.
118 *
119 * @param phone IPC phone to the virtual device.
120 * @param ep Target endpoint number.
121 * @param setup_buffer Setup buffer.
122 * @param setup_buffer_size Setup buffer size in bytes.
123 * @param data_buffer Data buffer (DATA stage of control transfer).
124 * @param data_buffer_size Size of data buffer in bytes.
125 * @return Error code.
126 */
127int usbvirt_ipc_send_control_write(int phone,
128 void *setup_buffer, size_t setup_buffer_size,
129 void *data_buffer, size_t data_buffer_size)
130{
131 if (phone < 0) {
132 return EINVAL;
133 }
134 if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
135 return EINVAL;
136 }
137 if ((data_buffer_size > 0) && (data_buffer == NULL)) {
138 return EINVAL;
139 }
140
141 aid_t opening_request = async_send_1(phone,
142 IPC_M_USBVIRT_CONTROL_WRITE, data_buffer_size, NULL);
143 if (opening_request == 0) {
144 return ENOMEM;
145 }
146
147 int rc = async_data_write_start(phone,
148 setup_buffer, setup_buffer_size);
149 if (rc != EOK) {
150 async_wait_for(opening_request, NULL);
151 return rc;
152 }
153
154 if (data_buffer_size > 0) {
155 rc = async_data_write_start(phone,
156 data_buffer, data_buffer_size);
157
158 if (rc != EOK) {
159 async_wait_for(opening_request, NULL);
160 return rc;
161 }
162 }
163
164 sysarg_t opening_request_rc;
165 async_wait_for(opening_request, &opening_request_rc);
166
167 return (int) opening_request_rc;
168}
169
170/** Request data transfer from virtual USB device.
171 *
172 * @param phone IPC phone to the virtual device.
173 * @param ep Target endpoint number.
174 * @param tr_type Transfer type (interrupt or bulk).
175 * @param data Data buffer.
176 * @param data_size Size of the data buffer in bytes.
177 * @param act_size Number of actually returned bytes.
178 * @return Error code.
179 */
180int usbvirt_ipc_send_data_in(int phone, usb_endpoint_t ep,
181 usb_transfer_type_t tr_type, void *data, size_t data_size, size_t *act_size)
182{
183 if (phone < 0) {
184 return EINVAL;
185 }
186 usbvirt_hc_to_device_method_t method;
187 switch (tr_type) {
188 case USB_TRANSFER_INTERRUPT:
189 method = IPC_M_USBVIRT_INTERRUPT_IN;
190 break;
191 case USB_TRANSFER_BULK:
192 method = IPC_M_USBVIRT_BULK_IN;
193 break;
194 default:
195 return EINVAL;
196 }
197 if ((ep <= 0) || (ep >= USBVIRT_ENDPOINT_MAX)) {
198 return EINVAL;
199 }
200 if ((data == NULL) || (data_size == 0)) {
201 return EINVAL;
202 }
203
204
205 aid_t opening_request = async_send_2(phone, method, ep, tr_type, NULL);
206 if (opening_request == 0) {
207 return ENOMEM;
208 }
209
210
211 ipc_call_t data_request_call;
212 aid_t data_request = async_data_read(phone,
213 data, data_size, &data_request_call);
214
215 if (data_request == 0) {
216 async_wait_for(opening_request, NULL);
217 return ENOMEM;
218 }
219
220 sysarg_t data_request_rc;
221 sysarg_t opening_request_rc;
222 async_wait_for(data_request, &data_request_rc);
223 async_wait_for(opening_request, &opening_request_rc);
224
225 if (data_request_rc != EOK) {
226 /* Prefer the return code of the opening request. */
227 if (opening_request_rc != EOK) {
228 return (int) opening_request_rc;
229 } else {
230 return (int) data_request_rc;
231 }
232 }
233 if (opening_request_rc != EOK) {
234 return (int) opening_request_rc;
235 }
236
237 if (act_size != NULL) {
238 *act_size = IPC_GET_ARG2(data_request_call);
239 }
240
241 return EOK;
242}
243
244/** Send data to virtual USB device.
245 *
246 * @param phone IPC phone to the virtual device.
247 * @param ep Target endpoint number.
248 * @param tr_type Transfer type (interrupt or bulk).
249 * @param data Data buffer.
250 * @param data_size Size of the data buffer in bytes.
251 * @return Error code.
252 */
253int usbvirt_ipc_send_data_out(int phone, usb_endpoint_t ep,
254 usb_transfer_type_t tr_type, void *data, size_t data_size)
255{
256 if (phone < 0) {
257 return EINVAL;
258 }
259 usbvirt_hc_to_device_method_t method;
260 switch (tr_type) {
261 case USB_TRANSFER_INTERRUPT:
262 method = IPC_M_USBVIRT_INTERRUPT_OUT;
263 break;
264 case USB_TRANSFER_BULK:
265 method = IPC_M_USBVIRT_BULK_OUT;
266 break;
267 default:
268 return EINVAL;
269 }
270 if ((ep <= 0) || (ep >= USBVIRT_ENDPOINT_MAX)) {
271 return EINVAL;
272 }
273 if ((data == NULL) || (data_size == 0)) {
274 return EINVAL;
275 }
276
277 aid_t opening_request = async_send_1(phone, method, ep, NULL);
278 if (opening_request == 0) {
279 return ENOMEM;
280 }
281
282 int rc = async_data_write_start(phone,
283 data, data_size);
284 if (rc != EOK) {
285 async_wait_for(opening_request, NULL);
286 return rc;
287 }
288
289 sysarg_t opening_request_rc;
290 async_wait_for(opening_request, &opening_request_rc);
291
292 return (int) opening_request_rc;
293}
294
295
296/**
297 * @}
298 */
Note: See TracBrowser for help on using the repository browser.