Changeset 41e645c in mainline


Ignore:
Timestamp:
2011-02-20T21:43:50Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
070f11e, ace12560
Parents:
423e8c81 (diff), 063ead6f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Add simple USB multi interface device driver

The MID driver serves as a mini bus driver for devices with several
interfaces or for devices with classes defined at interface level.

The keyboard driver is working with this driver with the same problems
as before introduction of USB MID driver.

The merge also includes addition of bulk transfers.

Files:
9 added
27 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    r423e8c81 r41e645c  
    8888./uspace/drv/usbhub/usbhub
    8989./uspace/drv/usbhid/usbhid
     90./uspace/drv/usbmid/usbmid
    9091./uspace/drv/vhc/vhc
    9192./uspace/srv/bd/ata_bd/ata_bd
  • boot/arch/amd64/Makefile.inc

    r423e8c81 r41e645c  
    4747        usbhub \
    4848        usbhid \
     49        usbmid \
    4950        vhc
    5051
  • uspace/Makefile

    r423e8c81 r41e645c  
    121121                drv/usbhid \
    122122                drv/usbhub \
     123                drv/usbmid \
    123124                drv/vhc
    124125endif
     
    136137                drv/usbhid \
    137138                drv/usbhub \
     139                drv/usbmid \
    138140                drv/vhc
    139141endif
  • uspace/doc/doxygroups.h

    r423e8c81 r41e645c  
    220220
    221221        /**
     222         * @defgroup drvusbmid USB multi interface device driver
     223         * @ingroup usb
     224         * @brief USB multi interface device driver
     225         * @details
     226         * This driver serves as a mini hub (or bus) driver for devices
     227         * that have the class defined at interface level (those devices
     228         * usually have several interfaces).
     229         *
     230         * The term multi interface device driver (MID) was borrowed
     231         * Solaris operating system.
     232         */
     233
     234        /**
    222235         * @defgroup drvusbhub USB hub driver
    223236         * @ingroup usb
  • uspace/drv/uhci-hcd/iface.c

    r423e8c81 r41e645c  
    4242#include "uhci.h"
    4343
    44 static int get_address(device_t *dev, devman_handle_t handle,
    45     usb_address_t *address)
    46 {
    47         assert(dev);
    48         uhci_t *hc = dev_to_uhci(dev);
    49         assert(hc);
    50         *address = usb_address_keeping_find(&hc->address_manager, handle);
    51         if (*address <= 0)
    52           return *address;
    53         return EOK;
    54 }
    5544/*----------------------------------------------------------------------------*/
    5645static int reserve_default_address(device_t *dev, usb_speed_t speed)
     
    168157/*----------------------------------------------------------------------------*/
    169158usbhc_iface_t uhci_iface = {
    170         .tell_address = get_address,
    171 
    172159        .reserve_default_address = reserve_default_address,
    173160        .release_default_address = release_default_address,
  • uspace/drv/uhci-hcd/main.c

    r423e8c81 r41e645c  
    3434#include <driver.h>
    3535#include <usb_iface.h>
     36#include <usb/ddfiface.h>
    3637#include <device/hw_res.h>
    3738
     
    4849
    4950static int uhci_add_device(device_t *device);
    50 static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle);
    51 /*----------------------------------------------------------------------------*/
    52 static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
     51
     52static int usb_iface_get_address(device_t *dev, devman_handle_t handle,
     53    usb_address_t *address)
    5354{
    54         /* This shall be called only for the UHCI itself. */
    55         assert(dev->parent == NULL);
     55        assert(dev);
     56        uhci_t *hc = dev_to_uhci(dev);
     57        assert(hc);
    5658
    57         *handle = dev->handle;
     59        usb_address_t addr = usb_address_keeping_find(&hc->address_manager,
     60            handle);
     61        if (addr < 0) {
     62                return addr;
     63        }
     64
     65        if (address != NULL) {
     66                *address = addr;
     67        }
     68
    5869        return EOK;
    5970}
    60 /*----------------------------------------------------------------------------*/
     71
     72
    6173static usb_iface_t hc_usb_iface = {
    62         .get_hc_handle = usb_iface_get_hc_handle
     74        .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
     75        .get_address = usb_iface_get_address
    6376};
    6477/*----------------------------------------------------------------------------*/
  • uspace/drv/uhci-rhd/main.c

    r423e8c81 r41e645c  
    3434#include <driver.h>
    3535#include <usb_iface.h>
     36#include <usb/ddfiface.h>
    3637
    3738#include <errno.h>
     
    5657
    5758static usb_iface_t uhci_rh_usb_iface = {
    58         .get_hc_handle = usb_iface_get_hc_handle
     59        .get_hc_handle = usb_iface_get_hc_handle,
     60        .get_address = usb_iface_get_address_hub_impl
    5961};
    6062
  • uspace/drv/usbhid/main.c

    r423e8c81 r41e645c  
    265265        for (i = 0; i < count; ++i) {
    266266                printf("%d ", key_codes[i]);
     267        }
     268        printf("\n");
     269
     270        for (i = 0; i < count; ++i) {
    267271                // TODO: Key press / release
    268272
    269273                // TODO: NOT WORKING
    270274                unsigned int key = usbkbd_parse_scancode(key_codes[i]);
     275
     276                if (key == 0) {
     277                        continue;
     278                }
    271279                kbd_push_ev(KEY_PRESS, key);
    272280        }
     
    348356                {
    349357                        .pipe = &kbd_dev->poll_pipe,
    350                         .description = &poll_endpoint_description
     358                        .description = &poll_endpoint_description,
     359                        .interface_no =
     360                            usb_device_get_assigned_interface(kbd_dev->device)
    351361                }
    352362        };
  • uspace/drv/usbhub/usbhub.c

    r423e8c81 r41e645c  
    3939
    4040#include <usb_iface.h>
     41#include <usb/ddfiface.h>
    4142#include <usb/usbdrv.h>
    4243#include <usb/descriptor.h>
     
    5051#include "usb/usb.h"
    5152
    52 static int iface_get_hc_handle(device_t *device, devman_handle_t *handle)
    53 {
    54         return usb_hc_find(device->handle, handle);
    55 }
    56 
    57 static usb_iface_t hub_usb_iface = {
    58         .get_hc_handle = iface_get_hc_handle
    59 };
    60 
    6153static device_ops_t hub_device_ops = {
    62         .interfaces[USB_DEV_IFACE] = &hub_usb_iface
     54        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
    6355};
    6456
  • uspace/drv/vhc/conn.h

    r423e8c81 r41e645c  
    3838#include <usb/usb.h>
    3939#include <usbhc_iface.h>
     40#include <usb_iface.h>
    4041#include "vhcd.h"
    4142#include "devices.h"
     
    4344void connection_handler_host(sysarg_t);
    4445
    45 usbhc_iface_t vhc_iface;
     46extern usbhc_iface_t vhc_iface;
     47extern usb_iface_t vhc_usb_iface;
    4648
    4749void address_init(void);
  • uspace/drv/vhc/connhost.c

    r423e8c81 r41e645c  
    3737#include <usb/usb.h>
    3838#include <usb/addrkeep.h>
     39#include <usb/ddfiface.h>
    3940
    4041#include "vhcd.h"
     
    313314static usb_address_keeping_t addresses;
    314315
     316static int tell_address(device_t *dev, devman_handle_t handle,
     317    usb_address_t *address)
     318{
     319        usb_address_t addr = usb_address_keeping_find(&addresses, handle);
     320        if (addr < 0) {
     321                return addr;
     322        }
     323
     324        *address = addr;
     325        return EOK;
     326}
    315327
    316328static int reserve_default_address(device_t *dev, usb_speed_t ignored)
     
    350362}
    351363
    352 static int tell_address(device_t *dev, devman_handle_t handle,
    353     usb_address_t *address)
    354 {
    355         usb_address_t addr = usb_address_keeping_find(&addresses, handle);
    356         if (addr < 0) {
    357                 return addr;
    358         }
    359 
    360         *address = addr;
    361         return EOK;
    362 }
    363 
    364364void address_init(void)
    365365{
     
    368368
    369369usbhc_iface_t vhc_iface = {
    370         .tell_address = tell_address,
    371 
    372370        .reserve_default_address = reserve_default_address,
    373371        .release_default_address = release_default_address,
     
    383381};
    384382
     383usb_iface_t vhc_usb_iface = {
     384        .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
     385        .get_address = tell_address
     386};
     387
     388
    385389/**
    386390 * @}
  • uspace/drv/vhc/hcd.c

    r423e8c81 r41e645c  
    4545
    4646#include <usb/usb.h>
     47#include <usb/ddfiface.h>
    4748#include <usb_iface.h>
    4849#include "vhcd.h"
     
    5253#include "conn.h"
    5354
    54 static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
    55 {
    56         /* This shall be called only for VHC device. */
    57         assert(dev->parent == NULL);
    58 
    59         *handle = dev->handle;
    60         return EOK;
    61 }
    62 
    63 static usb_iface_t hc_usb_iface = {
    64         .get_hc_handle = usb_iface_get_hc_handle
    65 };
    66 
    6755static device_ops_t vhc_ops = {
    6856        .interfaces[USBHC_DEV_IFACE] = &vhc_iface,
    69         .interfaces[USB_DEV_IFACE] = &hc_usb_iface,
     57        .interfaces[USB_DEV_IFACE] = &vhc_usb_iface,
    7058        .close = on_client_close,
    7159        .default_handler = default_connection_handler
  • uspace/lib/drv/generic/remote_usb.c

    r423e8c81 r41e645c  
    4040
    4141
     42static void remote_usb_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
     43static void remote_usb_get_interface(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4244static void remote_usb_get_hc_handle(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4345//static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *);
     
    4547/** Remote USB interface operations. */
    4648static remote_iface_func_ptr_t remote_usb_iface_ops [] = {
     49        remote_usb_get_address,
     50        remote_usb_get_interface,
    4751        remote_usb_get_hc_handle
    4852};
     
    5660};
    5761
     62
     63void remote_usb_get_address(device_t *device, void *iface,
     64    ipc_callid_t callid, ipc_call_t *call)
     65{
     66        usb_iface_t *usb_iface = (usb_iface_t *) iface;
     67
     68        if (usb_iface->get_address == NULL) {
     69                async_answer_0(callid, ENOTSUP);
     70                return;
     71        }
     72
     73        devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
     74
     75        usb_address_t address;
     76        int rc = usb_iface->get_address(device, handle, &address);
     77        if (rc != EOK) {
     78                async_answer_0(callid, rc);
     79        } else {
     80                async_answer_1(callid, EOK, address);
     81        }
     82}
     83
     84void remote_usb_get_interface(device_t *device, void *iface,
     85    ipc_callid_t callid, ipc_call_t *call)
     86{
     87        usb_iface_t *usb_iface = (usb_iface_t *) iface;
     88
     89        if (usb_iface->get_interface == NULL) {
     90                async_answer_0(callid, ENOTSUP);
     91                return;
     92        }
     93
     94        devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
     95
     96        int iface_no;
     97        int rc = usb_iface->get_interface(device, handle, &iface_no);
     98        if (rc != EOK) {
     99                async_answer_0(callid, rc);
     100        } else {
     101                async_answer_1(callid, EOK, iface_no);
     102        }
     103}
    58104
    59105void remote_usb_get_hc_handle(device_t *device, void *iface,
  • uspace/lib/drv/generic/remote_usbhc.c

    r423e8c81 r41e645c  
    4343#define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4
    4444
    45 static void remote_usbhc_get_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4645static void remote_usbhc_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4746static void remote_usbhc_interrupt_in(device_t *, void *, ipc_callid_t, ipc_call_t *);
     47static void remote_usbhc_bulk_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
     48static void remote_usbhc_bulk_in(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4849static void remote_usbhc_control_write(device_t *, void *, ipc_callid_t, ipc_call_t *);
    4950static void remote_usbhc_control_read(device_t *, void *, ipc_callid_t, ipc_call_t *);
     
    5758/** Remote USB host controller interface operations. */
    5859static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
    59         remote_usbhc_get_address,
    60 
    6160        remote_usbhc_reserve_default_address,
    6261        remote_usbhc_release_default_address,
     
    6867        remote_usbhc_interrupt_out,
    6968        remote_usbhc_interrupt_in,
     69
     70        remote_usbhc_bulk_out,
     71        remote_usbhc_bulk_in,
    7072
    7173        remote_usbhc_control_write,
     
    121123}
    122124
    123 void remote_usbhc_get_address(device_t *device, void *iface,
    124     ipc_callid_t callid, ipc_call_t *call)
    125 {
    126         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    127 
    128         if (!usb_iface->tell_address) {
    129                 async_answer_0(callid, ENOTSUP);
    130                 return;
    131         }
    132 
    133         devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
    134 
    135         usb_address_t address;
    136         int rc = usb_iface->tell_address(device, handle, &address);
    137         if (rc != EOK) {
    138                 async_answer_0(callid, rc);
    139         } else {
    140                 async_answer_1(callid, EOK, address);
    141         }
    142 }
    143 
    144125void remote_usbhc_reserve_default_address(device_t *device, void *iface,
    145126    ipc_callid_t callid, ipc_call_t *call)
     
    389370        return remote_usbhc_in_transfer(device, callid, call,
    390371            usb_iface->interrupt_in);
     372}
     373
     374void remote_usbhc_bulk_out(device_t *device, void *iface,
     375    ipc_callid_t callid, ipc_call_t *call)
     376{
     377        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     378        assert(usb_iface != NULL);
     379
     380        return remote_usbhc_out_transfer(device, callid, call,
     381            usb_iface->bulk_out);
     382}
     383
     384void remote_usbhc_bulk_in(device_t *device, void *iface,
     385    ipc_callid_t callid, ipc_call_t *call)
     386{
     387        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     388        assert(usb_iface != NULL);
     389
     390        return remote_usbhc_in_transfer(device, callid, call,
     391            usb_iface->bulk_in);
    391392}
    392393
  • uspace/lib/drv/include/usb_iface.h

    r423e8c81 r41e645c  
    4141#include <usb/usb.h>
    4242typedef enum {
     43        /** Tell USB address assigned to device.
     44         * Parameters:
     45         * - devman handle id
     46         * Answer:
     47         * - EINVAL - unknown handle or handle not managed by this driver
     48         * - ENOTSUP - operation not supported (shall not happen)
     49         * - arbitrary error code if returned by remote implementation
     50         * - EOK - handle found, first parameter contains the USB address
     51         */
     52        IPC_M_USB_GET_ADDRESS,
     53
     54        /** Tell interface number given device can use.
     55         * Parameters
     56         * - devman handle id of the device
     57         * Answer:
     58         * - ENOTSUP - operation not supported (can also mean any interface)
     59         * - EOK - operation okay, first parameter contains interface number
     60         */
     61        IPC_M_USB_GET_INTERFACE,
     62
    4363        /** Tell devman handle of device host controller.
    4464         * Parameters:
     
    5575/** USB device communication interface. */
    5676typedef struct {
     77        int (*get_address)(device_t *, devman_handle_t, usb_address_t *);
     78        int (*get_interface)(device_t *, devman_handle_t, int *);
    5779        int (*get_hc_handle)(device_t *, devman_handle_t *);
    5880} usb_iface_t;
  • uspace/lib/drv/include/usbhc_iface.h

    r423e8c81 r41e645c  
    8585 */
    8686typedef enum {
    87         /** Tell USB address assigned to device.
    88          * Parameters:
    89          * - devman handle id
    90          * Answer:
    91          * - EINVAL - unknown handle or handle not managed by this driver
    92          * - ENOTSUP - operation not supported by HC (shall not happen)
    93          * - arbitrary error code if returned by remote implementation
    94          * - EOK - handle found, first parameter contains the USB address
    95          */
    96         IPC_M_USBHC_GET_ADDRESS,
    97 
    98 
    9987        /** Reserve usage of default address.
    10088         * This call informs the host controller that the caller will be
     
    153141        IPC_M_USBHC_INTERRUPT_IN,
    154142
     143        /** Send bulk data to device.
     144         * See explanation at usb_iface_funcs_t (OUT transaction).
     145         */
     146        IPC_M_USBHC_BULK_OUT,
     147
     148        /** Get bulk data from device.
     149         * See explanation at usb_iface_funcs_t (IN transaction).
     150         */
     151        IPC_M_USBHC_BULK_IN,
     152
    155153        /** Issue control WRITE transfer.
    156154         * See explanation at usb_iface_funcs_t (OUT transaction) for
     
    196194/** USB host controller communication interface. */
    197195typedef struct {
    198         int (*tell_address)(device_t *, devman_handle_t, usb_address_t *);
    199 
    200196        int (*reserve_default_address)(device_t *, usb_speed_t);
    201197        int (*release_default_address)(device_t *);
     
    207203        usbhc_iface_transfer_in_t interrupt_in;
    208204
     205        usbhc_iface_transfer_out_t bulk_out;
     206        usbhc_iface_transfer_in_t bulk_in;
     207
    209208        int (*control_write)(device_t *, usb_target_t,
    210209            size_t,
  • uspace/lib/usb/Makefile

    r423e8c81 r41e645c  
    3535        src/addrkeep.c \
    3636        src/class.c \
     37        src/ddfiface.c \
    3738        src/debug.c \
    3839        src/dp.c \
  • uspace/lib/usb/include/usb/dp.h

    r423e8c81 r41e645c  
    4545} usb_dp_descriptor_nesting_t;
    4646
     47extern usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
     48
    4749typedef struct {
    4850        usb_dp_descriptor_nesting_t *nesting;
  • uspace/lib/usb/include/usb/pipes.h

    r423e8c81 r41e645c  
    107107        /** Endpoint description. */
    108108        const usb_endpoint_description_t *description;
     109        /** Interface number the endpoint must belong to (-1 for any). */
     110        const int interface_no;
    109111        /** Found descriptor fitting the description. */
    110112        usb_standard_endpoint_descriptor_t *descriptor;
     
    121123int usb_device_connection_initialize(usb_device_connection_t *,
    122124    devman_handle_t, usb_address_t);
     125
     126int usb_device_get_assigned_interface(device_t *);
    123127
    124128int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *,
  • uspace/lib/usb/include/usb/recognise.h

    r423e8c81 r41e645c  
    4141#include <ipc/devman.h>
    4242
     43int usb_device_create_match_ids_from_interface(
     44    const usb_standard_device_descriptor_t *,
     45    const usb_standard_interface_descriptor_t *, match_id_list_t *);
     46
    4347int usb_device_create_match_ids(usb_endpoint_pipe_t *, match_id_list_t *);
    4448
  • uspace/lib/usb/include/usb/usbdrv.h

    r423e8c81 r41e645c  
    103103int usb_drv_create_match_ids_from_device_descriptor(match_id_list_t *,
    104104    const usb_standard_device_descriptor_t *);
    105 int usb_drv_create_match_ids_from_configuration_descriptor(match_id_list_t *,
    106     const void *, size_t);
    107 
    108105
    109106#endif
  • uspace/lib/usb/src/dp.c

    r423e8c81 r41e645c  
    4040#include <bool.h>
    4141#include <usb/dp.h>
     42#include <usb/descriptor.h>
     43
     44#define NESTING(parentname, childname) \
     45        { \
     46                .child = USB_DESCTYPE_##childname, \
     47                .parent = USB_DESCTYPE_##parentname, \
     48        }
     49#define LAST_NESTING { -1, -1 }
     50
     51/** Nesting of standard USB descriptors. */
     52usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
     53        NESTING(CONFIGURATION, INTERFACE),
     54        NESTING(INTERFACE, ENDPOINT),
     55        NESTING(INTERFACE, HUB),
     56        NESTING(INTERFACE, HID),
     57        NESTING(HID, HID_REPORT),
     58        LAST_NESTING
     59};
     60
     61#undef NESTING
     62#undef LAST_NESTING
    4263
    4364/** Tells whether pointer points inside descriptor data.
  • uspace/lib/usb/src/hub.c

    r423e8c81 r41e645c  
    301301}
    302302
    303 
    304303/**
    305304 * @}
  • uspace/lib/usb/src/pipes.c

    r423e8c81 r41e645c  
    3636#include <usb/pipes.h>
    3737#include <usbhc_iface.h>
     38#include <usb_iface.h>
    3839#include <errno.h>
    3940#include <assert.h>
     
    4142/** Tell USB address assigned to given device.
    4243 *
    43  * @param phone Phone to my HC.
     44 * @param phone Phone to parent device.
    4445 * @param dev Device in question.
    4546 * @return USB address or error code.
     
    4849{
    4950        sysarg_t address;
    50         int rc = async_req_2_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
    51             IPC_M_USBHC_GET_ADDRESS,
     51        int rc = async_req_2_1(phone, DEV_IFACE_ID(USB_DEV_IFACE),
     52            IPC_M_USB_GET_ADDRESS,
    5253            dev->handle, &address);
    5354
     
    5758
    5859        return (usb_address_t) address;
     60}
     61
     62/** Tell USB interface assigned to given device.
     63 *
     64 * @param device Device in question.
     65 * @return Interface number (negative code means any).
     66 */
     67int usb_device_get_assigned_interface(device_t *device)
     68{
     69        int parent_phone = devman_parent_device_connect(device->handle,
     70            IPC_FLAG_BLOCKING);
     71        if (parent_phone < 0) {
     72                return -1;
     73        }
     74
     75        sysarg_t iface_no;
     76        int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
     77            IPC_M_USB_GET_INTERFACE,
     78            device->handle, &iface_no);
     79
     80        async_hangup(parent_phone);
     81
     82        if (rc != EOK) {
     83                return -1;
     84        }
     85
     86        return (int) iface_no;
    5987}
    6088
     
    80108        }
    81109
    82         int hc_phone = devman_device_connect(hc_handle, 0);
    83         if (hc_phone < 0) {
    84                 return hc_phone;
    85         }
    86 
    87         my_address = get_my_address(hc_phone, device);
     110        int parent_phone = devman_parent_device_connect(device->handle,
     111            IPC_FLAG_BLOCKING);
     112        if (parent_phone < 0) {
     113                return parent_phone;
     114        }
     115
     116        my_address = get_my_address(parent_phone, device);
    88117        if (my_address < 0) {
    89118                rc = my_address;
     
    95124
    96125leave:
    97         async_hangup(hc_phone);
     126        async_hangup(parent_phone);
    98127        return rc;
    99128}
  • uspace/lib/usb/src/pipesinit.c

    r423e8c81 r41e645c  
    109109 * @param mapping_count Number of endpoint mappings in @p mapping.
    110110 * @param found_endpoint Description of found endpoint.
     111 * @param interface_number Number of currently processed interface.
    111112 * @return Endpoint mapping corresponding to @p found_endpoint.
    112113 * @retval NULL No corresponding endpoint found.
     
    114115static usb_endpoint_mapping_t *find_endpoint_mapping(
    115116    usb_endpoint_mapping_t *mapping, size_t mapping_count,
    116     usb_endpoint_description_t *found_endpoint)
     117    usb_endpoint_description_t *found_endpoint,
     118    int interface_number)
    117119{
    118120        while (mapping_count > 0) {
    119                 if (endpoint_fits_description(mapping->description,
    120                     found_endpoint)) {
     121                bool interface_number_fits = (mapping->interface_no < 0)
     122                    || (mapping->interface_no == interface_number);
     123
     124                bool endpoint_descriptions_fits = endpoint_fits_description(
     125                    mapping->description, found_endpoint);
     126
     127                if (interface_number_fits && endpoint_descriptions_fits) {
    121128                        return mapping;
    122129                }
     
    169176         */
    170177        usb_endpoint_mapping_t *ep_mapping = find_endpoint_mapping(mapping,
    171             mapping_count, &description);
     178            mapping_count, &description, interface->interface_number);
    172179        if (ep_mapping == NULL) {
    173180                return ENOENT;
  • uspace/lib/usb/src/pipesio.c

    r423e8c81 r41e645c  
    7171                        ipc_method = IPC_M_USBHC_INTERRUPT_IN;
    7272                        break;
     73                case USB_TRANSFER_BULK:
     74                        ipc_method = IPC_M_USBHC_BULK_IN;
     75                        break;
    7376                default:
    7477                        return ENOTSUP;
     
    194197                case USB_TRANSFER_INTERRUPT:
    195198                        ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
     199                        break;
     200                case USB_TRANSFER_BULK:
     201                        ipc_method = IPC_M_USBHC_BULK_OUT;
    196202                        break;
    197203                default:
  • uspace/lib/usb/src/recognise.c

    r423e8c81 r41e645c  
    3434 */
    3535#include <sys/types.h>
    36 #include <usb_iface.h>
    3736#include <usb/usbdrv.h>
    3837#include <usb/pipes.h>
    3938#include <usb/recognise.h>
     39#include <usb/ddfiface.h>
    4040#include <usb/request.h>
    4141#include <usb/classes/classes.h>
     
    4646static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
    4747
    48 /** Callback for getting host controller handle.
    49  *
    50  * @param dev Device in question.
    51  * @param[out] handle Devman handle of the host controller.
    52  * @return Error code.
    53  */
    54 static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
    55 {
    56         assert(dev);
    57         assert(dev->parent != NULL);
    58 
    59         device_t *parent = dev->parent;
    60 
    61         if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
    62                 usb_iface_t *usb_iface
    63                     = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
    64                 assert(usb_iface != NULL);
    65                 if (usb_iface->get_hc_handle) {
    66                         int rc = usb_iface->get_hc_handle(parent, handle);
    67                         return rc;
    68                 }
    69         }
    70 
    71         return ENOTSUP;
    72 }
    73 
    74 static usb_iface_t usb_iface = {
    75         .get_hc_handle = usb_iface_get_hc_handle
    76 };
    77 
    7848device_ops_t child_ops = {
    79         .interfaces[USB_DEV_IFACE] = &usb_iface
     49        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
    8050};
    8151
     
    142112}
    143113
     114#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
     115        do { \
     116                int __rc = usb_add_match_id((match_ids), (score), \
     117                    format, ##__VA_ARGS__); \
     118                if (__rc != EOK) { \
     119                        return __rc; \
     120                } \
     121        } while (0)
     122
     123/** Create device match ids based on its interface.
     124 *
     125 * @param[in] descriptor Interface descriptor.
     126 * @param[out] matches Initialized list of match ids.
     127 * @return Error code (the two mentioned are not the only ones).
     128 * @retval EINVAL Invalid input parameters (expects non NULL pointers).
     129 * @retval ENOENT Interface does not specify class.
     130 */
     131int usb_device_create_match_ids_from_interface(
     132    const usb_standard_device_descriptor_t *desc_device,
     133    const usb_standard_interface_descriptor_t *desc_interface,
     134    match_id_list_t *matches)
     135{
     136        if (desc_interface == NULL) {
     137                return EINVAL;
     138        }
     139        if (matches == NULL) {
     140                return EINVAL;
     141        }
     142
     143        if (desc_interface->interface_class == USB_CLASS_USE_INTERFACE) {
     144                return ENOENT;
     145        }
     146
     147        const char *classname = usb_str_class(desc_interface->interface_class);
     148        assert(classname != NULL);
     149
     150#define IFACE_PROTOCOL_FMT "interface&class=%s&subclass=0x%02x&protocol=0x%02x"
     151#define IFACE_PROTOCOL_ARGS classname, desc_interface->interface_subclass, \
     152    desc_interface->interface_protocol
     153
     154#define IFACE_SUBCLASS_FMT "interface&class=%s&subclass=0x%02x"
     155#define IFACE_SUBCLASS_ARGS classname, desc_interface->interface_subclass
     156
     157#define IFACE_CLASS_FMT "interface&class=%s"
     158#define IFACE_CLASS_ARGS classname
     159
     160#define VENDOR_RELEASE_FMT "vendor=0x%04x&product=0x%04x&release=" BCD_FMT
     161#define VENDOR_RELEASE_ARGS desc_device->vendor_id, desc_device->product_id, \
     162    BCD_ARGS(desc_device->device_version)
     163
     164#define VENDOR_PRODUCT_FMT "vendor=0x%04x&product=0x%04x"
     165#define VENDOR_PRODUCT_ARGS desc_device->vendor_id, desc_device->product_id
     166
     167#define VENDOR_ONLY_FMT "vendor=0x%04x"
     168#define VENDOR_ONLY_ARGS desc_device->vendor_id
     169
     170        /*
     171         * If the vendor is specified, create match ids with vendor with
     172         * higher score.
     173         * Then the same ones without the vendor part.
     174         */
     175        if ((desc_device != NULL) && (desc_device->vendor_id != 0)) {
     176                /* First, interface matches with device release number. */
     177                ADD_MATCHID_OR_RETURN(matches, 250,
     178                    "usb&" VENDOR_RELEASE_FMT "&" IFACE_PROTOCOL_FMT,
     179                    VENDOR_RELEASE_ARGS, IFACE_PROTOCOL_ARGS);
     180                ADD_MATCHID_OR_RETURN(matches, 240,
     181                    "usb&" VENDOR_RELEASE_FMT "&" IFACE_SUBCLASS_FMT,
     182                    VENDOR_RELEASE_ARGS, IFACE_SUBCLASS_ARGS);
     183                ADD_MATCHID_OR_RETURN(matches, 230,
     184                    "usb&" VENDOR_RELEASE_FMT "&" IFACE_CLASS_FMT,
     185                    VENDOR_RELEASE_ARGS, IFACE_CLASS_ARGS);
     186
     187                /* Next, interface matches without release number. */
     188                ADD_MATCHID_OR_RETURN(matches, 220,
     189                    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_PROTOCOL_FMT,
     190                    VENDOR_PRODUCT_ARGS, IFACE_PROTOCOL_ARGS);
     191                ADD_MATCHID_OR_RETURN(matches, 210,
     192                    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_SUBCLASS_FMT,
     193                    VENDOR_PRODUCT_ARGS, IFACE_SUBCLASS_ARGS);
     194                ADD_MATCHID_OR_RETURN(matches, 200,
     195                    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_CLASS_FMT,
     196                    VENDOR_PRODUCT_ARGS, IFACE_CLASS_ARGS);
     197
     198                /* Finally, interface matches with only vendor. */
     199                ADD_MATCHID_OR_RETURN(matches, 190,
     200                    "usb&" VENDOR_ONLY_FMT "&" IFACE_PROTOCOL_FMT,
     201                    VENDOR_ONLY_ARGS, IFACE_PROTOCOL_ARGS);
     202                ADD_MATCHID_OR_RETURN(matches, 180,
     203                    "usb&" VENDOR_ONLY_FMT "&" IFACE_SUBCLASS_FMT,
     204                    VENDOR_ONLY_ARGS, IFACE_SUBCLASS_ARGS);
     205                ADD_MATCHID_OR_RETURN(matches, 170,
     206                    "usb&" VENDOR_ONLY_FMT "&" IFACE_CLASS_FMT,
     207                    VENDOR_ONLY_ARGS, IFACE_CLASS_ARGS);
     208        }
     209
     210        /* Now, the same but without any vendor specification. */
     211        ADD_MATCHID_OR_RETURN(matches, 160,
     212            "usb&" IFACE_PROTOCOL_FMT,
     213            IFACE_PROTOCOL_ARGS);
     214        ADD_MATCHID_OR_RETURN(matches, 150,
     215            "usb&" IFACE_SUBCLASS_FMT,
     216            IFACE_SUBCLASS_ARGS);
     217        ADD_MATCHID_OR_RETURN(matches, 140,
     218            "usb&" IFACE_CLASS_FMT,
     219            IFACE_CLASS_ARGS);
     220
     221#undef IFACE_PROTOCOL_FMT
     222#undef IFACE_PROTOCOL_ARGS
     223#undef IFACE_SUBCLASS_FMT
     224#undef IFACE_SUBCLASS_ARGS
     225#undef IFACE_CLASS_FMT
     226#undef IFACE_CLASS_ARGS
     227#undef VENDOR_RELEASE_FMT
     228#undef VENDOR_RELEASE_ARGS
     229#undef VENDOR_PRODUCT_FMT
     230#undef VENDOR_PRODUCT_ARGS
     231#undef VENDOR_ONLY_FMT
     232#undef VENDOR_ONLY_ARGS
     233
     234        return EOK;
     235}
     236
    144237/** Create DDF match ids from USB device descriptor.
    145238 *
     
    152245    const usb_standard_device_descriptor_t *device_descriptor)
    153246{
    154         int rc;
    155        
    156247        /*
    157248         * Unless the vendor id is 0, the pair idVendor-idProduct
     
    160251        if (device_descriptor->vendor_id != 0) {
    161252                /* First, with release number. */
    162                 rc = usb_add_match_id(matches, 100,
     253                ADD_MATCHID_OR_RETURN(matches, 100,
    163254                    "usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT,
    164255                    (int) device_descriptor->vendor_id,
    165256                    (int) device_descriptor->product_id,
    166257                    BCD_ARGS(device_descriptor->device_version));
    167                 if (rc != EOK) {
    168                         return rc;
    169                 }
    170258               
    171259                /* Next, without release number. */
    172                 rc = usb_add_match_id(matches, 90,
     260                ADD_MATCHID_OR_RETURN(matches, 90,
    173261                    "usb&vendor=0x%04x&product=0x%04x",
    174262                    (int) device_descriptor->vendor_id,
    175263                    (int) device_descriptor->product_id);
    176                 if (rc != EOK) {
    177                         return rc;
    178                 }
    179264        }       
    180265
    181266        /*
    182267         * If the device class points to interface we skip adding
    183          * class directly.
     268         * class directly but we add a multi interface device.
    184269         */
    185270        if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) {
    186                 rc = usb_add_match_id(matches, 50, "usb&class=%s",
     271                ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",
    187272                    usb_str_class(device_descriptor->device_class));
    188                 if (rc != EOK) {
    189                         return rc;
    190                 }
     273        } else {
     274                ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid");
    191275        }
    192276       
     
    194278}
    195279
    196 /** Create DDF match ids from USB configuration descriptor.
    197  * The configuration descriptor is expected to be in the complete form,
    198  * i.e. including interface, endpoint etc. descriptors.
    199  *
    200  * @param matches List of match ids to extend.
    201  * @param config_descriptor Configuration descriptor returned by given device.
    202  * @param total_size Size of the @p config_descriptor.
    203  * @return Error code.
    204  */
    205 int usb_drv_create_match_ids_from_configuration_descriptor(
    206     match_id_list_t *matches,
    207     const void *config_descriptor, size_t total_size)
    208 {
    209         /*
    210          * Iterate through config descriptor to find the interface
    211          * descriptors.
    212          */
    213         size_t position = sizeof(usb_standard_configuration_descriptor_t);
    214         while (position + 1 < total_size) {
    215                 uint8_t *current_descriptor
    216                     = ((uint8_t *) config_descriptor) + position;
    217                 uint8_t cur_descr_len = current_descriptor[0];
    218                 uint8_t cur_descr_type = current_descriptor[1];
    219 
    220                 if (cur_descr_len == 0) {
    221                         return ENOENT;
    222                 }
    223                
    224                 position += cur_descr_len;
    225                
    226                 if (cur_descr_type != USB_DESCTYPE_INTERFACE) {
    227                         continue;
    228                 }
    229                
    230                 /*
    231                  * Finally, we found an interface descriptor.
    232                  */
    233                 usb_standard_interface_descriptor_t *interface
    234                     = (usb_standard_interface_descriptor_t *)
    235                     current_descriptor;
    236                
    237                 int rc = usb_add_match_id(matches, 50,
    238                     "usb&interface&class=%s",
    239                     usb_str_class(interface->interface_class));
    240                 if (rc != EOK) {
    241                         return rc;
    242                 }
    243         }
    244        
    245         return EOK;
    246 }
    247 
    248 /** Add match ids based on configuration descriptor.
    249  *
    250  * @param pipe Control pipe to the device.
    251  * @param matches Match ids list to add matches to.
    252  * @param config_count Number of configurations the device has.
    253  * @return Error code.
    254  */
    255 static int usb_add_config_descriptor_match_ids(usb_endpoint_pipe_t *pipe,
    256     match_id_list_t *matches, int config_count)
    257 {
    258         int final_rc = EOK;
    259        
    260         int config_index;
    261         for (config_index = 0; config_index < config_count; config_index++) {
    262                 int rc;
    263                 usb_standard_configuration_descriptor_t config_descriptor;
    264                 rc = usb_request_get_bare_configuration_descriptor(pipe,
    265                     config_index, &config_descriptor);
    266                 if (rc != EOK) {
    267                         final_rc = rc;
    268                         continue;
    269                 }
    270 
    271                 size_t full_config_descriptor_size;
    272                 void *full_config_descriptor
    273                     = malloc(config_descriptor.total_length);
    274                 rc = usb_request_get_full_configuration_descriptor(pipe,
    275                     config_index,
    276                     full_config_descriptor, config_descriptor.total_length,
    277                     &full_config_descriptor_size);
    278                 if (rc != EOK) {
    279                         final_rc = rc;
    280                         continue;
    281                 }
    282                 if (full_config_descriptor_size
    283                     != config_descriptor.total_length) {
    284                         final_rc = ERANGE;
    285                         continue;
    286                 }
    287                
    288                 rc = usb_drv_create_match_ids_from_configuration_descriptor(
    289                     matches,
    290                     full_config_descriptor, full_config_descriptor_size);
    291                 if (rc != EOK) {
    292                         final_rc = rc;
    293                         continue;
    294                 }
    295                
    296         }
    297        
    298         return final_rc;
    299 }
    300280
    301281/** Create match ids describing attached device.
     
    330310
    331311        /*
    332          * Go through all configurations and add matches
    333          * based on interface class.
    334          */
    335         rc = usb_add_config_descriptor_match_ids(ctrl_pipe, matches,
    336             device_descriptor.configuration_count);
    337         if (rc != EOK) {
    338                 return rc;
    339         }
    340 
    341         /*
    342312         * As a fallback, provide the simplest match id possible.
    343313         */
    344         rc = usb_add_match_id(matches, 1, "usb&fallback");
    345         if (rc != EOK) {
    346                 return rc;
    347         }
     314        ADD_MATCHID_OR_RETURN(matches, 1, "usb&fallback");
    348315
    349316        return EOK;
Note: See TracChangeset for help on using the changeset viewer.