Changes in uspace/lib/usb/src/dev.c [026271d5:b49d872] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/dev.c
r026271d5 rb49d872 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(EXCHANGE_ATOMIC, device_handle, 53 IPC_FLAG_BLOCKING); 54 if (!parent_sess) 55 return ENOMEM; 56 57 async_exch_t *exch = async_exchange_begin(parent_sess); 58 if (!exch) { 59 async_hangup(parent_sess); 60 return ENOMEM; 61 } 62 63 usb_address_t tmp_address; 64 devman_handle_t tmp_handle; 65 int tmp_iface; 66 67 if (address) { 68 const int ret = usb_get_my_address(exch, &tmp_address); 69 if (ret != EOK) { 70 async_exchange_end(exch); 71 async_hangup(parent_sess); 72 return ret; 73 } 74 } 75 76 if (hc_handle) { 77 const int ret = usb_get_hc_handle(exch, &tmp_handle); 78 if (ret != EOK) { 79 async_exchange_end(exch); 80 async_hangup(parent_sess); 81 return ret; 82 } 83 } 84 85 if (iface) { 86 const int ret = usb_get_my_interface(exch, &tmp_iface); 87 switch (ret) { 88 case ENOTSUP: 89 /* Implementing GET_MY_INTERFACE is voluntary. */ 90 tmp_iface = -1; 91 case EOK: 92 break; 93 default: 94 async_exchange_end(exch); 95 async_hangup(parent_sess); 96 return ret; 97 } 98 } 99 100 if (hc_handle) 101 *hc_handle = tmp_handle; 102 103 if (address) 104 *address = tmp_address; 105 106 if (iface) 107 *iface = tmp_iface; 108 109 async_exchange_end(exch); 110 async_hangup(parent_sess); 111 112 return EOK; 113 } 114 115 static bool try_parse_bus_and_address(const char *path, 116 const 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 const char *ptr; 123 124 rc = str_uint64_t(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 } 35 157 36 158 /** Resolve handle and address of USB device from its path. … … 53 175 * @return Error code. 54 176 */ 55 int usb_resolve_device_handle(const char *dev_path, devman_handle_t *dev_handle) 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) 56 179 { 57 if (dev_path == NULL || dev_handle == NULL) {180 if (dev_path == NULL) { 58 181 return EBADMEM; 59 182 } 60 183 61 /* First, try to get the device handle. */ 62 int rc = devman_fun_get_handle(dev_path, dev_handle, 0); 63 64 /* Next, try parsing dev_handle from the provided string */ 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 const 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); 65 239 if (rc != EOK) { 66 *dev_handle = strtoul(dev_path, NULL, 10); 67 //FIXME: check errno 68 rc = EOK; 69 } 70 return rc; 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; 71 301 }
Note:
See TracChangeset
for help on using the changeset viewer.