Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/src/dev.c

    rf9b2cb4c rb7fd2a0  
    2929
    3030#include <usb/dev.h>
    31 #include <usb/hc.h>
    3231#include <errno.h>
    3332#include <usb_iface.h>
    3433#include <str.h>
    3534#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 }
    15635
    15736/** Resolve handle and address of USB device from its path.
     
    17453 * @return Error code.
    17554 */
    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)
     55errno_t usb_resolve_device_handle(const char *dev_path, devman_handle_t *dev_handle)
    17856{
    179         if (dev_path == NULL) {
     57        if (dev_path == NULL || dev_handle == NULL) {
    18058                return EBADMEM;
    18159        }
    18260
    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;
     61        /* First, try to get the device handle. */
     62        errno_t rc = devman_fun_get_handle(dev_path, dev_handle, 0);
    19163
    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                 }
     64        /* Next, try parsing dev_handle from the provided string */
     65        if (rc != EOK) {
     66                *dev_handle = strtoul(dev_path, NULL, 10);
     67                //FIXME: check errno
     68                rc = EOK;
    23469        }
    235 
    236         /* First try to get the device handle. */
    237         rc = devman_fun_get_handle(path, &dev_handle, 0);
    238         if (rc != EOK) {
    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;
     70        return rc;
    30071}
Note: See TracChangeset for help on using the changeset viewer.