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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fafb8e5 was fafb8e5, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Mechanically lowercase IPC_SET_*/IPC_GET_*

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