source: mainline/uspace/lib/usb/src/dev.c@ 5debe97

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

libusb: DCE

  • Property mode set to 100644
File size: 5.2 KB
Line 
1/*
2 * Copyright (c) 2011 Jan Vesely
3 * Copyright (c) 2011 Vojtech Horky
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <usb/dev.h>
31#include <usb/hc.h>
32#include <errno.h>
33#include <usb_iface.h>
34#include <str.h>
35#include <stdio.h>
36
37#define MAX_DEVICE_PATH 1024
38
39static bool try_parse_bus_and_address(const char *path,
40 char **func_start,
41 devman_handle_t *out_hc_handle, usb_address_t *out_device_address)
42{
43 uint64_t sid;
44 size_t address;
45 int rc;
46 char *ptr;
47
48 rc = str_uint64_t(path, &ptr, 10, false, &sid);
49 if (rc != EOK) {
50 return false;
51 }
52 if ((*ptr == ':') || (*ptr == '.')) {
53 ptr++;
54 } else {
55 return false;
56 }
57 rc = str_size_t(ptr, func_start, 10, false, &address);
58 if (rc != EOK) {
59 return false;
60 }
61 rc = usb_ddf_get_hc_handle_by_sid(sid, out_hc_handle);
62 if (rc != EOK) {
63 return false;
64 }
65 if (out_device_address != NULL) {
66 *out_device_address = (usb_address_t) address;
67 }
68 return true;
69}
70
71static int get_device_handle_by_address(devman_handle_t hc_handle, int addr,
72 devman_handle_t *dev_handle)
73{
74 usb_hc_connection_t conn;
75 usb_hc_connection_initialize(&conn, hc_handle);
76
77 const int rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle);
78
79 return rc;
80}
81
82/** Resolve handle and address of USB device from its path.
83 *
84 * This is a wrapper working on best effort principle.
85 * If the resolving fails, if will not give much details about what
86 * is wrong.
87 * Typically, error from this function would be reported to the user
88 * as "bad device specification" or "device does not exist".
89 *
90 * The path can be specified in following format:
91 * - devman path (e.g. /hw/pci0/.../usb01_a5
92 * - bus number and device address (e.g. 5.1)
93 * - bus number, device address and device function (e.g. 2.1/HID0/keyboard)
94 *
95 * @param[in] dev_path Path to the device.
96 * @param[out] out_hc_handle Where to store handle of a parent host controller.
97 * @param[out] out_dev_addr Where to store device (USB) address.
98 * @param[out] out_dev_handle Where to store device handle.
99 * @return Error code.
100 */
101int usb_resolve_device_handle(const char *dev_path, devman_handle_t *dev_handle)
102{
103 if (dev_path == NULL || dev_handle == NULL) {
104 return EBADMEM;
105 }
106
107 devman_handle_t hc;
108 usb_address_t addr = -1;
109 int rc;
110 char *func_start = NULL;
111 char *path = NULL;
112
113 /* First try the BUS.ADDR format. */
114 if (try_parse_bus_and_address(dev_path, &func_start, &hc, &addr)) {
115 /*
116 * Now get the handle of the device. We will need that
117 * in both cases. If there is only BUS.ADDR, it will
118 * be the handle to be returned to the caller, otherwise
119 * we will need it to resolve the path to which the
120 * suffix would be appended.
121 */
122 /* If there is nothing behind the BUS.ADDR, we will
123 * get the device handle from the host controller.
124 * Otherwise, we will
125 */
126
127 rc = get_device_handle_by_address(hc, addr, dev_handle);
128 if (rc != EOK) {
129 return rc;
130 }
131 if (str_length(func_start) > 0) {
132 char tmp_path[MAX_DEVICE_PATH];
133 rc = devman_fun_get_path(*dev_handle,
134 tmp_path, MAX_DEVICE_PATH);
135 if (rc != EOK) {
136 return rc;
137 }
138 rc = asprintf(&path, "%s%s", tmp_path, func_start);
139 if (rc < 0) {
140 return ENOMEM;
141 }
142 } else {
143 /* Everything is resolved. Get out of here. */
144 return EOK;
145 }
146 } else {
147 path = str_dup(dev_path);
148 if (path == NULL) {
149 return ENOMEM;
150 }
151 }
152
153 /* First try to get the device handle. */
154 rc = devman_fun_get_handle(path, dev_handle, 0);
155 if (rc != EOK) {
156 free(path);
157 /* Invalid path altogether. */
158 return rc;
159 }
160
161 /* Remove suffixes and hope that we will encounter device node. */
162 while (str_length(path) > 0) {
163 /* Get device handle first. */
164 devman_handle_t tmp_handle;
165 rc = devman_fun_get_handle(path, &tmp_handle, 0);
166 if (rc != EOK) {
167 free(path);
168 return rc;
169 }
170
171 /* Remove the last suffix. */
172 char *slash_pos = str_rchr(path, '/');
173 if (slash_pos != NULL) {
174 *slash_pos = 0;
175 }
176 }
177
178 free(path);
179
180
181 return EOK;
182}
Note: See TracBrowser for help on using the repository browser.