00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <inttypes.h>
00036 #include <usb/hc.h>
00037 #include <devman.h>
00038 #include <errno.h>
00039 #include <str.h>
00040 #include <stdio.h>
00041
00042 #define MAX_DEVICE_PATH 1024
00043
00044 static bool try_parse_bus_and_address(const char *path,
00045 char **func_start,
00046 devman_handle_t *out_hc_handle, usb_address_t *out_device_address)
00047 {
00048 size_t class_index;
00049 size_t address;
00050 int rc;
00051 char *ptr;
00052
00053 rc = str_size_t(path, &ptr, 10, false, &class_index);
00054 if (rc != EOK) {
00055 return false;
00056 }
00057 if ((*ptr == ':') || (*ptr == '.')) {
00058 ptr++;
00059 } else {
00060 return false;
00061 }
00062 rc = str_size_t(ptr, func_start, 10, false, &address);
00063 if (rc != EOK) {
00064 return false;
00065 }
00066 rc = usb_ddf_get_hc_handle_by_class(class_index, out_hc_handle);
00067 if (rc != EOK) {
00068 return false;
00069 }
00070 if (out_device_address != NULL) {
00071 *out_device_address = (usb_address_t) address;
00072 }
00073 return true;
00074 }
00075
00076 static int get_device_handle_by_address(devman_handle_t hc_handle, int addr,
00077 devman_handle_t *dev_handle)
00078 {
00079 int rc;
00080 usb_hc_connection_t conn;
00081
00082 usb_hc_connection_initialize(&conn, hc_handle);
00083 rc = usb_hc_connection_open(&conn);
00084 if (rc != EOK) {
00085 return rc;
00086 }
00087
00088 rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle);
00089
00090 usb_hc_connection_close(&conn);
00091
00092 return rc;
00093 }
00094
00114 int usb_resolve_device_handle(const char *dev_path, devman_handle_t *out_hc_handle,
00115 usb_address_t *out_dev_addr, devman_handle_t *out_dev_handle)
00116 {
00117 if (dev_path == NULL) {
00118 return EBADMEM;
00119 }
00120
00121 bool found_hc = false;
00122 bool found_addr = false;
00123 devman_handle_t hc_handle, dev_handle;
00124 usb_address_t dev_addr = -1;
00125 int rc;
00126 bool is_bus_addr;
00127 char *func_start = NULL;
00128 char *path = NULL;
00129
00130
00131 is_bus_addr = try_parse_bus_and_address(dev_path, &func_start,
00132 &hc_handle, &dev_addr);
00133 if (is_bus_addr) {
00134 found_hc = true;
00135 found_addr = true;
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 rc = get_device_handle_by_address(hc_handle, dev_addr,
00148 &dev_handle);
00149 if (rc != EOK) {
00150 return rc;
00151 }
00152 if (str_length(func_start) > 0) {
00153 char tmp_path[MAX_DEVICE_PATH ];
00154 rc = devman_get_device_path(dev_handle,
00155 tmp_path, MAX_DEVICE_PATH);
00156 if (rc != EOK) {
00157 return rc;
00158 }
00159 rc = asprintf(&path, "%s%s", tmp_path, func_start);
00160 if (rc < 0) {
00161 return ENOMEM;
00162 }
00163 } else {
00164
00165 goto copy_out;
00166 }
00167 } else {
00168 path = str_dup(dev_path);
00169 if (path == NULL) {
00170 return ENOMEM;
00171 }
00172 }
00173
00174
00175 rc = devman_device_get_handle(path, &dev_handle, 0);
00176 if (rc != EOK) {
00177 free(path);
00178
00179 return rc;
00180 }
00181
00182
00183 while (str_length(path) > 0) {
00184
00185 devman_handle_t tmp_handle;
00186 rc = devman_device_get_handle(path, &tmp_handle, 0);
00187 if (rc != EOK) {
00188 free(path);
00189 return rc;
00190 }
00191
00192
00193 if (!found_hc) {
00194 rc = usb_hc_find(tmp_handle, &hc_handle);
00195 if (rc == EOK) {
00196 found_hc = true;
00197 }
00198 }
00199
00200
00201 if (!found_addr) {
00202 dev_addr = usb_hc_get_address_by_handle(tmp_handle);
00203 if (dev_addr >= 0) {
00204 found_addr = true;
00205 }
00206 }
00207
00208
00209 if (found_hc && found_addr) {
00210 break;
00211 }
00212
00213
00214 char *slash_pos = str_rchr(path, '/');
00215 if (slash_pos != NULL) {
00216 *slash_pos = 0;
00217 }
00218 }
00219
00220 free(path);
00221
00222 if (!found_addr || !found_hc) {
00223 return ENOENT;
00224 }
00225
00226 copy_out:
00227 if (out_dev_addr != NULL) {
00228 *out_dev_addr = dev_addr;
00229 }
00230 if (out_hc_handle != NULL) {
00231 *out_hc_handle = hc_handle;
00232 }
00233 if (out_dev_handle != NULL) {
00234 *out_dev_handle = dev_handle;
00235 }
00236
00237 return EOK;
00238 }
00239
00240