source: mainline/uspace/lib/usbvirt/src/callback.c@ 17aca1c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 17aca1c was 17aca1c, checked in by Vojtech Horky <vojtechhorky@…>, 14 years ago

Merge mainline changes

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2010 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 * @brief Callback connection handling.
34 */
35#include <devmap.h>
36#include <fcntl.h>
37#include <vfs/vfs.h>
38#include <errno.h>
39#include <stdlib.h>
40#include <mem.h>
41
42#include "private.h"
43
44#define NAMESPACE "usb"
45#define USB_MAX_PAYLOAD_SIZE 1020
46
47/** Wrapper for SETUP transaction over telephone. */
48static void handle_setup_transaction(usbvirt_device_t *device,
49 ipc_callid_t iid, ipc_call_t icall)
50{
51 usb_address_t address = IPC_GET_ARG1(icall);
52 usb_endpoint_t endpoint = IPC_GET_ARG2(icall);
53 size_t expected_len = IPC_GET_ARG3(icall);
54
55 if (address != device->address) {
56 async_answer_0(iid, EADDRNOTAVAIL);
57 return;
58 }
59
60 if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
61 async_answer_0(iid, EINVAL);
62 return;
63 }
64
65 if (expected_len == 0) {
66 async_answer_0(iid, EINVAL);
67 return;
68 }
69
70 size_t len = 0;
71 void * buffer = NULL;
72 int rc = async_data_write_accept(&buffer, false,
73 1, USB_MAX_PAYLOAD_SIZE, 0, &len);
74
75 if (rc != EOK) {
76 async_answer_0(iid, rc);
77 return;
78 }
79
80 rc = device->transaction_setup(device, endpoint, buffer, len);
81
82 async_answer_0(iid, rc);
83}
84
85/** Wrapper for OUT transaction over telephone. */
86static void handle_out_transaction(usbvirt_device_t *device,
87 ipc_callid_t iid, ipc_call_t icall)
88{
89 usb_address_t address = IPC_GET_ARG1(icall);
90 usb_endpoint_t endpoint = IPC_GET_ARG2(icall);
91 size_t expected_len = IPC_GET_ARG3(icall);
92
93 if (address != device->address) {
94 async_answer_0(iid, EADDRNOTAVAIL);
95 return;
96 }
97
98 if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
99 async_answer_0(iid, EINVAL);
100 return;
101 }
102
103 int rc = EOK;
104
105 size_t len = 0;
106 void *buffer = NULL;
107
108 if (expected_len > 0) {
109 rc = async_data_write_accept(&buffer, false,
110 1, USB_MAX_PAYLOAD_SIZE, 0, &len);
111
112 if (rc != EOK) {
113 async_answer_0(iid, rc);
114 return;
115 }
116 }
117
118 rc = device->transaction_out(device, endpoint, buffer, len);
119
120 if (buffer != NULL) {
121 free(buffer);
122 }
123
124 async_answer_0(iid, rc);
125}
126
127
128/** Wrapper for IN transaction over telephone. */
129static void handle_in_transaction(usbvirt_device_t *device,
130 ipc_callid_t iid, ipc_call_t icall)
131{
132 usb_address_t address = IPC_GET_ARG1(icall);
133 usb_endpoint_t endpoint = IPC_GET_ARG2(icall);
134 size_t expected_len = IPC_GET_ARG3(icall);
135
136 if (address != device->address) {
137 async_answer_0(iid, EADDRNOTAVAIL);
138 return;
139 }
140
141 if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
142 async_answer_0(iid, EINVAL);
143 return;
144 }
145
146 int rc = EOK;
147
148 void *buffer = expected_len > 0 ? malloc(expected_len) : NULL;
149 size_t len;
150
151 rc = device->transaction_in(device, endpoint, buffer, expected_len, &len);
152 /*
153 * If the request was processed, we will send data back.
154 */
155 if ((rc == EOK) && (expected_len > 0)) {
156 size_t receive_len;
157 ipc_callid_t callid;
158 if (!async_data_read_receive(&callid, &receive_len)) {
159 async_answer_0(iid, EINVAL);
160 return;
161 }
162 if (len > receive_len) {
163 len = receive_len;
164 }
165 async_data_read_finalize(callid, buffer, len);
166 }
167
168 async_answer_1(iid, rc, len);
169}
170
171/** Wrapper for getting device name. */
172static void handle_get_name(usbvirt_device_t *device,
173 ipc_callid_t iid, ipc_call_t icall)
174{
175 if (device->name == NULL) {
176 async_answer_0(iid, ENOENT);
177 }
178
179 size_t size = str_size(device->name);
180
181 ipc_callid_t callid;
182 size_t accepted_size;
183 if (!async_data_read_receive(&callid, &accepted_size)) {
184 async_answer_0(iid, EINVAL);
185 return;
186 }
187
188 if (accepted_size > size) {
189 accepted_size = size;
190 }
191 async_data_read_finalize(callid, device->name, accepted_size);
192
193 async_answer_1(iid, EOK, accepted_size);
194}
195
196/** Callback connection for a given device. */
197void device_callback_connection(usbvirt_device_t *device, ipc_callid_t iid, ipc_call_t *icall)
198{
199 async_answer_0(iid, EOK);
200
201 while (true) {
202 ipc_callid_t callid;
203 ipc_call_t call;
204
205 callid = async_get_call(&call);
206 switch (IPC_GET_IMETHOD(call)) {
207 case IPC_M_PHONE_HUNGUP:
208 async_answer_0(callid, EOK);
209 return;
210
211 case IPC_M_USBVIRT_GET_NAME:
212 handle_get_name(device, callid, call);
213 break;
214
215 case IPC_M_USBVIRT_TRANSACTION_SETUP:
216 handle_setup_transaction(device, callid, call);
217 break;
218
219 case IPC_M_USBVIRT_TRANSACTION_OUT:
220 handle_out_transaction(device, callid, call);
221 break;
222
223 case IPC_M_USBVIRT_TRANSACTION_IN:
224 handle_in_transaction(device, callid, call);
225 break;
226
227 default:
228 async_answer_0(callid, EINVAL);
229 break;
230 }
231 }
232}
233
234
235/**
236 * @}
237 */
Note: See TracBrowser for help on using the repository browser.