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

Last change on this file since eec201d was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

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