source: mainline/uspace/lib/usbvirt/callback.c@ aca85e4

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

Directory structure reorganization

USB class-specific headers are in separate directory.

Removed unused/unreachable code.

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