Ignore:
File:
1 edited

Legend:

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

    rb49d872 r026271d5  
    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(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 }
    15735
    15836/** Resolve handle and address of USB device from its path.
     
    17553 * @return Error code.
    17654 */
    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)
     55int usb_resolve_device_handle(const char *dev_path, devman_handle_t *dev_handle)
    17956{
    180         if (dev_path == NULL) {
     57        if (dev_path == NULL || dev_handle == NULL) {
    18158                return EBADMEM;
    18259        }
    18360
    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;
     61        /* First, try to get the device handle. */
     62        int rc = devman_fun_get_handle(dev_path, dev_handle, 0);
    19263
    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                 }
     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;
    23569        }
    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;
     70        return rc;
    30171}
Note: See TracChangeset for help on using the changeset viewer.