Ignore:
File:
1 edited

Legend:

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

    r162726b r77ad86c  
    3333 * Functions for recognition of attached devices.
    3434 */
     35
    3536#include <sys/types.h>
    3637#include <fibril_synch.h>
     38#include <usb/debug.h>
     39#include <usb/dev/hub.h>
    3740#include <usb/dev/pipes.h>
    3841#include <usb/dev/recognise.h>
     
    4447#include <assert.h>
    4548
    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 
    5149/** DDF operations of child devices. */
    52 ddf_dev_ops_t child_ops = {
     50static ddf_dev_ops_t child_ops = {
    5351        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
    5452};
     
    6462#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
    6563
    66 /* FIXME: make this dynamic */
    67 #define MATCH_STRING_MAX 256
    68 
    6964/** Add formatted match id.
    7065 *
     
    7570 */
    7671static int usb_add_match_id(match_id_list_t *matches, int score,
    77     const char *format, ...)
     72    const char *match_str)
    7873{
    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();
     74        assert(matches);
     75
     76        match_id_t *match_id = create_match_id();
    9977        if (match_id == NULL) {
    100                 rc = ENOMEM;
    101                 goto failure;
     78                return ENOMEM;
    10279        }
    10380
     
    10784
    10885        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;
    12086}
    12187
     
    12995#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
    13096        do { \
    131                 int __rc = usb_add_match_id((match_ids), (score), \
    132                     format, ##__VA_ARGS__); \
     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                } \
    133102                if (__rc != EOK) { \
     103                        free(str); \
    134104                        return __rc; \
    135105                } \
     
    150120    match_id_list_t *matches)
    151121{
    152         if (desc_interface == NULL) {
    153                 return EINVAL;
    154         }
    155         if (matches == NULL) {
     122        if (desc_interface == NULL || matches == NULL) {
    156123                return EINVAL;
    157124        }
     
    314281    match_id_list_t *matches)
    315282{
     283        assert(ctrl_pipe);
    316284        int rc;
    317285        /*
     
    336304/** Probe for device kind and register it in devman.
    337305 *
    338  * @param[in] address Address of the (unknown) attached device.
    339  * @param[in] hc_handle Handle of the host controller.
     306 * @param[in] ctrl_pipe Control pipe to the device.
    340307 * @param[in] parent Parent device.
    341  * @param[in] dev_ops Child device ops.
     308 * @param[in] dev_ops Child device ops. Default child_ops will be used if NULL.
    342309 * @param[in] dev_data Arbitrary pointer to be stored in the child
    343310 *      as @c driver_data.
     
    345312 *      will be written.
    346313 * @return Error code.
    347  */
    348 int 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)
     314 *
     315 */
     316int 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)
    351319{
    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 
     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       
    359333        ddf_fun_t *child = NULL;
    360         char *child_name = NULL;
    361334        int rc;
    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 
     335       
    380336        /*
    381337         * TODO: Once the device driver framework support persistent
    382338         * naming etc., something more descriptive could be created.
    383339         */
    384         rc = asprintf(&child_name, "usb%02zu_a%d",
    385             this_device_name_index, address);
     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);
    386343        if (rc < 0) {
    387344                goto failure;
    388345        }
    389 
     346       
    390347        child = ddf_fun_create(parent, fun_inner, child_name);
    391348        if (child == NULL) {
     
    393350                goto failure;
    394351        }
    395 
    396         if (dev_ops != NULL) {
     352       
     353        if (dev_ops != NULL)
    397354                child->ops = dev_ops;
    398         } else {
     355        else
    399356                child->ops = &child_ops;
    400         }
    401 
     357       
    402358        child->driver_data = dev_data;
    403 
    404         rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
    405         if (rc != EOK) {
     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)
    406377                goto failure;
    407         }
    408 
     378       
    409379        rc = ddf_fun_bind(child);
    410         if (rc != EOK) {
     380        if (rc != EOK)
    411381                goto failure;
    412         }
    413 
    414         if (child_fun != NULL) {
    415                 *child_fun = child;
    416         }
    417 
     382       
     383        *child_fun = child;
    418384        return EOK;
    419 
     385       
    420386failure:
    421387        if (child != NULL) {
    422                 child->name = NULL;
     388                /* We know nothing about the data if it came from outside. */
     389                if (dev_data)
     390                        child->driver_data = NULL;
     391               
    423392                /* This takes care of match_id deallocation as well. */
    424393                ddf_fun_destroy(child);
    425394        }
    426         if (child_name != NULL) {
    427                 free(child_name);
    428         }
    429 
     395       
    430396        return rc;
    431397}
    432398
    433 
    434399/**
    435400 * @}
Note: See TracChangeset for help on using the changeset viewer.