Ignore:
File:
1 edited

Legend:

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

    r77ad86c r162726b  
    3333 * Functions for recognition of attached devices.
    3434 */
    35 
    3635#include <sys/types.h>
    3736#include <fibril_synch.h>
    38 #include <usb/debug.h>
    39 #include <usb/dev/hub.h>
    4037#include <usb/dev/pipes.h>
    4138#include <usb/dev/recognise.h>
     
    4744#include <assert.h>
    4845
     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
    4951/** DDF operations of child devices. */
    50 static ddf_dev_ops_t child_ops = {
     52ddf_dev_ops_t child_ops = {
    5153        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
    5254};
     
    6264#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
    6365
     66/* FIXME: make this dynamic */
     67#define MATCH_STRING_MAX 256
     68
    6469/** Add formatted match id.
    6570 *
     
    7075 */
    7176static int usb_add_match_id(match_id_list_t *matches, int score,
    72     const char *match_str)
     77    const char *format, ...)
    7378{
    74         assert(matches);
    75 
    76         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();
    7799        if (match_id == NULL) {
    78                 return ENOMEM;
     100                rc = ENOMEM;
     101                goto failure;
    79102        }
    80103
     
    84107
    85108        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;
    86120}
    87121
     
    95129#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
    96130        do { \
    97                 char *str = NULL; \
    98                 int __rc = asprintf(&str, format, ##__VA_ARGS__); \
    99                 if (__rc > 0) { \
    100                         __rc = usb_add_match_id((match_ids), (score), str); \
    101                 } \
     131                int __rc = usb_add_match_id((match_ids), (score), \
     132                    format, ##__VA_ARGS__); \
    102133                if (__rc != EOK) { \
    103                         free(str); \
    104134                        return __rc; \
    105135                } \
     
    120150    match_id_list_t *matches)
    121151{
    122         if (desc_interface == NULL || matches == NULL) {
     152        if (desc_interface == NULL) {
     153                return EINVAL;
     154        }
     155        if (matches == NULL) {
    123156                return EINVAL;
    124157        }
     
    281314    match_id_list_t *matches)
    282315{
    283         assert(ctrl_pipe);
    284316        int rc;
    285317        /*
     
    304336/** Probe for device kind and register it in devman.
    305337 *
    306  * @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.
    307340 * @param[in] parent Parent device.
    308  * @param[in] dev_ops Child device ops. Default child_ops will be used if NULL.
     341 * @param[in] dev_ops Child device ops.
    309342 * @param[in] dev_data Arbitrary pointer to be stored in the child
    310343 *      as @c driver_data.
     
    312345 *      will be written.
    313346 * @return Error code.
    314  *
    315  */
    316 int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe,
    317     ddf_dev_t *parent, ddf_dev_ops_t *dev_ops, void *dev_data,
    318     ddf_fun_t **child_fun)
     347 */
     348int usb_device_register_child_in_devman(usb_address_t address,
     349    devman_handle_t hc_handle, ddf_dev_t *parent,
     350    ddf_dev_ops_t *dev_ops, void *dev_data, ddf_fun_t **child_fun)
    319351{
    320         if (child_fun == NULL || ctrl_pipe == NULL)
    321                 return EINVAL;
    322        
    323         if (!dev_ops && dev_data) {
    324                 usb_log_warning("Using standard fun ops with arbitrary "
    325                     "driver data. This does not have to work.\n");
    326         }
    327        
    328         /** Index to append after device name for uniqueness. */
    329         static atomic_t device_name_index = {0};
    330         const size_t this_device_name_index =
    331             (size_t) atomic_preinc(&device_name_index);
    332        
     352        size_t this_device_name_index;
     353
     354        fibril_mutex_lock(&device_name_index_mutex);
     355        this_device_name_index = device_name_index;
     356        device_name_index++;
     357        fibril_mutex_unlock(&device_name_index_mutex);
     358
    333359        ddf_fun_t *child = NULL;
     360        char *child_name = NULL;
    334361        int rc;
    335        
     362        usb_device_connection_t dev_connection;
     363        usb_pipe_t ctrl_pipe;
     364
     365        rc = usb_device_connection_initialize(&dev_connection, hc_handle, address);
     366        if (rc != EOK) {
     367                goto failure;
     368        }
     369
     370        rc = usb_pipe_initialize_default_control(&ctrl_pipe,
     371            &dev_connection);
     372        if (rc != EOK) {
     373                goto failure;
     374        }
     375        rc = usb_pipe_probe_default_control(&ctrl_pipe);
     376        if (rc != EOK) {
     377                goto failure;
     378        }
     379
    336380        /*
    337381         * TODO: Once the device driver framework support persistent
    338382         * naming etc., something more descriptive could be created.
    339383         */
    340         char child_name[12];  /* The format is: "usbAB_aXYZ", length 11 */
    341         rc = snprintf(child_name, sizeof(child_name),
    342             "usb%02zu_a%d", this_device_name_index, ctrl_pipe->wire->address);
     384        rc = asprintf(&child_name, "usb%02zu_a%d",
     385            this_device_name_index, address);
    343386        if (rc < 0) {
    344387                goto failure;
    345388        }
    346        
     389
    347390        child = ddf_fun_create(parent, fun_inner, child_name);
    348391        if (child == NULL) {
     
    350393                goto failure;
    351394        }
    352        
    353         if (dev_ops != NULL)
     395
     396        if (dev_ops != NULL) {
    354397                child->ops = dev_ops;
    355         else
     398        } else {
    356399                child->ops = &child_ops;
    357        
     400        }
     401
    358402        child->driver_data = dev_data;
    359         /*
    360          * Store the attached device in fun
    361          * driver data if there is no other data
    362          */
    363         if (!dev_data) {
    364                 usb_hub_attached_device_t *new_device = ddf_fun_data_alloc(
    365                     child, sizeof(usb_hub_attached_device_t));
    366                 if (!new_device) {
    367                         rc = ENOMEM;
    368                         goto failure;
    369                 }
    370                
    371                 new_device->address = ctrl_pipe->wire->address;
    372                 new_device->fun = child;
    373         }
    374        
    375         rc = usb_device_create_match_ids(ctrl_pipe, &child->match_ids);
    376         if (rc != EOK)
    377                 goto failure;
    378        
     403
     404        rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
     405        if (rc != EOK) {
     406                goto failure;
     407        }
     408
    379409        rc = ddf_fun_bind(child);
    380         if (rc != EOK)
    381                 goto failure;
    382        
    383         *child_fun = child;
     410        if (rc != EOK) {
     411                goto failure;
     412        }
     413
     414        if (child_fun != NULL) {
     415                *child_fun = child;
     416        }
     417
    384418        return EOK;
    385        
     419
    386420failure:
    387421        if (child != NULL) {
    388                 /* We know nothing about the data if it came from outside. */
    389                 if (dev_data)
    390                         child->driver_data = NULL;
    391                
     422                child->name = NULL;
    392423                /* This takes care of match_id deallocation as well. */
    393424                ddf_fun_destroy(child);
    394425        }
    395        
     426        if (child_name != NULL) {
     427                free(child_name);
     428        }
     429
    396430        return rc;
    397431}
    398432
     433
    399434/**
    400435 * @}
Note: See TracChangeset for help on using the changeset viewer.