source: mainline/uspace/lib/usbvirt/src/ipc_dev.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: 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.