Ignore:
File:
1 edited

Legend:

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

    r58563585 rffa96c2  
    3434 */
    3535
     36#include <sys/types.h>
     37#include <fibril_synch.h>
     38#include <usb/debug.h>
     39#include <usb/dev/hub.h>
    3640#include <usb/dev/pipes.h>
    3741#include <usb/dev/recognise.h>
     42#include <usb/ddfiface.h>
    3843#include <usb/dev/request.h>
    3944#include <usb/classes/classes.h>
    40 
     45#include <stdio.h>
     46#include <errno.h>
    4147#include <assert.h>
    42 #include <errno.h>
    43 #include <stdio.h>
    44 #include <sys/types.h>
     48
     49/** DDF operations of child devices. */
     50static ddf_dev_ops_t child_ops = {
     51        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
     52};
    4553
    4654/** Get integer part from BCD coded number. */
     
    240248                    (int) device_descriptor->vendor_id,
    241249                    (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));
     250        }       
     251
     252        /*
     253         * If the device class points to interface we skip adding
     254         * class directly but we add a multi interface device.
     255         */
     256        if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) {
     257                ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",
     258                    usb_str_class(device_descriptor->device_class));
     259        } else {
     260                ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid");
     261        }
    247262       
    248263        /* As a last resort, try fallback driver. */
     
    287302}
    288303
     304/** Probe for device kind and register it in devman.
     305 *
     306 * @param[in] ctrl_pipe Control pipe to the device.
     307 * @param[in] parent Parent device.
     308 * @param[in] dev_ops Child device ops. Default child_ops will be used if NULL.
     309 * @param[in] dev_data Arbitrary pointer to be stored in the child
     310 *      as @c driver_data.
     311 * @param[out] child_fun Storage where pointer to allocated child function
     312 *      will be written.
     313 * @return Error code.
     314 *
     315 */
     316int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe,
     317    ddf_dev_t *parent, ddf_fun_t *fun, ddf_dev_ops_t *dev_ops)
     318{
     319        if (ctrl_pipe == NULL)
     320                return EINVAL;
     321       
     322        if (!dev_ops && ddf_fun_data_get(fun) != NULL) {
     323                usb_log_warning("Using standard fun ops with arbitrary "
     324                    "driver data. This does not have to work.\n");
     325        }
     326       
     327        /** Index to append after device name for uniqueness. */
     328        static atomic_t device_name_index = {0};
     329        const size_t this_device_name_index =
     330            (size_t) atomic_preinc(&device_name_index);
     331       
     332        int rc;
     333       
     334        /*
     335         * TODO: Once the device driver framework support persistent
     336         * naming etc., something more descriptive could be created.
     337         */
     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);
     341        if (rc < 0) {
     342                goto failure;
     343        }
     344       
     345        rc = ddf_fun_set_name(fun, child_name);
     346        if (rc != EOK)
     347                goto failure;
     348       
     349        if (dev_ops != NULL)
     350                ddf_fun_set_ops(fun, dev_ops);
     351        else
     352                ddf_fun_set_ops(fun, &child_ops);
     353       
     354        /*
     355         * Store the attached device in fun
     356         * driver data if there is no other data
     357         */
     358        if (ddf_fun_data_get(fun) == NULL) {
     359                usb_hub_attached_device_t *new_device = ddf_fun_data_alloc(
     360                    fun, sizeof(usb_hub_attached_device_t));
     361                if (!new_device) {
     362                        rc = ENOMEM;
     363                        goto failure;
     364                }
     365               
     366                new_device->address = ctrl_pipe->wire->address;
     367                new_device->fun = fun;
     368        }
     369       
     370        match_id_list_t match_ids;
     371        init_match_ids(&match_ids);
     372        rc = usb_device_create_match_ids(ctrl_pipe, &match_ids);
     373        if (rc != EOK)
     374                goto failure;
     375       
     376        list_foreach(match_ids.ids, link, match_id_t, match_id) {
     377                rc = ddf_fun_add_match_id(fun, match_id->id, match_id->score);
     378                if (rc != EOK) {
     379                        clean_match_ids(&match_ids);
     380                        goto failure;
     381                }
     382        }
     383       
     384        clean_match_ids(&match_ids);
     385       
     386        rc = ddf_fun_bind(fun);
     387        if (rc != EOK)
     388                goto failure;
     389       
     390        return EOK;
     391       
     392failure:
     393        return rc;
     394}
     395
    289396/**
    290397 * @}
Note: See TracChangeset for help on using the changeset viewer.