Changeset dbb7e3b in mainline
- Timestamp:
- 2011-12-12T12:17:19Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a56a13c
- Parents:
- 1a38701
- Location:
- uspace/lib/usb
- Files:
-
- 1 deleted
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/Makefile
r1a38701 rdbb7e3b 41 41 src/dump.c \ 42 42 src/hc.c \ 43 src/resolve.c \44 43 src/usb.c 45 44 -
uspace/lib/usb/src/dev.c
r1a38701 rdbb7e3b 1 1 /* 2 2 * Copyright (c) 2011 Jan Vesely 3 * Copyright (c) 2011 Vojtech Horky 3 4 * All rights reserved. 4 5 * … … 28 29 29 30 #include <usb/dev.h> 31 #include <usb/hc.h> 30 32 #include <errno.h> 31 33 #include <usb_iface.h> 34 #include <str.h> 35 #include <stdio.h> 36 37 #define MAX_DEVICE_PATH 1024 32 38 33 39 /** Find host controller handle, address and iface number for the device. … … 106 112 return EOK; 107 113 } 114 115 static bool try_parse_bus_and_address(const char *path, 116 char **func_start, 117 devman_handle_t *out_hc_handle, usb_address_t *out_device_address) 118 { 119 uint64_t sid; 120 size_t address; 121 int rc; 122 char *ptr; 123 124 rc = str_uint64(path, &ptr, 10, false, &sid); 125 if (rc != EOK) { 126 return false; 127 } 128 if ((*ptr == ':') || (*ptr == '.')) { 129 ptr++; 130 } else { 131 return false; 132 } 133 rc = str_size_t(ptr, func_start, 10, false, &address); 134 if (rc != EOK) { 135 return false; 136 } 137 rc = usb_ddf_get_hc_handle_by_sid(sid, out_hc_handle); 138 if (rc != EOK) { 139 return false; 140 } 141 if (out_device_address != NULL) { 142 *out_device_address = (usb_address_t) address; 143 } 144 return true; 145 } 146 147 static int get_device_handle_by_address(devman_handle_t hc_handle, int addr, 148 devman_handle_t *dev_handle) 149 { 150 usb_hc_connection_t conn; 151 usb_hc_connection_initialize(&conn, hc_handle); 152 153 const int rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle); 154 155 return rc; 156 } 157 158 /** Resolve handle and address of USB device from its path. 159 * 160 * This is a wrapper working on best effort principle. 161 * If the resolving fails, if will not give much details about what 162 * is wrong. 163 * Typically, error from this function would be reported to the user 164 * as "bad device specification" or "device does not exist". 165 * 166 * The path can be specified in following format: 167 * - devman path (e.g. /hw/pci0/.../usb01_a5 168 * - bus number and device address (e.g. 5.1) 169 * - bus number, device address and device function (e.g. 2.1/HID0/keyboard) 170 * 171 * @param[in] dev_path Path to the device. 172 * @param[out] out_hc_handle Where to store handle of a parent host controller. 173 * @param[out] out_dev_addr Where to store device (USB) address. 174 * @param[out] out_dev_handle Where to store device handle. 175 * @return Error code. 176 */ 177 int usb_resolve_device_handle(const char *dev_path, devman_handle_t *out_hc_handle, 178 usb_address_t *out_dev_addr, devman_handle_t *out_dev_handle) 179 { 180 if (dev_path == NULL) { 181 return EBADMEM; 182 } 183 184 bool found_hc = false; 185 bool found_addr = false; 186 devman_handle_t hc_handle, dev_handle; 187 usb_address_t dev_addr = -1; 188 int rc; 189 bool is_bus_addr; 190 char *func_start = NULL; 191 char *path = NULL; 192 193 /* First try the BUS.ADDR format. */ 194 is_bus_addr = try_parse_bus_and_address(dev_path, &func_start, 195 &hc_handle, &dev_addr); 196 if (is_bus_addr) { 197 found_hc = true; 198 found_addr = true; 199 /* 200 * Now get the handle of the device. We will need that 201 * in both cases. If there is only BUS.ADDR, it will 202 * be the handle to be returned to the caller, otherwise 203 * we will need it to resolve the path to which the 204 * suffix would be appended. 205 */ 206 /* If there is nothing behind the BUS.ADDR, we will 207 * get the device handle from the host controller. 208 * Otherwise, we will 209 */ 210 rc = get_device_handle_by_address(hc_handle, dev_addr, 211 &dev_handle); 212 if (rc != EOK) { 213 return rc; 214 } 215 if (str_length(func_start) > 0) { 216 char tmp_path[MAX_DEVICE_PATH]; 217 rc = devman_fun_get_path(dev_handle, 218 tmp_path, MAX_DEVICE_PATH); 219 if (rc != EOK) { 220 return rc; 221 } 222 rc = asprintf(&path, "%s%s", tmp_path, func_start); 223 if (rc < 0) { 224 return ENOMEM; 225 } 226 } else { 227 /* Everything is resolved. Get out of here. */ 228 goto copy_out; 229 } 230 } else { 231 path = str_dup(dev_path); 232 if (path == NULL) { 233 return ENOMEM; 234 } 235 } 236 237 /* First try to get the device handle. */ 238 rc = devman_fun_get_handle(path, &dev_handle, 0); 239 if (rc != EOK) { 240 free(path); 241 /* Invalid path altogether. */ 242 return rc; 243 } 244 245 /* Remove suffixes and hope that we will encounter device node. */ 246 while (str_length(path) > 0) { 247 /* Get device handle first. */ 248 devman_handle_t tmp_handle; 249 rc = devman_fun_get_handle(path, &tmp_handle, 0); 250 if (rc != EOK) { 251 free(path); 252 return rc; 253 } 254 255 /* Try to find its host controller. */ 256 if (!found_hc) { 257 rc = usb_get_hc_by_handle(tmp_handle, &hc_handle); 258 if (rc == EOK) { 259 found_hc = true; 260 } 261 } 262 263 /* Try to get its address. */ 264 if (!found_addr) { 265 rc = usb_get_address_by_handle(tmp_handle, &dev_addr); 266 if (rc == 0) { 267 found_addr = true; 268 } 269 } 270 271 /* Speed-up. */ 272 if (found_hc && found_addr) { 273 break; 274 } 275 276 /* Remove the last suffix. */ 277 char *slash_pos = str_rchr(path, '/'); 278 if (slash_pos != NULL) { 279 *slash_pos = 0; 280 } 281 } 282 283 free(path); 284 285 if (!found_addr || !found_hc) { 286 return ENOENT; 287 } 288 289 copy_out: 290 if (out_dev_addr != NULL) { 291 *out_dev_addr = dev_addr; 292 } 293 if (out_hc_handle != NULL) { 294 *out_hc_handle = hc_handle; 295 } 296 if (out_dev_handle != NULL) { 297 *out_dev_handle = dev_handle; 298 } 299 300 return EOK; 301 }
Note:
See TracChangeset
for help on using the changeset viewer.