Changeset 92574f4 in mainline for uspace/lib/usb


Ignore:
Timestamp:
2011-02-24T12:03:27Z (15 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e7b7ebd5
Parents:
4837092 (diff), a80849c (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:

Merged development (changes in DDF, etc.).

Conflicts in uspace/drv/usbkbd/main.c

Location:
uspace/lib/usb
Files:
9 added
10 deleted
18 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/Makefile

    r4837092 r92574f4  
    3535        src/addrkeep.c \
    3636        src/class.c \
     37        src/ddfiface.c \
    3738        src/debug.c \
    3839        src/dp.c \
    39         src/drvpsync.c \
    4040        src/dump.c \
    41         src/hcdhubd.c \
    42         src/hcdrv.c \
    4341        src/hidparser.c \
    44         src/localdrv.c \
     42        src/hub.c \
    4543        src/pipes.c \
     44        src/pipesinit.c \
     45        src/pipesio.c \
    4646        src/recognise.c \
    47         src/remotedrv.c \
    4847        src/request.c \
    4948        src/usb.c \
    50         src/usbdrvreq.c \
    51         src/usbdrv.c \
     49        src/usbdevice.c \
    5250        src/usbmem.c
    5351
  • uspace/lib/usb/include/usb/addrkeep.h

    r4837092 r92574f4  
    3131 */
    3232/** @file
    33  * @brief HC driver.
     33 * USB address keeping for host controller drivers.
    3434 */
    35 #ifndef LIBUSB_HCD_H_
    36 #define LIBUSB_HCD_H_
     35#ifndef LIBUSB_ADDRKEEP_H_
     36#define LIBUSB_ADDRKEEP_H_
    3737
    3838#include <usb/usb.h>
  • uspace/lib/usb/include/usb/classes/hid.h

    r4837092 r92574f4  
    5050        USB_HIDREQ_SET_PROTOCOL = 11
    5151} usb_hid_request_t;
     52
     53/** USB/HID subclass constants. */
     54typedef enum {
     55        USB_HID_SUBCLASS_NONE = 0,
     56        USB_HID_SUBCLASS_BOOT = 1
     57} usb_hid_subclass_t;
    5258
    5359/** USB/HID interface protocols. */
  • uspace/lib/usb/include/usb/classes/hub.h

    r4837092 r92574f4  
    11/*
    2  * Copyright (c) 2010 Vojtech Horky
     2 * Copyright (c) 2010 Matus Dekanek
    33 * All rights reserved.
    44 *
     
    3333 * @brief USB hub related structures.
    3434 */
    35 #ifndef LIBUSB_HUB_H_
    36 #define LIBUSB_HUB_H_
     35#ifndef LIBUSB_CLASS_HUB_H_
     36#define LIBUSB_CLASS_HUB_H_
    3737
    3838#include <sys/types.h>
    39 #include <usb/hcdhubd.h>
    40 
    4139
    4240/** Hub class feature selector.
     
    8078    /**
    8179            D1...D0: Logical Power Switching Mode
    82             00: Ganged power switching (all ports power at
     80            00: Ganged power switching (all ports power at
    8381            once)
    8482            01: Individual port power switching
     
    9189            00: Global Over-current Protection. The hub
    9290            reports over-current as a summation of all
    93             ports current draw, without a breakdown of
     91            ports current draw, without a breakdown of
    9492            individual port over-current status.
    9593            01: Individual Port Over-current Protection. The
  • uspace/lib/usb/include/usb/descriptor.h

    r4837092 r92574f4  
    3636#define LIBUSB_DESCRIPTOR_H_
    3737
    38 #include <ipc/ipc.h>
    3938#include <async.h>
    4039
  • uspace/lib/usb/include/usb/dp.h

    r4837092 r92574f4  
    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

    r4837092 r92574f4  
    3131 */
    3232/** @file
    33  * Communication between device drivers and host controller driver.
     33 * USB pipes representation.
    3434 */
    3535#ifndef LIBUSB_PIPES_H_
     
    3838#include <sys/types.h>
    3939#include <usb/usb.h>
     40#include <usb/usbdevice.h>
     41#include <usb/descriptor.h>
    4042#include <ipc/devman.h>
    41 #include <driver.h>
     43#include <ddf/driver.h>
    4244
    4345/**
     
    7375        usb_direction_t direction;
    7476
     77        /** Maximum packet size for the endpoint. */
     78        size_t max_packet_size;
     79
    7580        /** Phone to the host controller.
    7681         * Negative when no session is active.
     
    8085
    8186
     87/** Description of endpoint characteristics. */
     88typedef struct {
     89        /** Transfer type (e.g. control or interrupt). */
     90        usb_transfer_type_t transfer_type;
     91        /** Transfer direction (to or from a device). */
     92        usb_direction_t direction;
     93        /** Interface class this endpoint belongs to (-1 for any). */
     94        int interface_class;
     95        /** Interface subclass this endpoint belongs to (-1 for any). */
     96        int interface_subclass;
     97        /** Interface protocol this endpoint belongs to (-1 for any). */
     98        int interface_protocol;
     99        /** Extra endpoint flags. */
     100        unsigned int flags;
     101} usb_endpoint_description_t;
     102
     103/** Mapping of endpoint pipes and endpoint descriptions. */
     104typedef struct {
     105        /** Endpoint pipe. */
     106        usb_endpoint_pipe_t *pipe;
     107        /** Endpoint description. */
     108        const usb_endpoint_description_t *description;
     109        /** Interface number the endpoint must belong to (-1 for any). */
     110        const int interface_no;
     111        /** Found descriptor fitting the description. */
     112        usb_standard_endpoint_descriptor_t *descriptor;
     113        /** Interface the endpoint belongs to. */
     114        usb_standard_interface_descriptor_t *interface;
     115        /** Whether the endpoint was actually found. */
     116        bool present;
     117} usb_endpoint_mapping_t;
     118
     119int usb_device_connection_initialize_on_default_address(
     120    usb_device_connection_t *, usb_hc_connection_t *);
    82121int usb_device_connection_initialize_from_device(usb_device_connection_t *,
    83     device_t *);
     122    ddf_dev_t *);
    84123int usb_device_connection_initialize(usb_device_connection_t *,
    85124    devman_handle_t, usb_address_t);
    86125
     126int usb_device_get_assigned_interface(ddf_dev_t *);
     127
    87128int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *,
    88129    usb_device_connection_t *,
    89     usb_endpoint_t, usb_transfer_type_t, usb_direction_t);
     130    usb_endpoint_t, usb_transfer_type_t, size_t, usb_direction_t);
    90131int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *,
    91132    usb_device_connection_t *);
     133int usb_endpoint_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
     134    size_t, uint8_t *, size_t, usb_device_connection_t *);
    92135
    93136
    94137int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *);
    95138int usb_endpoint_pipe_end_session(usb_endpoint_pipe_t *);
     139bool usb_endpoint_pipe_is_session_started(usb_endpoint_pipe_t *);
    96140
    97141int usb_endpoint_pipe_read(usb_endpoint_pipe_t *, void *, size_t, size_t *);
     
    103147    void *, size_t);
    104148
    105 
    106 
    107 int usb_endpoint_pipe_async_read(usb_endpoint_pipe_t *, void *, size_t,
    108     size_t *, usb_handle_t *);
    109 int usb_endpoint_pipe_async_write(usb_endpoint_pipe_t *, void *, size_t,
    110     usb_handle_t *);
    111 
    112 int usb_endpoint_pipe_async_control_read(usb_endpoint_pipe_t *, void *, size_t,
    113     void *, size_t, size_t *, usb_handle_t *);
    114 int usb_endpoint_pipe_async_control_write(usb_endpoint_pipe_t *, void *, size_t,
    115     void *, size_t, usb_handle_t *);
    116 
    117 int usb_endpoint_pipe_wait_for(usb_endpoint_pipe_t *, usb_handle_t);
    118 
    119149#endif
    120150/**
  • uspace/lib/usb/include/usb/request.h

    r4837092 r92574f4  
    3737
    3838#include <sys/types.h>
     39#include <l18n/langs.h>
    3940#include <usb/usb.h>
    4041#include <usb/pipes.h>
    4142#include <usb/descriptor.h>
     43
     44/** Standard device request. */
     45typedef enum {
     46        USB_DEVREQ_GET_STATUS = 0,
     47        USB_DEVREQ_CLEAR_FEATURE = 1,
     48        USB_DEVREQ_SET_FEATURE = 3,
     49        USB_DEVREQ_SET_ADDRESS = 5,
     50        USB_DEVREQ_GET_DESCRIPTOR = 6,
     51        USB_DEVREQ_SET_DESCRIPTOR = 7,
     52        USB_DEVREQ_GET_CONFIGURATION = 8,
     53        USB_DEVREQ_SET_CONFIGURATION = 9,
     54        USB_DEVREQ_GET_INTERFACE = 10,
     55        USB_DEVREQ_SET_INTERFACE = 11,
     56        USB_DEVREQ_SYNCH_FRAME = 12,
     57        USB_DEVREQ_LAST_STD
     58} usb_stddevreq_t;
     59
     60/** Device request setup packet.
     61 * The setup packet describes the request.
     62 */
     63typedef struct {
     64        /** Request type.
     65         * The type combines transfer direction, request type and
     66         * intended recipient.
     67         */
     68        uint8_t request_type;
     69        /** Request identification. */
     70        uint8_t request;
     71        /** Main parameter to the request. */
     72        union {
     73                uint16_t value;
     74                /* FIXME: add #ifdefs according to host endianess */
     75                struct {
     76                        uint8_t value_low;
     77                        uint8_t value_high;
     78                };
     79        };
     80        /** Auxiliary parameter to the request.
     81         * Typically, it is offset to something.
     82         */
     83        uint16_t index;
     84        /** Length of extra data. */
     85        uint16_t length;
     86} __attribute__ ((packed)) usb_device_request_setup_packet_t;
    4287
    4388int usb_control_request_set(usb_endpoint_pipe_t *,
     
    5297int usb_request_get_descriptor(usb_endpoint_pipe_t *, usb_request_type_t,
    5398    uint8_t, uint8_t, uint16_t, void *, size_t, size_t *);
     99int usb_request_get_descriptor_alloc(usb_endpoint_pipe_t *, usb_request_type_t,
     100    uint8_t, uint8_t, uint16_t, void **, size_t *);
    54101int usb_request_get_device_descriptor(usb_endpoint_pipe_t *,
    55102    usb_standard_device_descriptor_t *);
     
    60107int usb_request_set_configuration(usb_endpoint_pipe_t *, uint8_t);
    61108
     109int usb_request_get_supported_languages(usb_endpoint_pipe_t *,
     110    l18_win_locales_t **, size_t *);
     111int usb_request_get_string(usb_endpoint_pipe_t *, size_t, l18_win_locales_t,
     112    char **);
     113
    62114#endif
    63115/**
  • uspace/lib/usb/include/usb/usb.h

    r4837092 r92574f4  
    3838#include <sys/types.h>
    3939#include <byteorder.h>
    40 #include <ipc/ipc.h>
    4140
    4241/** Convert 16bit value from native (host) endianness to USB endianness. */
     
    7069} usb_direction_t;
    7170
     71/** USB speeds. */
     72typedef enum {
     73        /** USB 1.1 low speed (1.5Mbits/s). */
     74        USB_SPEED_LOW,
     75        /** USB 1.1 full speed (12Mbits/s). */
     76        USB_SPEED_FULL,
     77        /** USB 2.0 high speed (480Mbits/s). */
     78        USB_SPEED_HIGH
     79} usb_speed_t;
     80
    7281/** USB request type target. */
    7382typedef enum {
     
    8392        USB_REQUEST_RECIPIENT_ENDPOINT = 2
    8493} usb_request_recipient_t;
    85 
    86 /** USB transaction outcome. */
    87 typedef enum {
    88         USB_OUTCOME_OK,
    89         USB_OUTCOME_CRCERROR,
    90         USB_OUTCOME_BABBLE
    91 } usb_transaction_outcome_t;
    92 
    93 const char * usb_str_transaction_outcome(usb_transaction_outcome_t o);
    9494
    9595/** USB address type.
  • uspace/lib/usb/include/usb/usbmem.h

    r4837092 r92574f4  
    11/*
    2  * Copyright (c) 2010 Matus Dekanek
     2 * Copyright (c) 2011 Matus Dekanek
    33 * All rights reserved.
    44 *
     
    3535 * @{
    3636 */
    37 /** @file definitions of special memory management, used mostly in usb stack
     37/** @file definitions of memory management with address translation, used mostly in usb stack
    3838 *
    3939 * USB HCD needs traslation between physical and virtual addresses. These
     
    5959
    6060extern void * mman_malloc(
    61                 size_t size,
    62                 size_t alignment,
    63                 unsigned long max_physical_address);
     61    size_t size,
     62    size_t alignment,
     63    unsigned long max_physical_address);
    6464
    6565extern void * mman_getVA(void * addr);
  • uspace/lib/usb/src/addrkeep.c

    r4837092 r92574f4  
    3333 * @brief Address keeping.
    3434 */
    35 #include <usb/hcd.h>
     35#include <usb/addrkeep.h>
    3636#include <errno.h>
    3737#include <assert.h>
  • uspace/lib/usb/src/debug.c

    r4837092 r92574f4  
    206206void usb_log_printf(usb_log_level_t level, const char *format, ...)
    207207{
    208         FILE *stream = NULL;
     208        FILE *screen_stream = NULL;
    209209        switch (level) {
    210210                case USB_LOG_LEVEL_FATAL:
    211211                case USB_LOG_LEVEL_ERROR:
    212                         stream = stderr;
     212                        screen_stream = stderr;
    213213                        break;
    214214                default:
    215                         stream = stdout;
     215                        screen_stream = stdout;
    216216                        break;
    217217        }
    218         assert(stream != NULL);
     218        assert(screen_stream != NULL);
    219219
    220220        va_list args;
    221         va_start(args, format);
    222221
    223222        /*
     
    231230
    232231        if (log_stream != NULL) {
     232                va_start(args, format);
     233
    233234                fprintf(log_stream, "[%s]%s: ", log_prefix, level_name);
    234235                vfprintf(log_stream, format, args);
     236                fflush(log_stream);
     237
     238                va_end(args);
    235239        }
    236240
    237241        if (level <= log_level) {
    238                 fprintf(stream, "[%s]%s: ", log_prefix, level_name);
    239                 vfprintf(stream, format, args);
     242                va_start(args, format);
     243
     244                fprintf(screen_stream, "[%s]%s: ", log_prefix, level_name);
     245                vfprintf(screen_stream, format, args);
     246                fflush(screen_stream);
     247
     248                va_end(args);
    240249        }
    241250
    242251        fibril_mutex_unlock(&log_serializer);
    243 
    244         va_end(args);
    245252}
    246253
  • uspace/lib/usb/src/dp.c

    r4837092 r92574f4  
    3737#include <str_error.h>
    3838#include <errno.h>
    39 #include <usb/usbdrv.h>
     39#include <assert.h>
    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/dump.c

    r4837092 r92574f4  
    147147        PRINTLINE("bDeviceProtocol = 0x%02x", d->device_protocol);
    148148        PRINTLINE("bMaxPacketSize0 = %d", d->max_packet_size);
    149         PRINTLINE("idVendor = %d", d->vendor_id);
    150         PRINTLINE("idProduct = %d", d->product_id);
     149        PRINTLINE("idVendor = 0x%04x", d->vendor_id);
     150        PRINTLINE("idProduct = 0x%04x", d->product_id);
    151151        PRINTLINE("bcdDevice = %d", d->device_version);
    152152        PRINTLINE("iManufacturer = %d", d->str_manufacturer);
  • uspace/lib/usb/src/pipes.c

    r4837092 r92574f4  
    3131 */
    3232/** @file
    33  * Communication between device drivers and host controller driver.
    34  *
    35  * Note on synchronousness of the operations: there is ABSOLUTELY NO
    36  * guarantee that a call to particular function will not trigger a fibril
    37  * switch.
    38  * The initialization functions may actually involve contacting some other
    39  * task, starting/ending a session might involve asynchronous IPC and since
    40  * the transfer functions uses IPC, asynchronous nature of them is obvious.
    41  * The pseudo synchronous versions for the transfers internally call the
    42  * asynchronous ones and so fibril switch is possible in them as well.
     33 * USB endpoint pipes miscellaneous functions.
    4334 */
    4435#include <usb/usb.h>
    4536#include <usb/pipes.h>
     37#include <usb/debug.h>
     38#include <usbhc_iface.h>
     39#include <usb_iface.h>
     40#include <devman.h>
    4641#include <errno.h>
    4742#include <assert.h>
    48 #include <usb/usbdrv.h>
    49 
    50 #define _PREPARE_TARGET(varname, pipe) \
    51         usb_target_t varname = { \
    52                 .address = (pipe)->wire->address, \
    53                 .endpoint = (pipe)->endpoint_no \
    54         }
     43
     44/** Tell USB address assigned to given device.
     45 *
     46 * @param phone Phone to parent device.
     47 * @param dev Device in question.
     48 * @return USB address or error code.
     49 */
     50static usb_address_t get_my_address(int phone, ddf_dev_t *dev)
     51{
     52        sysarg_t address;
     53
     54
     55        /*
     56         * We are sending special value as a handle - zero - to get
     57         * handle of the parent function (that handle was used
     58         * when registering our device @p dev.
     59         */
     60        int rc = async_req_2_1(phone, DEV_IFACE_ID(USB_DEV_IFACE),
     61            IPC_M_USB_GET_ADDRESS,
     62            0, &address);
     63
     64        if (rc != EOK) {
     65                return rc;
     66        }
     67
     68        return (usb_address_t) address;
     69}
     70
     71/** Tell USB interface assigned to given device.
     72 *
     73 * @param device Device in question.
     74 * @return Interface number (negative code means any).
     75 */
     76int usb_device_get_assigned_interface(ddf_dev_t *device)
     77{
     78        int parent_phone = devman_parent_device_connect(device->handle,
     79            IPC_FLAG_BLOCKING);
     80        if (parent_phone < 0) {
     81                return -1;
     82        }
     83
     84        sysarg_t iface_no;
     85        int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
     86            IPC_M_USB_GET_INTERFACE,
     87            device->handle, &iface_no);
     88
     89        async_hangup(parent_phone);
     90
     91        if (rc != EOK) {
     92                return -1;
     93        }
     94
     95        return (int) iface_no;
     96}
    5597
    5698/** Initialize connection to USB device.
     
    61103 */
    62104int usb_device_connection_initialize_from_device(
    63     usb_device_connection_t *connection, device_t *device)
     105    usb_device_connection_t *connection, ddf_dev_t *dev)
    64106{
    65107        assert(connection);
    66         assert(device);
     108        assert(dev);
    67109
    68110        int rc;
     
    70112        usb_address_t my_address;
    71113
    72         rc = usb_drv_find_hc(device, &hc_handle);
     114        rc = usb_hc_find(dev->handle, &hc_handle);
    73115        if (rc != EOK) {
    74116                return rc;
    75117        }
    76118
    77         int hc_phone = devman_device_connect(hc_handle, 0);
    78         if (hc_phone < 0) {
    79                 return hc_phone;
    80         }
    81 
    82         my_address = usb_drv_get_my_address(hc_phone, device);
     119        int parent_phone = devman_parent_device_connect(dev->handle,
     120            IPC_FLAG_BLOCKING);
     121        if (parent_phone < 0) {
     122                return parent_phone;
     123        }
     124
     125        my_address = get_my_address(parent_phone, dev);
    83126        if (my_address < 0) {
    84127                rc = my_address;
     
    90133
    91134leave:
    92         ipc_hangup(hc_phone);
     135        async_hangup(parent_phone);
    93136        return rc;
    94137}
     
    117160}
    118161
    119 /** Initialize USB endpoint pipe.
    120  *
    121  * @param pipe Endpoint pipe to be initialized.
    122  * @param connection Connection to the USB device backing this pipe (the wire).
    123  * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
    124  * @param transfer_type Transfer type (e.g. interrupt or bulk).
    125  * @param direction Endpoint direction (in/out).
    126  * @return Error code.
    127  */
    128 int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *pipe,
    129     usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
    130     usb_transfer_type_t transfer_type, usb_direction_t direction)
    131 {
    132         assert(pipe);
    133         assert(connection);
    134 
    135         pipe->wire = connection;
    136         pipe->hc_phone = -1;
    137         pipe->endpoint_no = endpoint_no;
    138         pipe->transfer_type = transfer_type;
    139         pipe->direction = direction;
    140 
    141         return EOK;
    142 }
    143 
    144 
    145 /** Initialize USB endpoint pipe as the default zero control pipe.
    146  *
    147  * @param pipe Endpoint pipe to be initialized.
    148  * @param connection Connection to the USB device backing this pipe (the wire).
    149  * @return Error code.
    150  */
    151 int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *pipe,
    152     usb_device_connection_t *connection)
    153 {
    154         assert(pipe);
    155         assert(connection);
    156 
    157         int rc = usb_endpoint_pipe_initialize(pipe, connection,
    158             0, USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH);
    159 
    160         return rc;
     162/** Initialize connection to USB device on default address.
     163 *
     164 * @param dev_connection Device connection structure to be initialized.
     165 * @param hc_connection Initialized connection to host controller.
     166 * @return Error code.
     167 */
     168int usb_device_connection_initialize_on_default_address(
     169    usb_device_connection_t *dev_connection,
     170    usb_hc_connection_t *hc_connection)
     171{
     172        assert(dev_connection);
     173
     174        if (hc_connection == NULL) {
     175                return EBADMEM;
     176        }
     177
     178        return usb_device_connection_initialize(dev_connection,
     179            hc_connection->hc_handle, (usb_address_t) 0);
    161180}
    162181
     
    181200        assert(pipe);
    182201
    183         if (pipe->hc_phone >= 0) {
     202        if (usb_endpoint_pipe_is_session_started(pipe)) {
    184203                return EBUSY;
    185204        }
     
    207226        assert(pipe);
    208227
    209         if (pipe->hc_phone < 0) {
     228        if (!usb_endpoint_pipe_is_session_started(pipe)) {
    210229                return ENOENT;
    211230        }
    212231
    213         int rc = ipc_hangup(pipe->hc_phone);
     232        int rc = async_hangup(pipe->hc_phone);
    214233        if (rc != EOK) {
    215234                return rc;
     
    221240}
    222241
    223 
    224 /** Request a read (in) transfer on an endpoint pipe.
    225  *
    226  * @param[in] pipe Pipe used for the transfer.
    227  * @param[out] buffer Buffer where to store the data.
    228  * @param[in] size Size of the buffer (in bytes).
    229  * @param[out] size_transfered Number of bytes that were actually transfered.
    230  * @return Error code.
    231  */
    232 int usb_endpoint_pipe_read(usb_endpoint_pipe_t *pipe,
    233     void *buffer, size_t size, size_t *size_transfered)
    234 {
    235         assert(pipe);
    236 
    237         int rc;
    238         usb_handle_t handle;
    239 
    240         rc = usb_endpoint_pipe_async_read(pipe, buffer, size, size_transfered,
    241             &handle);
    242         if (rc != EOK) {
    243                 return rc;
    244         }
    245 
    246         rc = usb_endpoint_pipe_wait_for(pipe, handle);
    247         return rc;
    248 }
    249 
    250 /** Request a write (out) transfer on an endpoint pipe.
    251  *
    252  * @param[in] pipe Pipe used for the transfer.
    253  * @param[in] buffer Buffer with data to transfer.
    254  * @param[in] size Size of the buffer (in bytes).
    255  * @return Error code.
    256  */
    257 int usb_endpoint_pipe_write(usb_endpoint_pipe_t *pipe,
    258     void *buffer, size_t size)
    259 {
    260         assert(pipe);
    261 
    262         int rc;
    263         usb_handle_t handle;
    264 
    265         rc = usb_endpoint_pipe_async_write(pipe, buffer, size, &handle);
    266         if (rc != EOK) {
    267                 return rc;
    268         }
    269 
    270         rc = usb_endpoint_pipe_wait_for(pipe, handle);
    271         return rc;
    272 }
    273 
    274 
    275 /** Request a control read transfer on an endpoint pipe.
    276  *
    277  * This function encapsulates all three stages of a control transfer.
    278  *
    279  * @param[in] pipe Pipe used for the transfer.
    280  * @param[in] setup_buffer Buffer with the setup packet.
    281  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    282  * @param[out] data_buffer Buffer for incoming data.
    283  * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
    284  * @param[out] data_transfered_size Number of bytes that were actually
    285  *                                  transfered during the DATA stage.
    286  * @return Error code.
    287  */
    288 int usb_endpoint_pipe_control_read(usb_endpoint_pipe_t *pipe,
    289     void *setup_buffer, size_t setup_buffer_size,
    290     void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
    291 {
    292         assert(pipe);
    293 
    294         int rc;
    295         usb_handle_t handle;
    296 
    297         rc = usb_endpoint_pipe_async_control_read(pipe,
    298             setup_buffer, setup_buffer_size,
    299             data_buffer, data_buffer_size, data_transfered_size,
    300             &handle);
    301         if (rc != EOK) {
    302                 return rc;
    303         }
    304 
    305         rc = usb_endpoint_pipe_wait_for(pipe, handle);
    306         return rc;
    307 }
    308 
    309 
    310 /** Request a control write transfer on an endpoint pipe.
    311  *
    312  * This function encapsulates all three stages of a control transfer.
    313  *
    314  * @param[in] pipe Pipe used for the transfer.
    315  * @param[in] setup_buffer Buffer with the setup packet.
    316  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    317  * @param[in] data_buffer Buffer with data to be sent.
    318  * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
    319  * @return Error code.
    320  */
    321 int usb_endpoint_pipe_control_write(usb_endpoint_pipe_t *pipe,
    322     void *setup_buffer, size_t setup_buffer_size,
    323     void *data_buffer, size_t data_buffer_size)
    324 {
    325         assert(pipe);
    326 
    327         int rc;
    328         usb_handle_t handle;
    329 
    330         rc = usb_endpoint_pipe_async_control_write(pipe,
    331             setup_buffer, setup_buffer_size,
    332             data_buffer, data_buffer_size,
    333             &handle);
    334         if (rc != EOK) {
    335                 return rc;
    336         }
    337 
    338         rc = usb_endpoint_pipe_wait_for(pipe, handle);
    339         return rc;
    340 }
    341 
    342 
    343 /** Request a read (in) transfer on an endpoint pipe (asynchronous version).
    344  *
    345  * @param[in] pipe Pipe used for the transfer.
    346  * @param[out] buffer Buffer where to store the data.
    347  * @param[in] size Size of the buffer (in bytes).
    348  * @param[out] size_transfered Number of bytes that were actually transfered.
    349  * @param[out] handle Handle of the transfer.
    350  * @return Error code.
    351  */
    352 int usb_endpoint_pipe_async_read(usb_endpoint_pipe_t *pipe,
    353     void *buffer, size_t size, size_t *size_transfered,
    354     usb_handle_t *handle)
    355 {
    356         assert(pipe);
    357 
    358         if (pipe->hc_phone < 0) {
    359                 return EBADF;
    360         }
    361 
    362         if (pipe->direction != USB_DIRECTION_IN) {
    363                 return EBADF;
    364         }
    365 
    366         int rc;
    367         _PREPARE_TARGET(target, pipe);
    368 
    369         switch (pipe->transfer_type) {
    370                 case USB_TRANSFER_INTERRUPT:
    371                         rc = usb_drv_async_interrupt_in(pipe->hc_phone, target,
    372                             buffer, size, size_transfered, handle);
    373                         break;
    374                 case USB_TRANSFER_CONTROL:
    375                         rc = EBADF;
    376                         break;
    377                 default:
    378                         rc = ENOTSUP;
    379                         break;
    380         }
    381 
    382         return rc;
    383 }
    384 
    385 
    386 /** Request a write (out) transfer on an endpoint pipe (asynchronous version).
    387  *
    388  * @param[in] pipe Pipe used for the transfer.
    389  * @param[in] buffer Buffer with data to transfer.
    390  * @param[in] size Size of the buffer (in bytes).
    391  * @param[out] handle Handle of the transfer.
    392  * @return Error code.
    393  */
    394 int usb_endpoint_pipe_async_write(usb_endpoint_pipe_t *pipe,
    395     void *buffer, size_t size,
    396     usb_handle_t *handle)
    397 {
    398         assert(pipe);
    399 
    400         if (pipe->hc_phone < 0) {
    401                 return EBADF;
    402         }
    403 
    404         if (pipe->direction != USB_DIRECTION_OUT) {
    405                 return EBADF;
    406         }
    407 
    408         int rc;
    409         _PREPARE_TARGET(target, pipe);
    410 
    411         switch (pipe->transfer_type) {
    412                 case USB_TRANSFER_INTERRUPT:
    413                         rc = usb_drv_async_interrupt_out(pipe->hc_phone, target,
    414                             buffer, size, handle);
    415                         break;
    416                 case USB_TRANSFER_CONTROL:
    417                         rc = EBADF;
    418                         break;
    419                 default:
    420                         rc = ENOTSUP;
    421                         break;
    422         }
    423 
    424         return rc;
    425 }
    426 
    427 
    428 /** Request a control read transfer on an endpoint pipe (asynchronous version).
    429  *
    430  * This function encapsulates all three stages of a control transfer.
    431  *
    432  * @param[in] pipe Pipe used for the transfer.
    433  * @param[in] setup_buffer Buffer with the setup packet.
    434  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    435  * @param[out] data_buffer Buffer for incoming data.
    436  * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
    437  * @param[out] data_transfered_size Number of bytes that were actually
    438  *                                  transfered during the DATA stage.
    439  * @param[out] handle Handle of the transfer.
    440  * @return Error code.
    441  */
    442 int usb_endpoint_pipe_async_control_read(usb_endpoint_pipe_t *pipe,
    443     void *setup_buffer, size_t setup_buffer_size,
    444     void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size,
    445     usb_handle_t *handle)
    446 {
    447         assert(pipe);
    448 
    449         if (pipe->hc_phone < 0) {
    450                 return EBADF;
    451         }
    452 
    453         if ((pipe->direction != USB_DIRECTION_BOTH)
    454             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
    455                 return EBADF;
    456         }
    457 
    458         int rc;
    459         _PREPARE_TARGET(target, pipe);
    460 
    461         rc = usb_drv_async_control_read(pipe->hc_phone, target,
    462             setup_buffer, setup_buffer_size,
    463             data_buffer, data_buffer_size, data_transfered_size,
    464             handle);
    465 
    466         return rc;
    467 }
    468 
    469 
    470 /** Request a control write transfer on an endpoint pipe (asynchronous version).
    471  *
    472  * This function encapsulates all three stages of a control transfer.
    473  *
    474  * @param[in] pipe Pipe used for the transfer.
    475  * @param[in] setup_buffer Buffer with the setup packet.
    476  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    477  * @param[in] data_buffer Buffer with data to be sent.
    478  * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
    479  * @param[out] handle Handle of the transfer.
    480  * @return Error code.
    481  */
    482 int usb_endpoint_pipe_async_control_write(usb_endpoint_pipe_t *pipe,
    483     void *setup_buffer, size_t setup_buffer_size,
    484     void *data_buffer, size_t data_buffer_size,
    485     usb_handle_t *handle)
    486 {
    487         assert(pipe);
    488 
    489         if (pipe->hc_phone < 0) {
    490                 return EBADF;
    491         }
    492 
    493         if ((pipe->direction != USB_DIRECTION_BOTH)
    494             || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
    495                 return EBADF;
    496         }
    497 
    498         int rc;
    499         _PREPARE_TARGET(target, pipe);
    500 
    501         rc = usb_drv_async_control_write(pipe->hc_phone, target,
    502             setup_buffer, setup_buffer_size,
    503             data_buffer, data_buffer_size,
    504             handle);
    505 
    506         return rc;
    507 }
    508 
    509 /** Wait for transfer completion.
    510  *
    511  * The function blocks the caller fibril until the transfer associated
    512  * with given @p handle is completed.
    513  *
    514  * @param[in] pipe Pipe the transfer executed on.
    515  * @param[in] handle Transfer handle.
    516  * @return Error code.
    517  */
    518 int usb_endpoint_pipe_wait_for(usb_endpoint_pipe_t *pipe, usb_handle_t handle)
    519 {
    520         return usb_drv_async_wait_for(handle);
    521 }
    522 
     242/** Tell whether a session is started (open) on the endpoint pipe.
     243 *
     244 * The expected usage of this function is in assertions for some
     245 * nested functions.
     246 *
     247 * @param pipe Endpoint pipe in question.
     248 * @return Whether @p pipe has opened a session.
     249 */
     250bool usb_endpoint_pipe_is_session_started(usb_endpoint_pipe_t *pipe)
     251{
     252        return (pipe->hc_phone >= 0);
     253}
    523254
    524255/**
  • uspace/lib/usb/src/recognise.c

    r4837092 r92574f4  
    3333 * @brief Functions for recognising kind of attached devices.
    3434 */
    35 #include <usb_iface.h>
    36 #include <usb/usbdrv.h>
     35#include <sys/types.h>
     36#include <fibril_synch.h>
     37#include <usb/pipes.h>
     38#include <usb/recognise.h>
     39#include <usb/ddfiface.h>
     40#include <usb/request.h>
    3741#include <usb/classes/classes.h>
    3842#include <stdio.h>
    3943#include <errno.h>
    40 
    41 /** Callback for getting host controller handle.
    42  *
    43  * @param dev Device in question.
    44  * @param[out] handle Devman handle of the host controller.
    45  * @return Error code.
    46  */
    47 static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
    48 {
    49         assert(dev);
    50         assert(dev->parent != NULL);
    51 
    52         device_t *parent = dev->parent;
    53 
    54         if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
    55                 usb_iface_t *usb_iface
    56                     = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
    57                 assert(usb_iface != NULL);
    58                 if (usb_iface->get_hc_handle) {
    59                         int rc = usb_iface->get_hc_handle(parent, handle);
    60                         return rc;
    61                 }
    62         }
    63 
    64         return ENOTSUP;
    65 }
    66 
    67 static usb_iface_t usb_iface = {
    68         .get_hc_handle = usb_iface_get_hc_handle
    69 };
    70 
    71 static device_ops_t child_ops = {
    72         .interfaces[USB_DEV_IFACE] = &usb_iface
     44#include <assert.h>
     45
     46static size_t device_name_index = 0;
     47static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
     48
     49ddf_dev_ops_t child_ops = {
     50        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
    7351};
    7452
     
    135113}
    136114
     115#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
     116        do { \
     117                int __rc = usb_add_match_id((match_ids), (score), \
     118                    format, ##__VA_ARGS__); \
     119                if (__rc != EOK) { \
     120                        return __rc; \
     121                } \
     122        } while (0)
     123
     124/** Create device match ids based on its interface.
     125 *
     126 * @param[in] descriptor Interface descriptor.
     127 * @param[out] matches Initialized list of match ids.
     128 * @return Error code (the two mentioned are not the only ones).
     129 * @retval EINVAL Invalid input parameters (expects non NULL pointers).
     130 * @retval ENOENT Interface does not specify class.
     131 */
     132int usb_device_create_match_ids_from_interface(
     133    const usb_standard_device_descriptor_t *desc_device,
     134    const usb_standard_interface_descriptor_t *desc_interface,
     135    match_id_list_t *matches)
     136{
     137        if (desc_interface == NULL) {
     138                return EINVAL;
     139        }
     140        if (matches == NULL) {
     141                return EINVAL;
     142        }
     143
     144        if (desc_interface->interface_class == USB_CLASS_USE_INTERFACE) {
     145                return ENOENT;
     146        }
     147
     148        const char *classname = usb_str_class(desc_interface->interface_class);
     149        assert(classname != NULL);
     150
     151#define IFACE_PROTOCOL_FMT "interface&class=%s&subclass=0x%02x&protocol=0x%02x"
     152#define IFACE_PROTOCOL_ARGS classname, desc_interface->interface_subclass, \
     153    desc_interface->interface_protocol
     154
     155#define IFACE_SUBCLASS_FMT "interface&class=%s&subclass=0x%02x"
     156#define IFACE_SUBCLASS_ARGS classname, desc_interface->interface_subclass
     157
     158#define IFACE_CLASS_FMT "interface&class=%s"
     159#define IFACE_CLASS_ARGS classname
     160
     161#define VENDOR_RELEASE_FMT "vendor=0x%04x&product=0x%04x&release=" BCD_FMT
     162#define VENDOR_RELEASE_ARGS desc_device->vendor_id, desc_device->product_id, \
     163    BCD_ARGS(desc_device->device_version)
     164
     165#define VENDOR_PRODUCT_FMT "vendor=0x%04x&product=0x%04x"
     166#define VENDOR_PRODUCT_ARGS desc_device->vendor_id, desc_device->product_id
     167
     168#define VENDOR_ONLY_FMT "vendor=0x%04x"
     169#define VENDOR_ONLY_ARGS desc_device->vendor_id
     170
     171        /*
     172         * If the vendor is specified, create match ids with vendor with
     173         * higher score.
     174         * Then the same ones without the vendor part.
     175         */
     176        if ((desc_device != NULL) && (desc_device->vendor_id != 0)) {
     177                /* First, interface matches with device release number. */
     178                ADD_MATCHID_OR_RETURN(matches, 250,
     179                    "usb&" VENDOR_RELEASE_FMT "&" IFACE_PROTOCOL_FMT,
     180                    VENDOR_RELEASE_ARGS, IFACE_PROTOCOL_ARGS);
     181                ADD_MATCHID_OR_RETURN(matches, 240,
     182                    "usb&" VENDOR_RELEASE_FMT "&" IFACE_SUBCLASS_FMT,
     183                    VENDOR_RELEASE_ARGS, IFACE_SUBCLASS_ARGS);
     184                ADD_MATCHID_OR_RETURN(matches, 230,
     185                    "usb&" VENDOR_RELEASE_FMT "&" IFACE_CLASS_FMT,
     186                    VENDOR_RELEASE_ARGS, IFACE_CLASS_ARGS);
     187
     188                /* Next, interface matches without release number. */
     189                ADD_MATCHID_OR_RETURN(matches, 220,
     190                    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_PROTOCOL_FMT,
     191                    VENDOR_PRODUCT_ARGS, IFACE_PROTOCOL_ARGS);
     192                ADD_MATCHID_OR_RETURN(matches, 210,
     193                    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_SUBCLASS_FMT,
     194                    VENDOR_PRODUCT_ARGS, IFACE_SUBCLASS_ARGS);
     195                ADD_MATCHID_OR_RETURN(matches, 200,
     196                    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_CLASS_FMT,
     197                    VENDOR_PRODUCT_ARGS, IFACE_CLASS_ARGS);
     198
     199                /* Finally, interface matches with only vendor. */
     200                ADD_MATCHID_OR_RETURN(matches, 190,
     201                    "usb&" VENDOR_ONLY_FMT "&" IFACE_PROTOCOL_FMT,
     202                    VENDOR_ONLY_ARGS, IFACE_PROTOCOL_ARGS);
     203                ADD_MATCHID_OR_RETURN(matches, 180,
     204                    "usb&" VENDOR_ONLY_FMT "&" IFACE_SUBCLASS_FMT,
     205                    VENDOR_ONLY_ARGS, IFACE_SUBCLASS_ARGS);
     206                ADD_MATCHID_OR_RETURN(matches, 170,
     207                    "usb&" VENDOR_ONLY_FMT "&" IFACE_CLASS_FMT,
     208                    VENDOR_ONLY_ARGS, IFACE_CLASS_ARGS);
     209        }
     210
     211        /* Now, the same but without any vendor specification. */
     212        ADD_MATCHID_OR_RETURN(matches, 160,
     213            "usb&" IFACE_PROTOCOL_FMT,
     214            IFACE_PROTOCOL_ARGS);
     215        ADD_MATCHID_OR_RETURN(matches, 150,
     216            "usb&" IFACE_SUBCLASS_FMT,
     217            IFACE_SUBCLASS_ARGS);
     218        ADD_MATCHID_OR_RETURN(matches, 140,
     219            "usb&" IFACE_CLASS_FMT,
     220            IFACE_CLASS_ARGS);
     221
     222#undef IFACE_PROTOCOL_FMT
     223#undef IFACE_PROTOCOL_ARGS
     224#undef IFACE_SUBCLASS_FMT
     225#undef IFACE_SUBCLASS_ARGS
     226#undef IFACE_CLASS_FMT
     227#undef IFACE_CLASS_ARGS
     228#undef VENDOR_RELEASE_FMT
     229#undef VENDOR_RELEASE_ARGS
     230#undef VENDOR_PRODUCT_FMT
     231#undef VENDOR_PRODUCT_ARGS
     232#undef VENDOR_ONLY_FMT
     233#undef VENDOR_ONLY_ARGS
     234
     235        return EOK;
     236}
     237
    137238/** Create DDF match ids from USB device descriptor.
    138239 *
     
    141242 * @return Error code.
    142243 */
    143 int usb_drv_create_match_ids_from_device_descriptor(
    144     match_id_list_t *matches,
    145     const usb_standard_device_descriptor_t *device_descriptor)
     244int usb_device_create_match_ids_from_device_descriptor(
     245    const usb_standard_device_descriptor_t *device_descriptor,
     246    match_id_list_t *matches)
    146247{
    147         int rc;
    148        
    149248        /*
    150249         * Unless the vendor id is 0, the pair idVendor-idProduct
     
    153252        if (device_descriptor->vendor_id != 0) {
    154253                /* First, with release number. */
    155                 rc = usb_add_match_id(matches, 100,
    156                     "usb&vendor=%d&product=%d&release=" BCD_FMT,
     254                ADD_MATCHID_OR_RETURN(matches, 100,
     255                    "usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT,
    157256                    (int) device_descriptor->vendor_id,
    158257                    (int) device_descriptor->product_id,
    159258                    BCD_ARGS(device_descriptor->device_version));
    160                 if (rc != EOK) {
    161                         return rc;
    162                 }
    163259               
    164260                /* Next, without release number. */
    165                 rc = usb_add_match_id(matches, 90, "usb&vendor=%d&product=%d",
     261                ADD_MATCHID_OR_RETURN(matches, 90,
     262                    "usb&vendor=0x%04x&product=0x%04x",
    166263                    (int) device_descriptor->vendor_id,
    167264                    (int) device_descriptor->product_id);
    168                 if (rc != EOK) {
    169                         return rc;
    170                 }
    171265        }       
    172266
    173267        /*
    174268         * If the device class points to interface we skip adding
    175          * class directly.
     269         * class directly but we add a multi interface device.
    176270         */
    177271        if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) {
    178                 rc = usb_add_match_id(matches, 50, "usb&class=%s",
     272                ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",
    179273                    usb_str_class(device_descriptor->device_class));
    180                 if (rc != EOK) {
    181                         return rc;
    182                 }
     274        } else {
     275                ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid");
    183276        }
    184277       
     
    186279}
    187280
    188 /** Create DDF match ids from USB configuration descriptor.
    189  * The configuration descriptor is expected to be in the complete form,
    190  * i.e. including interface, endpoint etc. descriptors.
    191  *
    192  * @param matches List of match ids to extend.
    193  * @param config_descriptor Configuration descriptor returned by given device.
    194  * @param total_size Size of the @p config_descriptor.
     281
     282/** Create match ids describing attached device.
     283 *
     284 * @warning The list of match ids @p matches may change even when
     285 * function exits with error.
     286 *
     287 * @param ctrl_pipe Control pipe to given device (session must be already
     288 *      started).
     289 * @param matches Initialized list of match ids.
    195290 * @return Error code.
    196291 */
    197 int usb_drv_create_match_ids_from_configuration_descriptor(
    198     match_id_list_t *matches,
    199     const void *config_descriptor, size_t total_size)
     292int usb_device_create_match_ids(usb_endpoint_pipe_t *ctrl_pipe,
     293    match_id_list_t *matches)
    200294{
    201         /*
    202          * Iterate through config descriptor to find the interface
    203          * descriptors.
    204          */
    205         size_t position = sizeof(usb_standard_configuration_descriptor_t);
    206         while (position + 1 < total_size) {
    207                 uint8_t *current_descriptor
    208                     = ((uint8_t *) config_descriptor) + position;
    209                 uint8_t cur_descr_len = current_descriptor[0];
    210                 uint8_t cur_descr_type = current_descriptor[1];
    211 
    212                 if (cur_descr_len == 0) {
    213                         return ENOENT;
    214                 }
    215                
    216                 position += cur_descr_len;
    217                
    218                 if (cur_descr_type != USB_DESCTYPE_INTERFACE) {
    219                         continue;
    220                 }
    221                
    222                 /*
    223                  * Finally, we found an interface descriptor.
    224                  */
    225                 usb_standard_interface_descriptor_t *interface
    226                     = (usb_standard_interface_descriptor_t *)
    227                     current_descriptor;
    228                
    229                 int rc = usb_add_match_id(matches, 50,
    230                     "usb&interface&class=%s",
    231                     usb_str_class(interface->interface_class));
    232                 if (rc != EOK) {
    233                         return rc;
    234                 }
    235         }
    236        
     295        int rc;
     296        /*
     297         * Retrieve device descriptor and add matches from it.
     298         */
     299        usb_standard_device_descriptor_t device_descriptor;
     300
     301        rc = usb_request_get_device_descriptor(ctrl_pipe, &device_descriptor);
     302        if (rc != EOK) {
     303                return rc;
     304        }
     305
     306        rc = usb_device_create_match_ids_from_device_descriptor(
     307            &device_descriptor, matches);
     308        if (rc != EOK) {
     309                return rc;
     310        }
     311
    237312        return EOK;
    238313}
    239314
    240 /** Add match ids based on configuration descriptor.
    241  *
    242  * @param hc Open phone to host controller.
    243  * @param matches Match ids list to add matches to.
    244  * @param address USB address of the attached device.
    245  * @param config_count Number of configurations the device has.
    246  * @return Error code.
    247  */
    248 static int usb_add_config_descriptor_match_ids(int hc,
    249     match_id_list_t *matches, usb_address_t address,
    250     int config_count)
    251 {
    252         int final_rc = EOK;
    253        
    254         int config_index;
    255         for (config_index = 0; config_index < config_count; config_index++) {
    256                 int rc;
    257                 usb_standard_configuration_descriptor_t config_descriptor;
    258                 rc = usb_drv_req_get_bare_configuration_descriptor(hc,
    259                     address,  config_index, &config_descriptor);
    260                 if (rc != EOK) {
    261                         final_rc = rc;
    262                         continue;
    263                 }
    264 
    265                 size_t full_config_descriptor_size;
    266                 void *full_config_descriptor
    267                     = malloc(config_descriptor.total_length);
    268                 rc = usb_drv_req_get_full_configuration_descriptor(hc,
    269                     address, config_index,
    270                     full_config_descriptor, config_descriptor.total_length,
    271                     &full_config_descriptor_size);
    272                 if (rc != EOK) {
    273                         final_rc = rc;
    274                         continue;
    275                 }
    276                 if (full_config_descriptor_size
    277                     != config_descriptor.total_length) {
    278                         final_rc = ERANGE;
    279                         continue;
    280                 }
    281                
    282                 rc = usb_drv_create_match_ids_from_configuration_descriptor(
    283                     matches,
    284                     full_config_descriptor, full_config_descriptor_size);
    285                 if (rc != EOK) {
    286                         final_rc = rc;
    287                         continue;
    288                 }
    289                
    290         }
    291        
    292         return final_rc;
    293 }
    294 
    295 /** Create match ids describing attached device.
    296  *
    297  * @warning The list of match ids @p matches may change even when
    298  * function exits with error.
    299  *
    300  * @param hc Open phone to host controller.
    301  * @param matches Initialized list of match ids.
    302  * @param address USB address of the attached device.
    303  * @return Error code.
    304  */
    305 int usb_drv_create_device_match_ids(int hc, match_id_list_t *matches,
    306     usb_address_t address)
    307 {
    308         int rc;
    309        
    310         /*
    311          * Retrieve device descriptor and add matches from it.
    312          */
    313         usb_standard_device_descriptor_t device_descriptor;
    314 
    315         rc = usb_drv_req_get_device_descriptor(hc, address,
    316             &device_descriptor);
    317         if (rc != EOK) {
    318                 return rc;
    319         }
    320        
    321         rc = usb_drv_create_match_ids_from_device_descriptor(matches,
    322             &device_descriptor);
    323         if (rc != EOK) {
    324                 return rc;
    325         }
    326        
    327         /*
    328          * Go through all configurations and add matches
    329          * based on interface class.
    330          */
    331         rc = usb_add_config_descriptor_match_ids(hc, matches,
    332             address, device_descriptor.configuration_count);
    333         if (rc != EOK) {
    334                 return rc;
    335         }
    336 
    337         /*
    338          * As a fallback, provide the simplest match id possible.
    339          */
    340         rc = usb_add_match_id(matches, 1, "usb&fallback");
    341         if (rc != EOK) {
    342                 return rc;
    343         }
    344 
    345         return EOK;
    346 }
    347 
    348 
    349315/** Probe for device kind and register it in devman.
    350316 *
    351  * @param[in] hc Open phone to the host controller.
     317 * @param[in] address Address of the (unknown) attached device.
     318 * @param[in] hc_handle Handle of the host controller.
    352319 * @param[in] parent Parent device.
    353  * @param[in] address Address of the (unknown) attached device.
    354320 * @param[out] child_handle Handle of the child device.
    355321 * @return Error code.
    356322 */
    357 int usb_drv_register_child_in_devman(int hc, device_t *parent,
    358     usb_address_t address, devman_handle_t *child_handle)
     323int usb_device_register_child_in_devman(usb_address_t address,
     324    devman_handle_t hc_handle,
     325    ddf_dev_t *parent, devman_handle_t *child_handle,
     326    ddf_dev_ops_t *dev_ops, void *dev_data, ddf_fun_t **child_fun)
    359327{
    360         static size_t device_name_index = 0;
    361 
    362         device_t *child = NULL;
     328        size_t this_device_name_index;
     329
     330        fibril_mutex_lock(&device_name_index_mutex);
     331        this_device_name_index = device_name_index;
     332        device_name_index++;
     333        fibril_mutex_unlock(&device_name_index_mutex);
     334
     335        ddf_fun_t *child = NULL;
    363336        char *child_name = NULL;
    364337        int rc;
    365 
    366         child = create_device();
     338        usb_device_connection_t dev_connection;
     339        usb_endpoint_pipe_t ctrl_pipe;
     340
     341        rc = usb_device_connection_initialize(&dev_connection, hc_handle, address);
     342        if (rc != EOK) {
     343                goto failure;
     344        }
     345
     346        rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe,
     347            &dev_connection);
     348        if (rc != EOK) {
     349                goto failure;
     350        }
     351
     352        /*
     353         * TODO: Once the device driver framework support persistent
     354         * naming etc., something more descriptive could be created.
     355         */
     356        rc = asprintf(&child_name, "usbdev%02zu", this_device_name_index);
     357        if (rc < 0) {
     358                goto failure;
     359        }
     360
     361        child = ddf_fun_create(parent, fun_inner, child_name);
    367362        if (child == NULL) {
    368363                rc = ENOMEM;
     
    370365        }
    371366
    372         /*
    373          * TODO: Once the device driver framework support persistent
    374          * naming etc., something more descriptive could be created.
    375          */
    376         rc = asprintf(&child_name, "usbdev%02zu", device_name_index);
    377         if (rc < 0) {
    378                 goto failure;
    379         }
    380         child->parent = parent;
    381         child->name = child_name;
    382         child->ops = &child_ops;
    383        
    384         rc = usb_drv_create_device_match_ids(hc, &child->match_ids, address);
    385         if (rc != EOK) {
    386                 goto failure;
    387         }
    388 
    389         rc = child_device_register(child, parent);
     367        if (dev_ops != NULL) {
     368                child->ops = dev_ops;
     369        } else {
     370                child->ops = &child_ops;
     371        }
     372
     373        child->driver_data = dev_data;
     374
     375        rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
     376        if (rc != EOK) {
     377                goto failure;
     378        }
     379
     380        rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
     381        if (rc != EOK) {
     382                goto failure;
     383        }
     384
     385        rc = usb_endpoint_pipe_end_session(&ctrl_pipe);
     386        if (rc != EOK) {
     387                goto failure;
     388        }
     389
     390        rc = ddf_fun_bind(child);
    390391        if (rc != EOK) {
    391392                goto failure;
     
    395396                *child_handle = child->handle;
    396397        }
    397        
    398         device_name_index++;
     398
     399        if (child_fun != NULL) {
     400                *child_fun = child;
     401        }
    399402
    400403        return EOK;
     
    404407                child->name = NULL;
    405408                /* This takes care of match_id deallocation as well. */
    406                 delete_device(child);
     409                ddf_fun_destroy(child);
    407410        }
    408411        if (child_name != NULL) {
     
    411414
    412415        return rc;
    413 
    414416}
    415417
  • uspace/lib/usb/src/request.c

    r4837092 r92574f4  
    3434 */
    3535#include <usb/request.h>
    36 #include <usb/devreq.h>
    3736#include <errno.h>
     37#include <assert.h>
    3838
    3939#define MAX_DATA_LENGTH ((size_t)(0xFFFF))
     
    230230}
    231231
     232/** Retrieve USB descriptor, allocate space for it.
     233 *
     234 * @param[in] pipe Control endpoint pipe (session must be already started).
     235 * @param[in] request_type Request type (standard/class/vendor).
     236 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
     237 * @param[in] descriptor_index Descriptor index.
     238 * @param[in] language Language index.
     239 * @param[out] buffer_ptr Where to store pointer to allocated buffer.
     240 * @param[out] buffer_size Where to store the size of the descriptor.
     241 * @return
     242 */
     243int usb_request_get_descriptor_alloc(usb_endpoint_pipe_t * pipe,
     244    usb_request_type_t request_type,
     245    uint8_t descriptor_type, uint8_t descriptor_index,
     246    uint16_t language,
     247    void **buffer_ptr, size_t *buffer_size)
     248{
     249        if (buffer_ptr == NULL) {
     250                return EBADMEM;
     251        }
     252
     253        int rc;
     254
     255        /*
     256         * Get only first byte to retrieve descriptor length.
     257         */
     258        uint8_t tmp_buffer[1];
     259        size_t bytes_transfered;
     260        rc = usb_request_get_descriptor(pipe, request_type,
     261            descriptor_type, descriptor_index, language,
     262            &tmp_buffer, 1, &bytes_transfered);
     263        if (rc != EOK) {
     264                return rc;
     265        }
     266        if (bytes_transfered != 1) {
     267                /* FIXME: some better error code? */
     268                return ESTALL;
     269        }
     270
     271        size_t size = tmp_buffer[0];
     272        if (size == 0) {
     273                /* FIXME: some better error code? */
     274                return ESTALL;
     275        }
     276
     277        /*
     278         * Allocate buffer and get the descriptor again.
     279         */
     280        void *buffer = malloc(size);
     281        if (buffer == NULL) {
     282                return ENOMEM;
     283        }
     284
     285        rc = usb_request_get_descriptor(pipe, request_type,
     286            descriptor_type, descriptor_index, language,
     287            buffer, size, &bytes_transfered);
     288        if (rc != EOK) {
     289                free(buffer);
     290                return rc;
     291        }
     292        if (bytes_transfered != size) {
     293                free(buffer);
     294                /* FIXME: some better error code? */
     295                return ESTALL;
     296        }
     297
     298        *buffer_ptr = buffer;
     299        if (buffer_size != NULL) {
     300                *buffer_size = size;
     301        }
     302
     303        return EOK;
     304}
     305
    232306/** Retrieve standard device descriptor of a USB device.
    233307 *
     
    355429}
    356430
     431/** Get list of supported languages by USB device.
     432 *
     433 * @param[in] pipe Control endpoint pipe (session must be already started).
     434 * @param[out] languages_ptr Where to store pointer to allocated array of
     435 *      supported languages.
     436 * @param[out] languages_count Number of supported languages.
     437 * @return Error code.
     438 */
     439int usb_request_get_supported_languages(usb_endpoint_pipe_t *pipe,
     440    l18_win_locales_t **languages_ptr, size_t *languages_count)
     441{
     442        int rc;
     443
     444        if (languages_ptr == NULL) {
     445                return EBADMEM;
     446        }
     447        if (languages_count == NULL) {
     448                return EBADMEM;
     449        }
     450
     451        uint8_t *string_descriptor = NULL;
     452        size_t string_descriptor_size = 0;
     453        rc = usb_request_get_descriptor_alloc(pipe,
     454            USB_REQUEST_TYPE_STANDARD, USB_DESCTYPE_STRING, 0, 0,
     455            (void **) &string_descriptor, &string_descriptor_size);
     456        if (rc != EOK) {
     457                return rc;
     458        }
     459        if (string_descriptor_size <= 2) {
     460                free(string_descriptor);
     461                return EEMPTY;
     462        }
     463        /* Substract first 2 bytes (length and descriptor type). */
     464        string_descriptor_size -= 2;
     465
     466        /* Odd number of bytes - descriptor is broken? */
     467        if ((string_descriptor_size % 2) != 0) {
     468                /* FIXME: shall we return with error or silently ignore? */
     469                free(string_descriptor);
     470                return ESTALL;
     471        }
     472
     473        size_t langs_count = string_descriptor_size / 2;
     474        l18_win_locales_t *langs
     475            = malloc(sizeof(l18_win_locales_t) * langs_count);
     476        if (langs == NULL) {
     477                free(string_descriptor);
     478                return ENOMEM;
     479        }
     480
     481        size_t i;
     482        for (i = 0; i < langs_count; i++) {
     483                /* Language code from the descriptor is in USB endianess. */
     484                /* FIXME: is this really correct? */
     485                uint16_t lang_code = (string_descriptor[2 + 2 * i + 1] << 8)
     486                    + string_descriptor[2 + 2 * i];
     487                langs[i] = uint16_usb2host(lang_code);
     488        }
     489
     490        free(string_descriptor);
     491
     492        *languages_ptr = langs;
     493        *languages_count =langs_count;
     494
     495        return EOK;
     496}
     497
     498/** Get string (descriptor) from USB device.
     499 *
     500 * The string is returned in native encoding of the operating system.
     501 * For HelenOS, that is UTF-8.
     502 *
     503 * @param[in] pipe Control endpoint pipe (session must be already started).
     504 * @param[in] index String index (in native endianess).
     505 * @param[in] lang String language (in native endianess).
     506 * @param[out] string_ptr Where to store allocated string in native encoding.
     507 * @return Error code.
     508 */
     509int usb_request_get_string(usb_endpoint_pipe_t *pipe,
     510    size_t index, l18_win_locales_t lang, char **string_ptr)
     511{
     512        if (string_ptr == NULL) {
     513                return EBADMEM;
     514        }
     515        /* Index is actually one byte value. */
     516        if (index > 0xFF) {
     517                return ERANGE;
     518        }
     519        /* Language is actually two byte value. */
     520        if (lang > 0xFFFF) {
     521                return ERANGE;
     522        }
     523
     524        int rc;
     525
     526        /* Prepare dynamically allocated variables. */
     527        uint8_t *string = NULL;
     528        wchar_t *string_chars = NULL;
     529
     530        /* Get the actual descriptor. */
     531        size_t string_size;
     532        rc = usb_request_get_descriptor_alloc(pipe,
     533            USB_REQUEST_TYPE_STANDARD, USB_DESCTYPE_STRING,
     534            index, uint16_host2usb(lang),
     535            (void **) &string, &string_size);
     536        if (rc != EOK) {
     537                goto leave;
     538        }
     539
     540        if (string_size <= 2) {
     541                rc =  EEMPTY;
     542                goto leave;
     543        }
     544        /* Substract first 2 bytes (length and descriptor type). */
     545        string_size -= 2;
     546
     547        /* Odd number of bytes - descriptor is broken? */
     548        if ((string_size % 2) != 0) {
     549                /* FIXME: shall we return with error or silently ignore? */
     550                rc = ESTALL;
     551                goto leave;
     552        }
     553
     554        size_t string_char_count = string_size / 2;
     555        string_chars = malloc(sizeof(wchar_t) * (string_char_count + 1));
     556        if (string_chars == NULL) {
     557                rc = ENOMEM;
     558                goto leave;
     559        }
     560
     561        /*
     562         * Build a wide string.
     563         * And do not forget to set NULL terminator (string descriptors
     564         * do not have them).
     565         */
     566        size_t i;
     567        for (i = 0; i < string_char_count; i++) {
     568                uint16_t uni_char = (string[2 + 2 * i + 1] << 8)
     569                    + string[2 + 2 * i];
     570                string_chars[i] = uni_char;
     571        }
     572        string_chars[string_char_count] = 0;
     573
     574
     575        /* Convert to normal string. */
     576        char *str = wstr_to_astr(string_chars);
     577        if (str == NULL) {
     578                rc = ENOMEM;
     579                goto leave;
     580        }
     581
     582        *string_ptr = str;
     583        rc = EOK;
     584
     585leave:
     586        if (string != NULL) {
     587                free(string);
     588        }
     589        if (string_chars != NULL) {
     590                free(string_chars);
     591        }
     592
     593        return rc;
     594}
     595
    357596/**
    358597 * @}
  • uspace/lib/usb/src/usb.c

    r4837092 r92574f4  
    5454}
    5555
    56 /** String representation of USB transaction outcome. */
    57 const char * usb_str_transaction_outcome(usb_transaction_outcome_t o)
    58 {
    59         switch (o) {
    60                 case USB_OUTCOME_OK:
    61                         return "ok";
    62                 case USB_OUTCOME_CRCERROR:
    63                         return "CRC error";
    64                 case USB_OUTCOME_BABBLE:
    65                         return "babble";
    66                 default:
    67                         return "unknown";
    68         }
    69 }
    70 
    71 
    7256/**
    7357 * @}
  • uspace/lib/usb/src/usbmem.c

    r4837092 r92574f4  
    11/*
    2  * Copyright (c) 2010 Matus Dekanek
     2 * Copyright (c) 2011 Matus Dekanek
    33 * All rights reserved.
    44 *
     
    6969}
    7070
    71 static void addr_remove_callback(link_t *item)
     71static void addr_remove_callback(link_t * item)
    7272{
    7373        //delete item
Note: See TracChangeset for help on using the changeset viewer.