Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbdev/src/recognise.c

    r6e3c005 r160b75e  
    3535#include <sys/types.h>
    3636#include <fibril_synch.h>
    37 #include <usb/debug.h>
    38 #include <usb/dev/hub.h>
    3937#include <usb/dev/pipes.h>
    4038#include <usb/dev/recognise.h>
     
    4644#include <assert.h>
    4745
     46/** Index to append after device name for uniqueness. */
     47static size_t device_name_index = 0;
     48/** Mutex guard for device_name_index. */
     49static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
     50
    4851/** DDF operations of child devices. */
    49 static ddf_dev_ops_t child_ops = {
     52ddf_dev_ops_t child_ops = {
    5053        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
    5154};
     
    6164#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
    6265
     66/* FIXME: make this dynamic */
     67#define MATCH_STRING_MAX 256
     68
    6369/** Add formatted match id.
    6470 *
     
    6975 */
    7076static int usb_add_match_id(match_id_list_t *matches, int score,
    71     const char *match_str)
     77    const char *format, ...)
    7278{
    73         assert(matches);
    74 
    75         match_id_t *match_id = create_match_id();
     79        char *match_str = NULL;
     80        match_id_t *match_id = NULL;
     81        int rc;
     82       
     83        match_str = malloc(MATCH_STRING_MAX + 1);
     84        if (match_str == NULL) {
     85                rc = ENOMEM;
     86                goto failure;
     87        }
     88
     89        /*
     90         * FIXME: replace with dynamic allocation of exact size
     91         */
     92        va_list args;
     93        va_start(args, format   );
     94        vsnprintf(match_str, MATCH_STRING_MAX, format, args);
     95        match_str[MATCH_STRING_MAX] = 0;
     96        va_end(args);
     97
     98        match_id = create_match_id();
    7699        if (match_id == NULL) {
    77                 return ENOMEM;
     100                rc = ENOMEM;
     101                goto failure;
    78102        }
    79103
     
    83107
    84108        return EOK;
     109       
     110failure:
     111        if (match_str != NULL) {
     112                free(match_str);
     113        }
     114        if (match_id != NULL) {
     115                match_id->id = NULL;
     116                delete_match_id(match_id);
     117        }
     118       
     119        return rc;
    85120}
    86121
     
    94129#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
    95130        do { \
    96                 char *str = NULL; \
    97                 int __rc = asprintf(&str, format, ##__VA_ARGS__); \
    98                 if (__rc > 0) { \
    99                         __rc = usb_add_match_id((match_ids), (score), str); \
    100                 } \
     131                int __rc = usb_add_match_id((match_ids), (score), \
     132                    format, ##__VA_ARGS__); \
    101133                if (__rc != EOK) { \
    102                         free(str); \
    103134                        return __rc; \
    104135                } \
     
    119150    match_id_list_t *matches)
    120151{
    121         if (desc_interface == NULL || matches == NULL) {
     152        if (desc_interface == NULL) {
     153                return EINVAL;
     154        }
     155        if (matches == NULL) {
    122156                return EINVAL;
    123157        }
     
    280314    match_id_list_t *matches)
    281315{
    282         assert(ctrl_pipe);
    283316        int rc;
    284317        /*
     
    303336/** Probe for device kind and register it in devman.
    304337 *
    305  * @param[in] ctrl_pipe Control pipe to the device.
     338 * @param[in] address Address of the (unknown) attached device.
     339 * @param[in] hc_handle Handle of the host controller.
    306340 * @param[in] parent Parent device.
    307  * @param[in] dev_ops Child device ops. Default child_ops will be used if NULL.
     341 * @param[out] child_handle Handle of the child device.
     342 * @param[in] dev_ops Child device ops.
    308343 * @param[in] dev_data Arbitrary pointer to be stored in the child
    309344 *      as @c driver_data.
     
    312347 * @return Error code.
    313348 */
    314 int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe,
    315     ddf_dev_t *parent, ddf_dev_ops_t *dev_ops, void *dev_data,
    316     ddf_fun_t **child_fun)
     349int usb_device_register_child_in_devman(usb_address_t address,
     350    devman_handle_t hc_handle,
     351    ddf_dev_t *parent, devman_handle_t *child_handle,
     352    ddf_dev_ops_t *dev_ops, void *dev_data, ddf_fun_t **child_fun)
    317353{
    318         if (child_fun == NULL || ctrl_pipe == NULL)
    319                 return EINVAL;
    320 
    321         if (!dev_ops && dev_data) {
    322                 usb_log_warning("Using standard fun ops with arbitrary "
    323                     "driver data. This does not have to work.\n");
    324         }
    325 
    326         /** Index to append after device name for uniqueness. */
    327         static atomic_t device_name_index = {0};
    328         const size_t this_device_name_index =
    329             (size_t) atomic_preinc(&device_name_index);
     354        size_t this_device_name_index;
     355
     356        fibril_mutex_lock(&device_name_index_mutex);
     357        this_device_name_index = device_name_index;
     358        device_name_index++;
     359        fibril_mutex_unlock(&device_name_index_mutex);
    330360
    331361        ddf_fun_t *child = NULL;
     362        char *child_name = NULL;
    332363        int rc;
     364        usb_device_connection_t dev_connection;
     365        usb_pipe_t ctrl_pipe;
     366
     367        rc = usb_device_connection_initialize(&dev_connection, hc_handle, address);
     368        if (rc != EOK) {
     369                goto failure;
     370        }
     371
     372        rc = usb_pipe_initialize_default_control(&ctrl_pipe,
     373            &dev_connection);
     374        if (rc != EOK) {
     375                goto failure;
     376        }
     377        rc = usb_pipe_probe_default_control(&ctrl_pipe);
     378        if (rc != EOK) {
     379                goto failure;
     380        }
    333381
    334382        /*
     
    336384         * naming etc., something more descriptive could be created.
    337385         */
    338         char child_name[12]; /* The format is: "usbAB_aXYZ", length 11 */
    339         rc = snprintf(child_name, sizeof(child_name),
    340             "usb%02zu_a%d", this_device_name_index, ctrl_pipe->wire->address);
     386        rc = asprintf(&child_name, "usb%02zu_a%d",
     387            this_device_name_index, address);
    341388        if (rc < 0) {
    342389                goto failure;
     
    356403
    357404        child->driver_data = dev_data;
    358         /* Store the attached device in fun driver data if there is no
    359          * other data */
    360         if (!dev_data) {
    361                 usb_hub_attached_device_t *new_device = ddf_fun_data_alloc(
    362                     child, sizeof(usb_hub_attached_device_t));
    363                 if (!new_device) {
    364                         rc = ENOMEM;
    365                         goto failure;
    366                 }
    367                 new_device->address = ctrl_pipe->wire->address;
    368                 new_device->fun = child;
    369         }
    370 
    371 
    372         rc = usb_device_create_match_ids(ctrl_pipe, &child->match_ids);
     405
     406        rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
    373407        if (rc != EOK) {
    374408                goto failure;
     
    380414        }
    381415
    382         *child_fun = child;
     416        if (child_handle != NULL) {
     417                *child_handle = child->handle;
     418        }
     419
     420        if (child_fun != NULL) {
     421                *child_fun = child;
     422        }
     423
    383424        return EOK;
    384425
    385426failure:
    386427        if (child != NULL) {
    387                 /* We know nothing about the data if it came from outside. */
    388                 if (dev_data) {
    389                         child->driver_data = NULL;
    390                 }
     428                child->name = NULL;
    391429                /* This takes care of match_id deallocation as well. */
    392430                ddf_fun_destroy(child);
    393431        }
     432        if (child_name != NULL) {
     433                free(child_name);
     434        }
    394435
    395436        return rc;
Note: See TracChangeset for help on using the changeset viewer.