source: mainline/uspace/lib/usbvirt/main.c@ 47e3a8e

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

Virtual USB device tracks its address

Now, each virtual device tracks its address and its state.

The virtual HC dispatches all transactions to all devices, thus
more precisely simulating situation on USB. The usbvirt framework
then decides whether it can accept the data or not, based on
their destination address.

  • Property mode set to 100644
File size: 5.0 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 Main handler for virtual USB device.
34 */
35#include <devmap.h>
36#include <fcntl.h>
37#include <vfs/vfs.h>
38#include <errno.h>
39#include <stdlib.h>
40
41#include "hub.h"
42#include "device.h"
43#include "private.h"
44
45#define NAMESPACE "usb"
46
47usbvirt_device_t *device = NULL;
48
49
50static void handle_data_to_device(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
55 if (address != device->address) {
56 ipc_answer_0(iid, EADDRNOTAVAIL);
57 return;
58 }
59
60 size_t len;
61 void * buffer;
62 int rc = async_data_write_accept(&buffer, false,
63 1, USB_MAX_PAYLOAD_SIZE,
64 0, &len);
65
66 if (rc != EOK) {
67 ipc_answer_0(iid, rc);
68 return;
69 }
70
71 handle_incoming_data(endpoint, buffer, len);
72
73 free(buffer);
74
75 ipc_answer_0(iid, EOK);
76}
77
78static void callback_connection(ipc_callid_t iid, ipc_call_t *icall)
79{
80 ipc_answer_0(iid, EOK);
81
82 while (true) {
83 ipc_callid_t callid;
84 ipc_call_t call;
85
86 callid = async_get_call(&call);
87 switch (IPC_GET_METHOD(call)) {
88 case IPC_M_PHONE_HUNGUP:
89 ipc_answer_0(callid, EOK);
90 return;
91
92 case IPC_M_USBVIRT_DATA_TO_DEVICE:
93 handle_data_to_device(callid, call);
94 break;
95
96 default:
97 ipc_answer_0(callid, EINVAL);
98 break;
99 }
100 }
101}
102
103static void device_init(usbvirt_device_t *dev)
104{
105 dev->send_data = usbvirt_data_to_host;
106 dev->state = USBVIRT_STATE_DEFAULT;
107 dev->address = 0;
108}
109
110int usbvirt_data_to_host(struct usbvirt_device *dev,
111 usb_endpoint_t endpoint, void *buffer, size_t size)
112{
113 int phone = dev->vhcd_phone_;
114
115 if (phone < 0) {
116 return EINVAL;
117 }
118 if ((buffer == NULL) || (size == 0)) {
119 return EINVAL;
120 }
121
122 ipc_call_t answer_data;
123 ipcarg_t answer_rc;
124 aid_t req;
125 int rc;
126
127 req = async_send_2(phone,
128 IPC_M_USBVIRT_DATA_FROM_DEVICE,
129 dev->address,
130 endpoint,
131 &answer_data);
132
133 rc = async_data_write_start(phone, buffer, size);
134 if (rc != EOK) {
135 async_wait_for(req, NULL);
136 return rc;
137 }
138
139 async_wait_for(req, &answer_rc);
140 rc = (int)answer_rc;
141 if (rc != EOK) {
142 return rc;
143 }
144
145 return EOK;
146}
147
148/** Create necessary phones for comunication with virtual HCD.
149 * This function wraps following calls:
150 * -# open <code>/dev/usb/<i>hcd_path</i></code> for reading
151 * -# access phone of file opened in previous step
152 * -# create callback through just opened phone
153 * -# create handler for calling on data from host to function
154 * -# return the (outgoing) phone
155 *
156 * @warning This function is wrapper for several actions and therefore
157 * it is not possible - in case of error - to determine at which point
158 * error occured.
159 *
160 * @param hcd_path HCD identification under devfs
161 * (without <code>/dev/usb/</code>).
162 * @param device_id Internal device identification (used by HCD).
163 * @param callback Handler for callbacks from HCD.
164 * @return EOK on success or error code from errno.h.
165 */
166int usbvirt_connect(usbvirt_device_t *dev, const char *hcd_path)
167{
168 char dev_path[DEVMAP_NAME_MAXLEN + 1];
169 snprintf(dev_path, DEVMAP_NAME_MAXLEN,
170 "/dev/%s/%s", NAMESPACE, hcd_path);
171
172 int fd = open(dev_path, O_RDONLY);
173 if (fd < 0) {
174 return fd;
175 }
176
177 int hcd_phone = fd_phone(fd);
178
179 if (hcd_phone < 0) {
180 return hcd_phone;
181 }
182
183 ipcarg_t phonehash;
184 int rc = ipc_connect_to_me(hcd_phone, 1, dev->device_id_, 0, &phonehash);
185 if (rc != EOK) {
186 return rc;
187 }
188
189 dev->vhcd_phone_ = hcd_phone;
190 device_init(dev);
191
192 device = dev;
193
194 async_new_connection(phonehash, 0, NULL, callback_connection);
195
196 return EOK;
197}
198
199
200int usbvirt_disconnect(void)
201{
202 ipc_hangup(device->vhcd_phone_);
203
204 device = NULL;
205
206 return EOK;
207}
208
209
210/**
211 * @}
212 */
Note: See TracBrowser for help on using the repository browser.