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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d3ce33fa was 79ae36dd, checked in by Martin Decky <martin@…>, 14 years ago

new async framework with integrated exchange tracking

  • strict isolation between low-level IPC and high-level async framework with integrated exchange tracking
    • each IPC connection is represented by an async_sess_t structure
    • each IPC exchange is represented by an async_exch_t structure
    • exchange management is either based on atomic messages (EXCHANGE_ATOMIC), locking (EXCHANGE_SERIALIZE) or connection cloning (EXCHANGE_CLONE)
  • async_obsolete: temporary compatibility layer to keep old async clients working (several pieces of code are currently broken, but only non-essential functionality)
  • IPC_M_PHONE_HANGUP is now method no. 0 (for elegant boolean evaluation)
  • IPC_M_DEBUG_ALL has been renamed to IPC_M_DEBUG
  • IPC_M_PING has been removed (VFS protocol now has VFS_IN_PING)
  • console routines in libc have been rewritten for better abstraction
  • additional use for libc-private header files (FILE structure opaque to the client)
  • various cstyle changes (typos, indentation, missing externs in header files, improved comments, etc.)
  • Property mode set to 100644
File size: 8.2 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 sess Session 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 *
55 * @return Error code.
56 *
57 */
58int usbvirt_ipc_send_control_read(async_sess_t *sess, void *setup_buffer,
59 size_t setup_buffer_size, void *data_buffer, size_t data_buffer_size,
60 size_t *data_transfered_size)
61{
62 if (!sess)
63 return EINVAL;
64
65 if ((setup_buffer == NULL) || (setup_buffer_size == 0))
66 return EINVAL;
67
68 if ((data_buffer == NULL) || (data_buffer_size == 0))
69 return EINVAL;
70
71 async_exch_t *exch = async_exchange_begin(sess);
72
73 aid_t opening_request = async_send_0(exch, IPC_M_USBVIRT_CONTROL_READ,
74 NULL);
75 if (opening_request == 0) {
76 async_exchange_end(exch);
77 return ENOMEM;
78 }
79
80 int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
81 if (rc != EOK) {
82 async_exchange_end(exch);
83 async_wait_for(opening_request, NULL);
84 return rc;
85 }
86
87 ipc_call_t data_request_call;
88 aid_t data_request = async_data_read(exch, data_buffer, data_buffer_size,
89 &data_request_call);
90
91 async_exchange_end(exch);
92
93 if (data_request == 0) {
94 async_wait_for(opening_request, NULL);
95 return ENOMEM;
96 }
97
98 sysarg_t data_request_rc;
99 sysarg_t opening_request_rc;
100 async_wait_for(data_request, &data_request_rc);
101 async_wait_for(opening_request, &opening_request_rc);
102
103 if (data_request_rc != EOK) {
104 /* Prefer the return code of the opening request. */
105 if (opening_request_rc != EOK)
106 return (int) opening_request_rc;
107 else
108 return (int) data_request_rc;
109 }
110
111 if (opening_request_rc != EOK)
112 return (int) opening_request_rc;
113
114 if (data_transfered_size != NULL)
115 *data_transfered_size = IPC_GET_ARG2(data_request_call);
116
117 return EOK;
118}
119
120/** Send control write transfer to virtual USB device.
121 *
122 * @param sess Session to the virtual device.
123 * @param ep Target endpoint number.
124 * @param setup_buffer Setup buffer.
125 * @param setup_buffer_size Setup buffer size in bytes.
126 * @param data_buffer Data buffer (DATA stage of control transfer).
127 * @param data_buffer_size Size of data buffer in bytes.
128 *
129 * @return Error code.
130 *
131 */
132int usbvirt_ipc_send_control_write(async_sess_t *sess, void *setup_buffer,
133 size_t setup_buffer_size, void *data_buffer, size_t data_buffer_size)
134{
135 if (!sess)
136 return EINVAL;
137
138 if ((setup_buffer == NULL) || (setup_buffer_size == 0))
139 return EINVAL;
140
141 if ((data_buffer_size > 0) && (data_buffer == NULL))
142 return EINVAL;
143
144 async_exch_t *exch = async_exchange_begin(sess);
145
146 aid_t opening_request = async_send_1(exch, IPC_M_USBVIRT_CONTROL_WRITE,
147 data_buffer_size, NULL);
148 if (opening_request == 0) {
149 async_exchange_end(exch);
150 return ENOMEM;
151 }
152
153 int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
154 if (rc != EOK) {
155 async_exchange_end(exch);
156 async_wait_for(opening_request, NULL);
157 return rc;
158 }
159
160 if (data_buffer_size > 0) {
161 rc = async_data_write_start(exch, data_buffer, data_buffer_size);
162 if (rc != EOK) {
163 async_exchange_end(exch);
164 async_wait_for(opening_request, NULL);
165 return rc;
166 }
167 }
168
169 async_exchange_end(exch);
170
171 sysarg_t opening_request_rc;
172 async_wait_for(opening_request, &opening_request_rc);
173
174 return (int) opening_request_rc;
175}
176
177/** Request data transfer from virtual USB device.
178 *
179 * @param sess Session to the virtual device.
180 * @param ep Target endpoint number.
181 * @param tr_type Transfer type (interrupt or bulk).
182 * @param data Data buffer.
183 * @param data_size Size of the data buffer in bytes.
184 * @param act_size Number of actually returned bytes.
185 *
186 * @return Error code.
187 *
188 */
189int usbvirt_ipc_send_data_in(async_sess_t *sess, usb_endpoint_t ep,
190 usb_transfer_type_t tr_type, void *data, size_t data_size, size_t *act_size)
191{
192 if (!sess)
193 return EINVAL;
194
195 usbvirt_hc_to_device_method_t method;
196
197 switch (tr_type) {
198 case USB_TRANSFER_INTERRUPT:
199 method = IPC_M_USBVIRT_INTERRUPT_IN;
200 break;
201 case USB_TRANSFER_BULK:
202 method = IPC_M_USBVIRT_BULK_IN;
203 break;
204 default:
205 return EINVAL;
206 }
207
208 if ((ep <= 0) || (ep >= USBVIRT_ENDPOINT_MAX))
209 return EINVAL;
210
211 if ((data == NULL) || (data_size == 0))
212 return EINVAL;
213
214 async_exch_t *exch = async_exchange_begin(sess);
215
216 aid_t opening_request = async_send_2(exch, method, ep, tr_type, NULL);
217 if (opening_request == 0) {
218 async_exchange_end(exch);
219 return ENOMEM;
220 }
221
222 ipc_call_t data_request_call;
223 aid_t data_request = async_data_read(exch, data, data_size,
224 &data_request_call);
225
226 async_exchange_end(exch);
227
228 if (data_request == 0) {
229 async_wait_for(opening_request, NULL);
230 return ENOMEM;
231 }
232
233 sysarg_t data_request_rc;
234 sysarg_t opening_request_rc;
235 async_wait_for(data_request, &data_request_rc);
236 async_wait_for(opening_request, &opening_request_rc);
237
238 if (data_request_rc != EOK) {
239 /* Prefer the return code of the opening request. */
240 if (opening_request_rc != EOK)
241 return (int) opening_request_rc;
242 else
243 return (int) data_request_rc;
244 }
245
246 if (opening_request_rc != EOK)
247 return (int) opening_request_rc;
248
249 if (act_size != NULL)
250 *act_size = IPC_GET_ARG2(data_request_call);
251
252 return EOK;
253}
254
255/** Send data to virtual USB device.
256 *
257 * @param sess Session to the virtual device.
258 * @param ep Target endpoint number.
259 * @param tr_type Transfer type (interrupt or bulk).
260 * @param data Data buffer.
261 * @param data_size Size of the data buffer in bytes.
262 *
263 * @return Error code.
264 *
265 */
266int usbvirt_ipc_send_data_out(async_sess_t *sess, usb_endpoint_t ep,
267 usb_transfer_type_t tr_type, void *data, size_t data_size)
268{
269 if (!sess)
270 return EINVAL;
271
272 usbvirt_hc_to_device_method_t method;
273
274 switch (tr_type) {
275 case USB_TRANSFER_INTERRUPT:
276 method = IPC_M_USBVIRT_INTERRUPT_OUT;
277 break;
278 case USB_TRANSFER_BULK:
279 method = IPC_M_USBVIRT_BULK_OUT;
280 break;
281 default:
282 return EINVAL;
283 }
284
285 if ((ep <= 0) || (ep >= USBVIRT_ENDPOINT_MAX))
286 return EINVAL;
287
288 if ((data == NULL) || (data_size == 0))
289 return EINVAL;
290
291 async_exch_t *exch = async_exchange_begin(sess);
292
293 aid_t opening_request = async_send_1(exch, method, ep, NULL);
294 if (opening_request == 0) {
295 async_exchange_end(exch);
296 return ENOMEM;
297 }
298
299 int rc = async_data_write_start(exch, data, data_size);
300
301 async_exchange_end(exch);
302
303 if (rc != EOK) {
304 async_wait_for(opening_request, NULL);
305 return rc;
306 }
307
308 sysarg_t opening_request_rc;
309 async_wait_for(opening_request, &opening_request_rc);
310
311 return (int) opening_request_rc;
312}
313
314/**
315 * @}
316 */
Note: See TracBrowser for help on using the repository browser.