Ignore:
File:
1 edited

Legend:

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

    r160b75e r6e3c005  
    3535#include <sys/types.h>
    3636#include <fibril_synch.h>
     37#include <usb/debug.h>
     38#include <usb/dev/hub.h>
    3739#include <usb/dev/pipes.h>
    3840#include <usb/dev/recognise.h>
     
    4446#include <assert.h>
    4547
    46 /** Index to append after device name for uniqueness. */
    47 static size_t device_name_index = 0;
    48 /** Mutex guard for device_name_index. */
    49 static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
    50 
    5148/** DDF operations of child devices. */
    52 ddf_dev_ops_t child_ops = {
     49static ddf_dev_ops_t child_ops = {
    5350        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
    5451};
     
    6461#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
    6562
    66 /* FIXME: make this dynamic */
    67 #define MATCH_STRING_MAX 256
    68 
    6963/** Add formatted match id.
    7064 *
     
    7569 */
    7670static int usb_add_match_id(match_id_list_t *matches, int score,
    77     const char *format, ...)
     71    const char *match_str)
    7872{
    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();
     73        assert(matches);
     74
     75        match_id_t *match_id = create_match_id();
    9976        if (match_id == NULL) {
    100                 rc = ENOMEM;
    101                 goto failure;
     77                return ENOMEM;
    10278        }
    10379
     
    10783
    10884        return EOK;
    109        
    110 failure:
    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;
    12085}
    12186
     
    12994#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
    13095        do { \
    131                 int __rc = usb_add_match_id((match_ids), (score), \
    132                     format, ##__VA_ARGS__); \
     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                } \
    133101                if (__rc != EOK) { \
     102                        free(str); \
    134103                        return __rc; \
    135104                } \
     
    150119    match_id_list_t *matches)
    151120{
    152         if (desc_interface == NULL) {
    153                 return EINVAL;
    154         }
    155         if (matches == NULL) {
     121        if (desc_interface == NULL || matches == NULL) {
    156122                return EINVAL;
    157123        }
     
    314280    match_id_list_t *matches)
    315281{
     282        assert(ctrl_pipe);
    316283        int rc;
    317284        /*
     
    336303/** Probe for device kind and register it in devman.
    337304 *
    338  * @param[in] address Address of the (unknown) attached device.
    339  * @param[in] hc_handle Handle of the host controller.
     305 * @param[in] ctrl_pipe Control pipe to the device.
    340306 * @param[in] parent Parent device.
    341  * @param[out] child_handle Handle of the child device.
    342  * @param[in] dev_ops Child device ops.
     307 * @param[in] dev_ops Child device ops. Default child_ops will be used if NULL.
    343308 * @param[in] dev_data Arbitrary pointer to be stored in the child
    344309 *      as @c driver_data.
     
    347312 * @return Error code.
    348313 */
    349 int 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)
     314int 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)
    353317{
    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);
     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);
    360330
    361331        ddf_fun_t *child = NULL;
    362         char *child_name = NULL;
    363332        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         }
    381333
    382334        /*
     
    384336         * naming etc., something more descriptive could be created.
    385337         */
    386         rc = asprintf(&child_name, "usb%02zu_a%d",
    387             this_device_name_index, address);
     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);
    388341        if (rc < 0) {
    389342                goto failure;
     
    403356
    404357        child->driver_data = dev_data;
    405 
    406         rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
     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);
    407373        if (rc != EOK) {
    408374                goto failure;
     
    414380        }
    415381
    416         if (child_handle != NULL) {
    417                 *child_handle = child->handle;
    418         }
    419 
    420         if (child_fun != NULL) {
    421                 *child_fun = child;
    422         }
    423 
     382        *child_fun = child;
    424383        return EOK;
    425384
    426385failure:
    427386        if (child != NULL) {
    428                 child->name = NULL;
     387                /* We know nothing about the data if it came from outside. */
     388                if (dev_data) {
     389                        child->driver_data = NULL;
     390                }
    429391                /* This takes care of match_id deallocation as well. */
    430392                ddf_fun_destroy(child);
    431393        }
    432         if (child_name != NULL) {
    433                 free(child_name);
    434         }
    435394
    436395        return rc;
Note: See TracChangeset for help on using the changeset viewer.