source: mainline/uspace/lib/usbdev/src/pipes.c@ 2c202c5

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2c202c5 was 56bdd9a4, checked in by Jan Vesely <jano.vesely@…>, 14 years ago

usb: Provide IPC wrappers instead of IPC call numbers.

Put IPC protocol in one file.
This is does not make much difference for usb_iface, but will be useful
for more complicated interfaces.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 * Copyright (c) 2011 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 libusbdev
30 * @{
31 */
32/** @file
33 * USB endpoint pipes miscellaneous functions.
34 */
35#include <usb/usb.h>
36#include <usb/dev/pipes.h>
37#include <usb/debug.h>
38#include <usb/hc.h>
39#include <usbhc_iface.h>
40#include <usb_iface.h>
41#include <devman.h>
42#include <errno.h>
43#include <assert.h>
44#include "pipepriv.h"
45
46#define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
47
48/** Tell USB address assigned to given device.
49 *
50 * @param sess Session to parent device.
51 * @param dev Device in question.
52 * @return USB address or error code.
53 */
54static usb_address_t get_my_address(async_sess_t *sess, const ddf_dev_t *dev)
55{
56 assert(sess);
57 async_exch_t *exch = async_exchange_begin(sess);
58 if (!exch)
59 return ENOMEM;
60
61 usb_address_t address;
62 const int ret = usb_get_my_address(exch, &address);
63
64 async_exchange_end(exch);
65
66 return (ret == EOK) ? address : ret;
67}
68
69/** Tell USB interface assigned to given device.
70 *
71 * @param device Device in question.
72 * @return Error code (ENOTSUP means any).
73 */
74int usb_device_get_assigned_interface(const ddf_dev_t *device)
75{
76 assert(device);
77 async_sess_t *parent_sess =
78 devman_parent_device_connect(EXCHANGE_ATOMIC, device->handle,
79 IPC_FLAG_BLOCKING);
80 if (!parent_sess)
81 return ENOMEM;
82
83 async_exch_t *exch = async_exchange_begin(parent_sess);
84 if (!exch) {
85 async_hangup(parent_sess);
86 return ENOMEM;
87 }
88
89 int iface_no;
90 const int ret = usb_get_my_interface(exch, &iface_no);
91
92 return ret == EOK ? iface_no : ret;
93}
94
95/** Initialize connection to USB device.
96 *
97 * @param connection Connection structure to be initialized.
98 * @param dev Generic device backing the USB device.
99 * @return Error code.
100 */
101int usb_device_connection_initialize_from_device(
102 usb_device_connection_t *connection, const ddf_dev_t *dev)
103{
104 assert(connection);
105 assert(dev);
106
107 int rc;
108 devman_handle_t hc_handle;
109 usb_address_t my_address;
110
111 rc = usb_hc_find(dev->handle, &hc_handle);
112 if (rc != EOK)
113 return rc;
114
115 async_sess_t *parent_sess =
116 devman_parent_device_connect(EXCHANGE_ATOMIC, dev->handle,
117 IPC_FLAG_BLOCKING);
118 if (!parent_sess)
119 return ENOMEM;
120
121 /*
122 * Asking for "my" address may require several attempts.
123 * That is because following scenario may happen:
124 * - parent driver (i.e. driver of parent device) announces new device
125 * and devman launches current driver
126 * - parent driver is preempted and thus does not send address-handle
127 * binding to HC driver
128 * - this driver gets here and wants the binding
129 * - the HC does not know the binding yet and thus it answers ENOENT
130 * So, we need to wait for the HC to learn the binding.
131 */
132
133 do {
134 my_address = get_my_address(parent_sess, dev);
135
136 if (my_address == ENOENT) {
137 /* Be nice, let other fibrils run and try again. */
138 async_usleep(IPC_AGAIN_DELAY);
139 } else if (my_address < 0) {
140 /* Some other problem, no sense trying again. */
141 rc = my_address;
142 goto leave;
143 }
144
145 } while (my_address < 0);
146
147 rc = usb_device_connection_initialize(connection,
148 hc_handle, my_address);
149
150leave:
151 async_hangup(parent_sess);
152 return rc;
153}
154
155/** Initialize connection to USB device.
156 *
157 * @param connection Connection structure to be initialized.
158 * @param host_controller_handle Devman handle of host controller device is
159 * connected to.
160 * @param device_address Device USB address.
161 * @return Error code.
162 */
163int usb_device_connection_initialize(usb_device_connection_t *connection,
164 devman_handle_t host_controller_handle, usb_address_t device_address)
165{
166 assert(connection);
167
168 if ((device_address < 0) || (device_address >= USB11_ADDRESS_MAX)) {
169 return EINVAL;
170 }
171
172 connection->hc_handle = host_controller_handle;
173 connection->address = device_address;
174
175 return EOK;
176}
177
178/** Initialize connection to USB device on default address.
179 *
180 * @param dev_connection Device connection structure to be initialized.
181 * @param hc_connection Initialized connection to host controller.
182 * @return Error code.
183 */
184int usb_device_connection_initialize_on_default_address(
185 usb_device_connection_t *dev_connection,
186 usb_hc_connection_t *hc_connection)
187{
188 assert(dev_connection);
189
190 if (hc_connection == NULL) {
191 return EBADMEM;
192 }
193
194 return usb_device_connection_initialize(dev_connection,
195 hc_connection->hc_handle, (usb_address_t) 0);
196}
197
198/** Prepare pipe for a long transfer.
199 *
200 * By a long transfer is mean transfer consisting of several
201 * requests to the HC.
202 * Calling such function is optional and it has positive effect of
203 * improved performance because IPC session is initiated only once.
204 *
205 * @param pipe Pipe over which the transfer will happen.
206 * @return Error code.
207 */
208void usb_pipe_start_long_transfer(usb_pipe_t *pipe)
209{
210 (void) pipe_add_ref(pipe, true);
211}
212
213/** Terminate a long transfer on a pipe.
214 *
215 * @see usb_pipe_start_long_transfer
216 *
217 * @param pipe Pipe where to end the long transfer.
218 */
219void usb_pipe_end_long_transfer(usb_pipe_t *pipe)
220{
221 pipe_drop_ref(pipe);
222}
223
224/**
225 * @}
226 */
Note: See TracBrowser for help on using the repository browser.