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
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, device 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
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 */
50static void ipc_get_name(usbvirt_device_t *dev,
51 cap_call_handle_t icall_handle, ipc_call_t *icall)
52{
53 if (dev->name == NULL) {
54 async_answer_0(icall_handle, ENOENT);
55 }
56
57 size_t size = str_size(dev->name);
58
59 cap_call_handle_t chandle;
60 size_t accepted_size;
61 if (!async_data_read_receive(&chandle, &accepted_size)) {
62 async_answer_0(icall_handle, EINVAL);
63 return;
64 }
65
66 if (accepted_size > size) {
67 accepted_size = size;
68 }
69 async_data_read_finalize(chandle, dev->name, accepted_size);
70
71 async_answer_1(icall_handle, EOK, accepted_size);
72}
73
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 */
80static void ipc_control_read(usbvirt_device_t *dev,
81 cap_call_handle_t icall_handle, ipc_call_t *icall)
82{
83 errno_t rc;
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) {
92 async_answer_0(icall_handle, rc);
93 return;
94 }
95
96 cap_call_handle_t data_chandle;
97 if (!async_data_read_receive(&data_chandle, &data_len)) {
98 async_answer_0(icall_handle, EPARTY);
99 free(setup_packet);
100 return;
101 }
102
103 void *buffer = malloc(data_len);
104 if (buffer == NULL) {
105 async_answer_0(icall_handle, ENOMEM);
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) {
115 async_answer_0(data_chandle, rc);
116 async_answer_0(icall_handle, rc);
117 free(setup_packet);
118 free(buffer);
119 return;
120 }
121
122 async_data_read_finalize(data_chandle, buffer, actual_len);
123 async_answer_0(icall_handle, EOK);
124
125 free(setup_packet);
126 free(buffer);
127}
128
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 */
135static void ipc_control_write(usbvirt_device_t *dev,
136 cap_call_handle_t icall_handle, ipc_call_t *icall)
137{
138 size_t data_buffer_len = IPC_GET_ARG1(*icall);
139 errno_t rc;
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,
146 1, 0, 0, &setup_packet_len);
147 if (rc != EOK) {
148 async_answer_0(icall_handle, rc);
149 return;
150 }
151
152 if (data_buffer_len > 0) {
153 rc = async_data_write_accept(&data_buffer, false,
154 1, 0, 0, &data_buffer_len);
155 if (rc != EOK) {
156 async_answer_0(icall_handle, rc);
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
165 async_answer_0(icall_handle, rc);
166
167 free(setup_packet);
168 if (data_buffer != NULL) {
169 free(data_buffer);
170 }
171}
172
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,
181 cap_call_handle_t icall_handle, ipc_call_t *icall)
182{
183 usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
184
185 errno_t rc;
186
187 size_t data_len = 0;
188 cap_call_handle_t data_chandle;
189 if (!async_data_read_receive(&data_chandle, &data_len)) {
190 async_answer_0(icall_handle, EPARTY);
191 return;
192 }
193
194 void *buffer = malloc(data_len);
195 if (buffer == NULL) {
196 async_answer_0(icall_handle, ENOMEM);
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) {
205 async_answer_0(data_chandle, rc);
206 async_answer_0(icall_handle, rc);
207 free(buffer);
208 return;
209 }
210
211 async_data_read_finalize(data_chandle, buffer, actual_len);
212 async_answer_0(icall_handle, EOK);
213
214 free(buffer);
215}
216
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,
225 cap_call_handle_t icall_handle, ipc_call_t *icall)
226{
227 usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
228
229 void *data_buffer = NULL;
230 size_t data_buffer_size = 0;
231
232 errno_t rc = async_data_write_accept(&data_buffer, false,
233 1, 0, 0, &data_buffer_size);
234 if (rc != EOK) {
235 async_answer_0(icall_handle, rc);
236 return;
237 }
238
239 rc = usbvirt_data_out(dev, transfer_type, endpoint,
240 data_buffer, data_buffer_size);
241
242 async_answer_0(icall_handle, rc);
243
244 free(data_buffer);
245}
246
247/** Handle incoming IPC call for virtual USB device.
248 *
249 * @param dev Target USB device.
250 * @param chandle Caller id.
251 * @param call Incoming call.
252 * @return Whether the call was handled.
253 */
254bool usbvirt_ipc_handle_call(usbvirt_device_t *dev,
255 cap_call_handle_t chandle, ipc_call_t *call)
256{
257 switch (IPC_GET_IMETHOD(*call)) {
258 case IPC_M_USBVIRT_GET_NAME:
259 ipc_get_name(dev, chandle, call);
260 break;
261
262 case IPC_M_USBVIRT_CONTROL_READ:
263 ipc_control_read(dev, chandle, call);
264 break;
265
266 case IPC_M_USBVIRT_CONTROL_WRITE:
267 ipc_control_write(dev, chandle, call);
268 break;
269
270 case IPC_M_USBVIRT_INTERRUPT_IN:
271 ipc_data_in(dev, USB_TRANSFER_INTERRUPT, chandle, call);
272 break;
273
274 case IPC_M_USBVIRT_BULK_IN:
275 ipc_data_in(dev, USB_TRANSFER_BULK, chandle, call);
276 break;
277
278 case IPC_M_USBVIRT_INTERRUPT_OUT:
279 ipc_data_out(dev, USB_TRANSFER_INTERRUPT, chandle, call);
280 break;
281
282 case IPC_M_USBVIRT_BULK_OUT:
283 ipc_data_out(dev, USB_TRANSFER_BULK, chandle, call);
284 break;
285
286
287 default:
288 return false;
289 }
290
291 return true;
292}
293
294/**
295 * @}
296 */
Note: See TracBrowser for help on using the repository browser.