source: mainline/uspace/lib/usb/src/hc.c@ d3ce33fa

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

Use atomic exchanges where possible

  • Property mode set to 100644
File size: 6.7 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 libusb
30 * @{
31 */
32/** @file
33 * General communication with host controller driver (implementation).
34 */
35#include <devman.h>
36#include <async.h>
37#include <dev_iface.h>
38#include <usb_iface.h>
39#include <usbhc_iface.h>
40#include <usb/hc.h>
41#include <usb/debug.h>
42#include <errno.h>
43#include <assert.h>
44
45/** Initialize connection to USB host controller.
46 *
47 * @param connection Connection to be initialized.
48 * @param device Device connecting to the host controller.
49 * @return Error code.
50 */
51int usb_hc_connection_initialize_from_device(usb_hc_connection_t *connection,
52 ddf_dev_t *device)
53{
54 assert(connection);
55
56 if (device == NULL) {
57 return EBADMEM;
58 }
59
60 devman_handle_t hc_handle;
61 int rc = usb_hc_find(device->handle, &hc_handle);
62 if (rc != EOK) {
63 return rc;
64 }
65
66 rc = usb_hc_connection_initialize(connection, hc_handle);
67
68 return rc;
69}
70
71/** Manually initialize connection to USB host controller.
72 *
73 * @param connection Connection to be initialized.
74 * @param hc_handle Devman handle of the host controller.
75 * @return Error code.
76 */
77int usb_hc_connection_initialize(usb_hc_connection_t *connection,
78 devman_handle_t hc_handle)
79{
80 assert(connection);
81
82 connection->hc_handle = hc_handle;
83 connection->hc_sess = NULL;
84
85 return EOK;
86}
87
88/** Open connection to host controller.
89 *
90 * @param connection Connection to the host controller.
91 * @return Error code.
92 */
93int usb_hc_connection_open(usb_hc_connection_t *connection)
94{
95 assert(connection);
96
97 if (usb_hc_connection_is_opened(connection))
98 return EBUSY;
99
100 async_sess_t *sess = devman_device_connect(EXCHANGE_ATOMIC,
101 connection->hc_handle, 0);
102 if (!sess)
103 return ENOMEM;
104
105 connection->hc_sess = sess;
106 return EOK;
107}
108
109/** Tells whether connection to host controller is opened.
110 *
111 * @param connection Connection to the host controller.
112 * @return Whether connection is opened.
113 */
114bool usb_hc_connection_is_opened(const usb_hc_connection_t *connection)
115{
116 assert(connection);
117 return (connection->hc_sess != NULL);
118}
119
120/** Close connection to the host controller.
121 *
122 * @param connection Connection to the host controller.
123 * @return Error code.
124 */
125int usb_hc_connection_close(usb_hc_connection_t *connection)
126{
127 assert(connection);
128
129 if (!usb_hc_connection_is_opened(connection)) {
130 return ENOENT;
131 }
132
133 int rc = async_hangup(connection->hc_sess);
134 if (rc != EOK) {
135 return rc;
136 }
137
138 connection->hc_sess = NULL;
139
140 return EOK;
141}
142
143/** Get handle of USB device with given address.
144 *
145 * @param[in] connection Opened connection to host controller.
146 * @param[in] address Address of device in question.
147 * @param[out] handle Where to write the device handle.
148 * @return Error code.
149 */
150int usb_hc_get_handle_by_address(usb_hc_connection_t *connection,
151 usb_address_t address, devman_handle_t *handle)
152{
153 if (!usb_hc_connection_is_opened(connection))
154 return ENOENT;
155
156 async_exch_t *exch = async_exchange_begin(connection->hc_sess);
157
158 sysarg_t tmp;
159 int rc = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
160 IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,
161 address, &tmp);
162
163 async_exchange_end(exch);
164
165 if ((rc == EOK) && (handle != NULL))
166 *handle = tmp;
167
168 return rc;
169}
170
171/** Tell USB address assigned to device with given handle.
172 *
173 * @param dev_handle Devman handle of the USB device in question.
174 * @return USB address or negative error code.
175 */
176usb_address_t usb_hc_get_address_by_handle(devman_handle_t dev_handle)
177{
178 async_sess_t *parent_sess =
179 devman_parent_device_connect(EXCHANGE_ATOMIC, dev_handle,
180 IPC_FLAG_BLOCKING);
181 if (!parent_sess)
182 return ENOMEM;
183
184 async_exch_t *exch = async_exchange_begin(parent_sess);
185
186 sysarg_t address;
187 int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
188 IPC_M_USB_GET_ADDRESS,
189 dev_handle, &address);
190
191 async_exchange_end(exch);
192 async_hangup(parent_sess);
193
194 if (rc != EOK)
195 return rc;
196
197 return (usb_address_t) address;
198}
199
200
201/** Get host controller handle by its class index.
202 *
203 * @param class_index Class index for the host controller.
204 * @param hc_handle Where to store the HC handle
205 * (can be NULL for existence test only).
206 * @return Error code.
207 */
208int usb_ddf_get_hc_handle_by_class(size_t class_index,
209 devman_handle_t *hc_handle)
210{
211 char *class_index_str;
212 devman_handle_t hc_handle_tmp;
213 int rc;
214
215 rc = asprintf(&class_index_str, "%zu", class_index);
216 if (rc < 0) {
217 return ENOMEM;
218 }
219 rc = devman_device_get_handle_by_class("usbhc", class_index_str,
220 &hc_handle_tmp, 0);
221 free(class_index_str);
222 if (rc != EOK) {
223 return rc;
224 }
225
226 if (hc_handle != NULL) {
227 *hc_handle = hc_handle_tmp;
228 }
229
230 return EOK;
231}
232
233/** Find host controller handle that is ancestor of given device.
234 *
235 * @param[in] device_handle Device devman handle.
236 * @param[out] hc_handle Where to store handle of host controller
237 * controlling device with @p device_handle handle.
238 * @return Error code.
239 */
240int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle)
241{
242 async_sess_t *parent_sess =
243 devman_parent_device_connect(EXCHANGE_ATOMIC, device_handle,
244 IPC_FLAG_BLOCKING);
245 if (!parent_sess)
246 return ENOMEM;
247
248 async_exch_t *exch = async_exchange_begin(parent_sess);
249
250 devman_handle_t h;
251 int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
252 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
253
254 async_exchange_end(exch);
255 async_hangup(parent_sess);
256
257 if (rc != EOK)
258 return rc;
259
260 if (hc_handle != NULL)
261 *hc_handle = h;
262
263 return EOK;
264}
265
266/**
267 * @}
268 */
Note: See TracBrowser for help on using the repository browser.