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

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

Code cleanup, various bugfixes

The internal functions of virtual device framework always get
device structure as parameter, thus possible enabling more devices
within single task (that is not possible because currently there
is no way to pass extra argument into callback_connection()).

Also, added some missing comments and completely removed the device
id nonsense (devices can send their descriptors and the hub is able
to enable/disable its ports).

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