Changes in uspace/lib/usb/src/dev.c [b7fd2a0:f9b2cb4c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/dev.c
rb7fd2a0 rf9b2cb4c 29 29 30 30 #include <usb/dev.h> 31 #include <usb/hc.h> 31 32 #include <errno.h> 32 33 #include <usb_iface.h> 33 34 #include <str.h> 34 35 #include <stdio.h> 36 37 #define MAX_DEVICE_PATH 1024 38 39 /** Find host controller handle, address and iface number for the device. 40 * 41 * @param[in] device_handle Device devman handle. 42 * @param[out] hc_handle Where to store handle of host controller 43 * controlling device with @p device_handle handle. 44 * @param[out] address Place to store the device's address 45 * @param[out] iface Place to stoer the assigned USB interface number. 46 * @return Error code. 47 */ 48 int usb_get_info_by_handle(devman_handle_t device_handle, 49 devman_handle_t *hc_handle, usb_address_t *address, int *iface) 50 { 51 async_sess_t *parent_sess = 52 devman_parent_device_connect(device_handle, IPC_FLAG_BLOCKING); 53 if (!parent_sess) 54 return ENOMEM; 55 56 async_exch_t *exch = async_exchange_begin(parent_sess); 57 if (!exch) { 58 async_hangup(parent_sess); 59 return ENOMEM; 60 } 61 62 usb_address_t tmp_address; 63 devman_handle_t tmp_handle; 64 int tmp_iface; 65 66 if (address) { 67 const int ret = usb_get_my_address(exch, &tmp_address); 68 if (ret != EOK) { 69 async_exchange_end(exch); 70 async_hangup(parent_sess); 71 return ret; 72 } 73 } 74 75 if (hc_handle) { 76 const int ret = usb_get_hc_handle(exch, &tmp_handle); 77 if (ret != EOK) { 78 async_exchange_end(exch); 79 async_hangup(parent_sess); 80 return ret; 81 } 82 } 83 84 if (iface) { 85 const int ret = usb_get_my_interface(exch, &tmp_iface); 86 switch (ret) { 87 case ENOTSUP: 88 /* Implementing GET_MY_INTERFACE is voluntary. */ 89 tmp_iface = -1; 90 case EOK: 91 break; 92 default: 93 async_exchange_end(exch); 94 async_hangup(parent_sess); 95 return ret; 96 } 97 } 98 99 if (hc_handle) 100 *hc_handle = tmp_handle; 101 102 if (address) 103 *address = tmp_address; 104 105 if (iface) 106 *iface = tmp_iface; 107 108 async_exchange_end(exch); 109 async_hangup(parent_sess); 110 111 return EOK; 112 } 113 114 static bool try_parse_bus_and_address(const char *path, 115 const char **func_start, 116 devman_handle_t *out_hc_handle, usb_address_t *out_device_address) 117 { 118 uint64_t sid; 119 size_t address; 120 int rc; 121 const char *ptr; 122 123 rc = str_uint64_t(path, &ptr, 10, false, &sid); 124 if (rc != EOK) { 125 return false; 126 } 127 if ((*ptr == ':') || (*ptr == '.')) { 128 ptr++; 129 } else { 130 return false; 131 } 132 rc = str_size_t(ptr, func_start, 10, false, &address); 133 if (rc != EOK) { 134 return false; 135 } 136 rc = usb_ddf_get_hc_handle_by_sid(sid, out_hc_handle); 137 if (rc != EOK) { 138 return false; 139 } 140 if (out_device_address != NULL) { 141 *out_device_address = (usb_address_t) address; 142 } 143 return true; 144 } 145 146 static int get_device_handle_by_address(devman_handle_t hc_handle, int addr, 147 devman_handle_t *dev_handle) 148 { 149 usb_hc_connection_t conn; 150 usb_hc_connection_initialize(&conn, hc_handle); 151 152 const int rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle); 153 154 return rc; 155 } 35 156 36 157 /** Resolve handle and address of USB device from its path. … … 53 174 * @return Error code. 54 175 */ 55 errno_t usb_resolve_device_handle(const char *dev_path, devman_handle_t *dev_handle) 176 int usb_resolve_device_handle(const char *dev_path, devman_handle_t *out_hc_handle, 177 usb_address_t *out_dev_addr, devman_handle_t *out_dev_handle) 56 178 { 57 if (dev_path == NULL || dev_handle == NULL) {179 if (dev_path == NULL) { 58 180 return EBADMEM; 59 181 } 60 182 61 /* First, try to get the device handle. */ 62 errno_t rc = devman_fun_get_handle(dev_path, dev_handle, 0); 63 64 /* Next, try parsing dev_handle from the provided string */ 183 bool found_hc = false; 184 bool found_addr = false; 185 devman_handle_t hc_handle, dev_handle; 186 usb_address_t dev_addr = -1; 187 int rc; 188 bool is_bus_addr; 189 const char *func_start = NULL; 190 char *path = NULL; 191 192 /* First try the BUS.ADDR format. */ 193 is_bus_addr = try_parse_bus_and_address(dev_path, &func_start, 194 &hc_handle, &dev_addr); 195 if (is_bus_addr) { 196 found_hc = true; 197 found_addr = true; 198 /* 199 * Now get the handle of the device. We will need that 200 * in both cases. If there is only BUS.ADDR, it will 201 * be the handle to be returned to the caller, otherwise 202 * we will need it to resolve the path to which the 203 * suffix would be appended. 204 */ 205 /* If there is nothing behind the BUS.ADDR, we will 206 * get the device handle from the host controller. 207 * Otherwise, we will 208 */ 209 rc = get_device_handle_by_address(hc_handle, dev_addr, 210 &dev_handle); 211 if (rc != EOK) { 212 return rc; 213 } 214 if (str_length(func_start) > 0) { 215 char tmp_path[MAX_DEVICE_PATH]; 216 rc = devman_fun_get_path(dev_handle, 217 tmp_path, MAX_DEVICE_PATH); 218 if (rc != EOK) { 219 return rc; 220 } 221 rc = asprintf(&path, "%s%s", tmp_path, func_start); 222 if (rc < 0) { 223 return ENOMEM; 224 } 225 } else { 226 /* Everything is resolved. Get out of here. */ 227 goto copy_out; 228 } 229 } else { 230 path = str_dup(dev_path); 231 if (path == NULL) { 232 return ENOMEM; 233 } 234 } 235 236 /* First try to get the device handle. */ 237 rc = devman_fun_get_handle(path, &dev_handle, 0); 65 238 if (rc != EOK) { 66 *dev_handle = strtoul(dev_path, NULL, 10); 67 //FIXME: check errno 68 rc = EOK; 69 } 70 return rc; 239 free(path); 240 /* Invalid path altogether. */ 241 return rc; 242 } 243 244 /* Remove suffixes and hope that we will encounter device node. */ 245 while (str_length(path) > 0) { 246 /* Get device handle first. */ 247 devman_handle_t tmp_handle; 248 rc = devman_fun_get_handle(path, &tmp_handle, 0); 249 if (rc != EOK) { 250 free(path); 251 return rc; 252 } 253 254 /* Try to find its host controller. */ 255 if (!found_hc) { 256 rc = usb_get_hc_by_handle(tmp_handle, &hc_handle); 257 if (rc == EOK) { 258 found_hc = true; 259 } 260 } 261 262 /* Try to get its address. */ 263 if (!found_addr) { 264 rc = usb_get_address_by_handle(tmp_handle, &dev_addr); 265 if (rc == 0) { 266 found_addr = true; 267 } 268 } 269 270 /* Speed-up. */ 271 if (found_hc && found_addr) { 272 break; 273 } 274 275 /* Remove the last suffix. */ 276 char *slash_pos = str_rchr(path, '/'); 277 if (slash_pos != NULL) { 278 *slash_pos = 0; 279 } 280 } 281 282 free(path); 283 284 if (!found_addr || !found_hc) { 285 return ENOENT; 286 } 287 288 copy_out: 289 if (out_dev_addr != NULL) { 290 *out_dev_addr = dev_addr; 291 } 292 if (out_hc_handle != NULL) { 293 *out_hc_handle = hc_handle; 294 } 295 if (out_dev_handle != NULL) { 296 *out_dev_handle = dev_handle; 297 } 298 299 return EOK; 71 300 }
Note:
See TracChangeset
for help on using the changeset viewer.