source: mainline/uspace/lib/usbvirt/src/callback.c@ 0eddb76

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

libusbvirt directoy structure reorganized

  • Property mode set to 100644
File size: 5.7 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 usb
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 ipc_answer_0(iid, EADDRNOTAVAIL);
57 return;
58 }
59
60 if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
61 ipc_answer_0(iid, EINVAL);
62 return;
63 }
64
65 if (expected_len == 0) {
66 ipc_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 ipc_answer_0(iid, rc);
77 return;
78 }
79
80 rc = device->transaction_setup(device, endpoint, buffer, len);
81
82 ipc_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 ipc_answer_0(iid, EADDRNOTAVAIL);
95 return;
96 }
97
98 if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
99 ipc_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 ipc_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 ipc_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 ipc_answer_0(iid, EADDRNOTAVAIL);
138 return;
139 }
140
141 if ((endpoint < 0) || (endpoint >= USB11_ENDPOINT_MAX)) {
142 ipc_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) {
156 size_t receive_len;
157 ipc_callid_t callid;
158 if (!async_data_read_receive(&callid, &receive_len)) {
159 ipc_answer_0(iid, EINVAL);
160 return;
161 }
162 async_data_read_finalize(callid, buffer, receive_len);
163 }
164
165 ipc_answer_0(iid, rc);
166}
167
168/** Wrapper for getting device name. */
169static void handle_get_name(usbvirt_device_t *device,
170 ipc_callid_t iid, ipc_call_t icall)
171{
172 if (device->name == NULL) {
173 ipc_answer_0(iid, ENOENT);
174 }
175
176 size_t size = str_size(device->name);
177
178 ipc_callid_t callid;
179 size_t accepted_size;
180 if (!async_data_read_receive(&callid, &accepted_size)) {
181 ipc_answer_0(iid, EINVAL);
182 return;
183 }
184
185 if (accepted_size > size) {
186 accepted_size = size;
187 }
188 async_data_read_finalize(callid, device->name, accepted_size);
189
190 ipc_answer_1(iid, EOK, accepted_size);
191}
192
193/** Callback connection for a given device. */
194void device_callback_connection(usbvirt_device_t *device, ipc_callid_t iid, ipc_call_t *icall)
195{
196 ipc_answer_0(iid, EOK);
197
198 while (true) {
199 ipc_callid_t callid;
200 ipc_call_t call;
201
202 callid = async_get_call(&call);
203 switch (IPC_GET_METHOD(call)) {
204 case IPC_M_PHONE_HUNGUP:
205 ipc_answer_0(callid, EOK);
206 return;
207
208 case IPC_M_USBVIRT_GET_NAME:
209 handle_get_name(device, callid, call);
210 break;
211
212 case IPC_M_USBVIRT_TRANSACTION_SETUP:
213 handle_setup_transaction(device, callid, call);
214 break;
215
216 case IPC_M_USBVIRT_TRANSACTION_OUT:
217 handle_out_transaction(device, callid, call);
218 break;
219
220 case IPC_M_USBVIRT_TRANSACTION_IN:
221 handle_in_transaction(device, callid, call);
222 break;
223
224 default:
225 ipc_answer_0(callid, EINVAL);
226 break;
227 }
228 }
229}
230
231
232/**
233 * @}
234 */
Note: See TracBrowser for help on using the repository browser.