source: mainline/uspace/lib/usbvirt/src/ipc_dev.c@ 76f566d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 76f566d was a46e56b, checked in by Jakub Jermar <jakub@…>, 7 years ago

Prefer handle over ID in naming handle variables

  • Property mode set to 100644
File size: 7.3 KB
RevLine 
[6cb58e6]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
[e25a849]33 * IPC wrappers, device side.
[6cb58e6]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
[beee81a]44/** Handle VHC request for device name.
45 *
46 * @param dev Target virtual device.
47 * @param iid Caller id.
48 * @param icall The call with the request.
49 */
[6cb58e6]50static void ipc_get_name(usbvirt_device_t *dev,
[a46e56b]51 cap_call_handle_t icall_handle, ipc_call_t *icall)
[6cb58e6]52{
53 if (dev->name == NULL) {
[a46e56b]54 async_answer_0(icall_handle, ENOENT);
[6cb58e6]55 }
56
57 size_t size = str_size(dev->name);
58
[a46e56b]59 cap_call_handle_t chandle;
[6cb58e6]60 size_t accepted_size;
[a46e56b]61 if (!async_data_read_receive(&chandle, &accepted_size)) {
62 async_answer_0(icall_handle, EINVAL);
[6cb58e6]63 return;
64 }
65
66 if (accepted_size > size) {
67 accepted_size = size;
68 }
[a46e56b]69 async_data_read_finalize(chandle, dev->name, accepted_size);
[6cb58e6]70
[a46e56b]71 async_answer_1(icall_handle, EOK, accepted_size);
[6cb58e6]72}
73
[beee81a]74/** Handle VHC request for control read from the device.
75 *
76 * @param dev Target virtual device.
77 * @param iid Caller id.
78 * @param icall The call with the request.
79 */
[6cb58e6]80static void ipc_control_read(usbvirt_device_t *dev,
[a46e56b]81 cap_call_handle_t icall_handle, ipc_call_t *icall)
[6cb58e6]82{
[b7fd2a0]83 errno_t rc;
[6cb58e6]84
85 void *setup_packet = NULL;
86 size_t setup_packet_len = 0;
87 size_t data_len = 0;
88
89 rc = async_data_write_accept(&setup_packet, false,
90 1, 1024, 0, &setup_packet_len);
91 if (rc != EOK) {
[a46e56b]92 async_answer_0(icall_handle, rc);
[6cb58e6]93 return;
94 }
95
[a46e56b]96 cap_call_handle_t data_chandle;
97 if (!async_data_read_receive(&data_chandle, &data_len)) {
98 async_answer_0(icall_handle, EPARTY);
[6cb58e6]99 free(setup_packet);
100 return;
101 }
102
103 void *buffer = malloc(data_len);
104 if (buffer == NULL) {
[a46e56b]105 async_answer_0(icall_handle, ENOMEM);
[6cb58e6]106 free(setup_packet);
107 return;
108 }
109
110 size_t actual_len;
111 rc = usbvirt_control_read(dev, setup_packet, setup_packet_len,
112 buffer, data_len, &actual_len);
113
114 if (rc != EOK) {
[a46e56b]115 async_answer_0(data_chandle, rc);
116 async_answer_0(icall_handle, rc);
[6cb58e6]117 free(setup_packet);
118 free(buffer);
119 return;
120 }
121
[a46e56b]122 async_data_read_finalize(data_chandle, buffer, actual_len);
123 async_answer_0(icall_handle, EOK);
[6cb58e6]124
125 free(setup_packet);
126 free(buffer);
127}
128
[beee81a]129/** Handle VHC request for control write to the device.
130 *
131 * @param dev Target virtual device.
132 * @param iid Caller id.
133 * @param icall The call with the request.
134 */
[6cb58e6]135static void ipc_control_write(usbvirt_device_t *dev,
[a46e56b]136 cap_call_handle_t icall_handle, ipc_call_t *icall)
[6cb58e6]137{
[beee81a]138 size_t data_buffer_len = IPC_GET_ARG1(*icall);
[b7fd2a0]139 errno_t rc;
[6cb58e6]140
141 void *setup_packet = NULL;
142 void *data_buffer = NULL;
143 size_t setup_packet_len = 0;
144
145 rc = async_data_write_accept(&setup_packet, false,
[beee81a]146 1, 0, 0, &setup_packet_len);
[6cb58e6]147 if (rc != EOK) {
[a46e56b]148 async_answer_0(icall_handle, rc);
[6cb58e6]149 return;
150 }
151
152 if (data_buffer_len > 0) {
153 rc = async_data_write_accept(&data_buffer, false,
[beee81a]154 1, 0, 0, &data_buffer_len);
[6cb58e6]155 if (rc != EOK) {
[a46e56b]156 async_answer_0(icall_handle, rc);
[6cb58e6]157 free(setup_packet);
158 return;
159 }
160 }
161
162 rc = usbvirt_control_write(dev, setup_packet, setup_packet_len,
163 data_buffer, data_buffer_len);
164
[a46e56b]165 async_answer_0(icall_handle, rc);
[beee81a]166
167 free(setup_packet);
168 if (data_buffer != NULL) {
169 free(data_buffer);
170 }
[6cb58e6]171}
172
[beee81a]173/** Handle VHC request for data read from the device (in transfer).
174 *
175 * @param dev Target virtual device.
176 * @param iid Caller id.
177 * @param icall The call with the request.
178 */
179static void ipc_data_in(usbvirt_device_t *dev,
180 usb_transfer_type_t transfer_type,
[a46e56b]181 cap_call_handle_t icall_handle, ipc_call_t *icall)
[6cb58e6]182{
183 usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
184
[b7fd2a0]185 errno_t rc;
[6cb58e6]186
187 size_t data_len = 0;
[a46e56b]188 cap_call_handle_t data_chandle;
189 if (!async_data_read_receive(&data_chandle, &data_len)) {
190 async_answer_0(icall_handle, EPARTY);
[6cb58e6]191 return;
192 }
193
194 void *buffer = malloc(data_len);
195 if (buffer == NULL) {
[a46e56b]196 async_answer_0(icall_handle, ENOMEM);
[6cb58e6]197 return;
198 }
199
200 size_t actual_len;
201 rc = usbvirt_data_in(dev, transfer_type, endpoint,
202 buffer, data_len, &actual_len);
203
204 if (rc != EOK) {
[a46e56b]205 async_answer_0(data_chandle, rc);
206 async_answer_0(icall_handle, rc);
[6cb58e6]207 free(buffer);
208 return;
209 }
210
[a46e56b]211 async_data_read_finalize(data_chandle, buffer, actual_len);
212 async_answer_0(icall_handle, EOK);
[6cb58e6]213
214 free(buffer);
215}
216
[beee81a]217/** Handle VHC request for data write to the device (out transfer).
218 *
219 * @param dev Target virtual device.
220 * @param iid Caller id.
221 * @param icall The call with the request.
222 */
223static void ipc_data_out(usbvirt_device_t *dev,
224 usb_transfer_type_t transfer_type,
[a46e56b]225 cap_call_handle_t icall_handle, ipc_call_t *icall)
[6cb58e6]226{
[aa9a53d]227 usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
228
229 void *data_buffer = NULL;
230 size_t data_buffer_size = 0;
231
[b7fd2a0]232 errno_t rc = async_data_write_accept(&data_buffer, false,
[beee81a]233 1, 0, 0, &data_buffer_size);
[aa9a53d]234 if (rc != EOK) {
[a46e56b]235 async_answer_0(icall_handle, rc);
[aa9a53d]236 return;
237 }
238
239 rc = usbvirt_data_out(dev, transfer_type, endpoint,
240 data_buffer, data_buffer_size);
241
[a46e56b]242 async_answer_0(icall_handle, rc);
[aa9a53d]243
244 free(data_buffer);
[6cb58e6]245}
246
[beee81a]247/** Handle incoming IPC call for virtual USB device.
248 *
249 * @param dev Target USB device.
[a46e56b]250 * @param chandle Caller id.
[beee81a]251 * @param call Incoming call.
252 * @return Whether the call was handled.
253 */
[6cb58e6]254bool usbvirt_ipc_handle_call(usbvirt_device_t *dev,
[a46e56b]255 cap_call_handle_t chandle, ipc_call_t *call)
[6cb58e6]256{
257 switch (IPC_GET_IMETHOD(*call)) {
[beee81a]258 case IPC_M_USBVIRT_GET_NAME:
[a46e56b]259 ipc_get_name(dev, chandle, call);
[beee81a]260 break;
261
262 case IPC_M_USBVIRT_CONTROL_READ:
[a46e56b]263 ipc_control_read(dev, chandle, call);
[beee81a]264 break;
265
266 case IPC_M_USBVIRT_CONTROL_WRITE:
[a46e56b]267 ipc_control_write(dev, chandle, call);
[beee81a]268 break;
269
270 case IPC_M_USBVIRT_INTERRUPT_IN:
[a46e56b]271 ipc_data_in(dev, USB_TRANSFER_INTERRUPT, chandle, call);
[beee81a]272 break;
[6cb58e6]273
[beee81a]274 case IPC_M_USBVIRT_BULK_IN:
[a46e56b]275 ipc_data_in(dev, USB_TRANSFER_BULK, chandle, call);
[beee81a]276 break;
[6cb58e6]277
[beee81a]278 case IPC_M_USBVIRT_INTERRUPT_OUT:
[a46e56b]279 ipc_data_out(dev, USB_TRANSFER_INTERRUPT, chandle, call);
[beee81a]280 break;
[6cb58e6]281
[beee81a]282 case IPC_M_USBVIRT_BULK_OUT:
[a46e56b]283 ipc_data_out(dev, USB_TRANSFER_BULK, chandle, call);
[beee81a]284 break;
[6cb58e6]285
286
[beee81a]287 default:
288 return false;
[6cb58e6]289 }
290
291 return true;
292}
293
294/**
295 * @}
296 */
Note: See TracBrowser for help on using the repository browser.