Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset dbb7e3b in mainline


Ignore:
Timestamp:
2011-12-12T12:17:19Z (10 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
Children:
a56a13c
Parents:
1a38701
Message:

libusb: Move function from resolve.c to dev.c

Drop empty resolve.c

Location:
uspace/lib/usb
Files:
1 deleted
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/Makefile

    r1a38701 rdbb7e3b  
    4141        src/dump.c \
    4242        src/hc.c \
    43         src/resolve.c \
    4443        src/usb.c
    4544
  • uspace/lib/usb/src/dev.c

    r1a38701 rdbb7e3b  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2011 Vojtech Horky
    34 * All rights reserved.
    45 *
     
    2829
    2930#include <usb/dev.h>
     31#include <usb/hc.h>
    3032#include <errno.h>
    3133#include <usb_iface.h>
     34#include <str.h>
     35#include <stdio.h>
     36
     37#define MAX_DEVICE_PATH 1024
    3238
    3339/** Find host controller handle, address and iface number for the device.
     
    106112        return EOK;
    107113}
     114
     115static bool try_parse_bus_and_address(const char *path,
     116    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        char *ptr;
     123
     124        rc = str_uint64(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
     147static 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}
     157
     158/** Resolve handle and address of USB device from its path.
     159 *
     160 * This is a wrapper working on best effort principle.
     161 * If the resolving fails, if will not give much details about what
     162 * is wrong.
     163 * Typically, error from this function would be reported to the user
     164 * as "bad device specification" or "device does not exist".
     165 *
     166 * The path can be specified in following format:
     167 *  - devman path (e.g. /hw/pci0/.../usb01_a5
     168 *  - bus number and device address (e.g. 5.1)
     169 *  - bus number, device address and device function (e.g. 2.1/HID0/keyboard)
     170 *
     171 * @param[in] dev_path Path to the device.
     172 * @param[out] out_hc_handle Where to store handle of a parent host controller.
     173 * @param[out] out_dev_addr Where to store device (USB) address.
     174 * @param[out] out_dev_handle Where to store device handle.
     175 * @return Error code.
     176 */
     177int 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)
     179{
     180        if (dev_path == NULL) {
     181                return EBADMEM;
     182        }
     183
     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        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);
     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
     289copy_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;
     301}
Note: See TracChangeset for help on using the changeset viewer.