Ignore:
File:
1 edited

Legend:

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

    rc01987c rfeeac0d  
    3434 */
    3535
     36/** XXX Fix this */
     37#define _DDF_DATA_IMPLANT
     38
     39#include <sys/types.h>
     40#include <fibril_synch.h>
     41#include <usb/debug.h>
     42#include <usb/dev/hub.h>
    3643#include <usb/dev/pipes.h>
    3744#include <usb/dev/recognise.h>
     45#include <usb/ddfiface.h>
    3846#include <usb/dev/request.h>
    3947#include <usb/classes/classes.h>
    40 
     48#include <stdio.h>
     49#include <errno.h>
    4150#include <assert.h>
    42 #include <errno.h>
    43 #include <stdio.h>
    44 #include <sys/types.h>
     51
     52/** DDF operations of child devices. */
     53static ddf_dev_ops_t child_ops = {
     54        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
     55};
    4556
    4657/** Get integer part from BCD coded number. */
     
    234245                    (int) device_descriptor->product_id,
    235246                    BCD_ARGS(device_descriptor->device_version));
    236 
     247               
    237248                /* Next, without release number. */
    238249                ADD_MATCHID_OR_RETURN(matches, 90,
     
    240251                    (int) device_descriptor->vendor_id,
    241252                    (int) device_descriptor->product_id);
    242         }
    243 
    244         /* Class match id */
    245         ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",
    246             usb_str_class(device_descriptor->device_class));
    247 
     253        }       
     254
     255        /*
     256         * If the device class points to interface we skip adding
     257         * class directly but we add a multi interface device.
     258         */
     259        if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) {
     260                ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",
     261                    usb_str_class(device_descriptor->device_class));
     262        } else {
     263                ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid");
     264        }
     265       
    248266        /* As a last resort, try fallback driver. */
    249267        ADD_MATCHID_OR_RETURN(matches, 10, "usb&fallback");
     
    287305}
    288306
     307/** Probe for device kind and register it in devman.
     308 *
     309 * @param[in] ctrl_pipe Control pipe to the device.
     310 * @param[in] parent Parent device.
     311 * @param[in] dev_ops Child device ops. Default child_ops will be used if NULL.
     312 * @param[in] dev_data Arbitrary pointer to be stored in the child
     313 *      as @c driver_data.
     314 * @param[out] child_fun Storage where pointer to allocated child function
     315 *      will be written.
     316 * @return Error code.
     317 *
     318 */
     319int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe,
     320    ddf_dev_t *parent, ddf_dev_ops_t *dev_ops, void *dev_data,
     321    ddf_fun_t **child_fun)
     322{
     323        if (child_fun == NULL || ctrl_pipe == NULL)
     324                return EINVAL;
     325       
     326        if (!dev_ops && dev_data) {
     327                usb_log_warning("Using standard fun ops with arbitrary "
     328                    "driver data. This does not have to work.\n");
     329        }
     330       
     331        /** Index to append after device name for uniqueness. */
     332        static atomic_t device_name_index = {0};
     333        const size_t this_device_name_index =
     334            (size_t) atomic_preinc(&device_name_index);
     335       
     336        ddf_fun_t *child = NULL;
     337        int rc;
     338       
     339        /*
     340         * TODO: Once the device driver framework support persistent
     341         * naming etc., something more descriptive could be created.
     342         */
     343        char child_name[12];  /* The format is: "usbAB_aXYZ", length 11 */
     344        rc = snprintf(child_name, sizeof(child_name),
     345            "usb%02zu_a%d", this_device_name_index, ctrl_pipe->wire->address);
     346        if (rc < 0) {
     347                goto failure;
     348        }
     349       
     350        child = ddf_fun_create(parent, fun_inner, child_name);
     351        if (child == NULL) {
     352                rc = ENOMEM;
     353                goto failure;
     354        }
     355       
     356        if (dev_ops != NULL)
     357                ddf_fun_set_ops(child, dev_ops);
     358        else
     359                ddf_fun_set_ops(child, &child_ops);
     360       
     361        ddf_fun_data_implant(child, dev_data);
     362       
     363        /*
     364         * Store the attached device in fun
     365         * driver data if there is no other data
     366         */
     367        if (!dev_data) {
     368                usb_hub_attached_device_t *new_device = ddf_fun_data_alloc(
     369                    child, sizeof(usb_hub_attached_device_t));
     370                if (!new_device) {
     371                        rc = ENOMEM;
     372                        goto failure;
     373                }
     374               
     375                new_device->address = ctrl_pipe->wire->address;
     376                new_device->fun = child;
     377        }
     378       
     379        match_id_list_t match_ids;
     380        init_match_ids(&match_ids);
     381        rc = usb_device_create_match_ids(ctrl_pipe, &match_ids);
     382        if (rc != EOK)
     383                goto failure;
     384       
     385        list_foreach(match_ids.ids, link, match_id_t, match_id) {
     386                rc = ddf_fun_add_match_id(child, match_id->id, match_id->score);
     387                if (rc != EOK) {
     388                        clean_match_ids(&match_ids);
     389                        goto failure;
     390                }
     391        }
     392       
     393        clean_match_ids(&match_ids);
     394       
     395        rc = ddf_fun_bind(child);
     396        if (rc != EOK)
     397                goto failure;
     398       
     399        *child_fun = child;
     400        return EOK;
     401       
     402failure:
     403        if (child != NULL) {
     404                /* This takes care of match_id deallocation as well. */
     405                ddf_fun_destroy(child);
     406        }
     407       
     408        return rc;
     409}
     410
    289411/**
    290412 * @}
Note: See TracChangeset for help on using the changeset viewer.