Changeset 361e61b in mainline for uspace/lib


Ignore:
Timestamp:
2011-03-21T14:23:15Z (15 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
55e388a1
Parents:
c32688d (diff), 48fe0c9 (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:

merge with development

Location:
uspace/lib
Files:
6 added
16 edited
2 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/block/libblock.c

    rc32688d r361e61b  
    411411        l = hash_table_find(&cache->block_hash, &key);
    412412        if (l) {
     413found:
    413414                /*
    414415                 * We found the block in the cache.
     
    493494                                        fibril_mutex_unlock(&b->lock);
    494495                                        goto retry;
     496                                }
     497                                l = hash_table_find(&cache->block_hash, &key);
     498                                if (l) {
     499                                        /*
     500                                         * Someone else must have already
     501                                         * instantiated the block while we were
     502                                         * not holding the cache lock.
     503                                         * Leave the recycled block on the
     504                                         * freelist and continue as if we
     505                                         * found the block of interest during
     506                                         * the first try.
     507                                         */
     508                                        fibril_mutex_unlock(&b->lock);
     509                                        goto found;
    495510                                }
    496511
  • uspace/lib/c/Makefile

    rc32688d r361e61b  
    6565        generic/str.c \
    6666        generic/str_error.c \
     67        generic/l18n/langs.c \
    6768        generic/fibril.c \
    6869        generic/fibril_synch.c \
  • uspace/lib/c/include/l18n/langs.h

    rc32688d r361e61b  
    5757} l18_win_locales_t;
    5858
     59const char *str_l18_win_locale(l18_win_locales_t);
     60
    5961#endif
    6062
  • uspace/lib/drv/generic/remote_usbhc.c

    rc32688d r361e61b  
    5555static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5656static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     57static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     58static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5759//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5860
     
    7375
    7476        remote_usbhc_control_write,
    75         remote_usbhc_control_read
     77        remote_usbhc_control_read,
     78
     79        remote_usbhc_register_endpoint,
     80        remote_usbhc_unregister_endpoint
    7681};
    7782
     
    522527
    523528
     529void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
     530    ipc_callid_t callid, ipc_call_t *call)
     531{
     532        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     533
     534        if (!usb_iface->register_endpoint) {
     535                async_answer_0(callid, ENOTSUP);
     536                return;
     537        }
     538
     539#define INIT_FROM_HIGH_DATA(type, var, arg_no) \
     540        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256
     541#define INIT_FROM_LOW_DATA(type, var, arg_no) \
     542        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256
     543
     544        INIT_FROM_HIGH_DATA(usb_address_t, address, 1);
     545        INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1);
     546        INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2);
     547        INIT_FROM_LOW_DATA(usb_direction_t, direction, 2);
     548
     549#undef INIT_FROM_HIGH_DATA
     550#undef INIT_FROM_LOW_DATA
     551
     552        size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call);
     553        unsigned int interval  = (unsigned int) DEV_IPC_GET_ARG4(*call);
     554
     555        int rc = usb_iface->register_endpoint(fun, address, endpoint,
     556            transfer_type, direction, max_packet_size, interval);
     557
     558        async_answer_0(callid, rc);
     559}
     560
     561
     562void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
     563    ipc_callid_t callid, ipc_call_t *call)
     564{
     565        usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     566
     567        if (!usb_iface->unregister_endpoint) {
     568                async_answer_0(callid, ENOTSUP);
     569                return;
     570        }
     571
     572        usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
     573        usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call);
     574        usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call);
     575
     576        int rc = usb_iface->unregister_endpoint(fun,
     577            address, endpoint, direction);
     578
     579        async_answer_0(callid, rc);
     580}
     581
    524582
    525583/**
  • uspace/lib/drv/include/usbhc_iface.h

    rc32688d r361e61b  
    167167        IPC_M_USBHC_CONTROL_READ,
    168168
    169         /* IPC_M_USB_ */
     169        /** Register endpoint attributes at host controller.
     170         * This is used to reserve portion of USB bandwidth.
     171         * Parameters:
     172         * - USB address + endpoint number (ADDR * 256 + EP)
     173         * - transfer type + direction (TYPE * 256 + DIR)
     174         * - maximum packet size
     175         * - interval (in milliseconds)
     176         * Answer:
     177         * - EOK - reservation successful
     178         * - ELIMIT - not enough bandwidth to satisfy the request
     179         */
     180        IPC_M_USBHC_REGISTER_ENDPOINT,
     181
     182        /** Revert endpoint registration.
     183         * Parameters:
     184         * - USB address
     185         * - endpoint number
     186         * - data direction
     187         * Answer:
     188         * - EOK - endpoint unregistered
     189         * - ENOENT - unknown endpoint
     190         */
     191        IPC_M_USBHC_UNREGISTER_ENDPOINT
    170192} usbhc_iface_funcs_t;
    171193
     
    200222        int (*release_address)(ddf_fun_t *, usb_address_t);
    201223
     224        int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
     225            usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
     226        int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
     227            usb_direction_t);
     228
    202229        usbhc_iface_transfer_out_t interrupt_out;
    203230        usbhc_iface_transfer_in_t interrupt_in;
  • uspace/lib/usb/Makefile

    rc32688d r361e61b  
    3737        src/ddfiface.c \
    3838        src/debug.c \
     39        src/devdrv.c \
     40        src/devpoll.c \
    3941        src/dp.c \
    4042        src/dump.c \
     
    4749        src/request.c \
    4850        src/usb.c \
    49         src/usbdevice.c
     51        src/usbdevice.c \
     52        src/host/device_keeper.c \
     53        src/host/batch.c
    5054
    5155include $(USPACE_PREFIX)/Makefile.common
  • uspace/lib/usb/include/usb/classes/hub.h

    rc32688d r361e61b  
    6060} usb_hub_class_feature_t;
    6161
     62/** Header of standard hub descriptor without the "variadic" part. */
     63typedef struct {
     64        /** Descriptor length. */
     65        uint8_t length;
     66        /** Descriptor type (0x29). */
     67        uint8_t descriptor_type;
     68        /** Number of downstream ports. */
     69        uint8_t port_count;
     70        /** Characteristics bitmask. */
     71        uint16_t characteristics;
     72        /** Time from power-on to stabilization of current on the port. */
     73        uint8_t power_good_time;
     74        /** Maximum current requirements in mA. */
     75        uint8_t max_current;
     76} __attribute__ ((packed)) usb_hub_descriptor_header_t;
    6277
    6378/**
  • uspace/lib/usb/include/usb/dp.h

    rc32688d r361e61b  
    7777    usb_dp_parser_data_t *, uint8_t *, uint8_t *);
    7878
     79void usb_dp_walk_simple(uint8_t *, size_t, usb_dp_descriptor_nesting_t *,
     80    void (*)(uint8_t *, size_t, void *), void *);
     81
    7982#endif
    8083/**
  • uspace/lib/usb/include/usb/host/device_keeper.h

    rc32688d r361e61b  
    2727 */
    2828
    29 /** @addtogroup drvusbuhci
     29/** @addtogroup libusb
    3030 * @{
    3131 */
     
    3333 * @brief UHCI driver
    3434 */
    35 #ifndef UTILS_DEVICE_KEEPER_H
    36 #define UTILS_DEVICE_KEEPER_H
     35#ifndef LIBUSB_HOST_DEVICE_KEEPER_H
     36#define LIBUSB_HOST_DEVICE_KEEPER_H
    3737#include <devman.h>
    3838#include <fibril_synch.h>
     
    4444        usb_speed_t speed;
    4545        bool occupied;
    46         uint16_t toggle_status;
     46        uint16_t toggle_status[2];
    4747        devman_handle_t handle;
    4848};
     
    6363
    6464void device_keeper_reset_if_need(
    65     device_keeper_t *instance, usb_target_t target, const unsigned char *setup_data);
     65    device_keeper_t *instance, usb_target_t target,
     66    const unsigned char *setup_data);
    6667
    67 int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target);
     68int device_keeper_get_toggle(
     69    device_keeper_t *instance, usb_target_t target, usb_direction_t direction);
    6870
    69 int device_keeper_set_toggle(
    70     device_keeper_t *instance, usb_target_t target, bool toggle);
     71int device_keeper_set_toggle(device_keeper_t *instance,
     72    usb_target_t target, usb_direction_t direction, bool toggle);
    7173
    7274usb_address_t device_keeper_request(
  • uspace/lib/usb/include/usb/pipes.h

    rc32688d r361e61b  
    106106        const usb_endpoint_description_t *description;
    107107        /** Interface number the endpoint must belong to (-1 for any). */
    108         const int interface_no;
     108        int interface_no;
    109109        /** Found descriptor fitting the description. */
    110110        usb_standard_endpoint_descriptor_t *descriptor;
     
    123123
    124124int usb_device_get_assigned_interface(ddf_dev_t *);
     125usb_address_t usb_device_get_assigned_address(devman_handle_t);
    125126
    126127int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *,
     
    129130int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *,
    130131    usb_device_connection_t *);
     132int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *);
    131133int usb_endpoint_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    132134    size_t, uint8_t *, size_t, usb_device_connection_t *);
    133 
     135int usb_endpoint_pipe_register(usb_endpoint_pipe_t *, unsigned int,
     136    usb_hc_connection_t *);
     137int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *, usb_hc_connection_t *);
    134138
    135139int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *);
  • uspace/lib/usb/include/usb/request.h

    rc32688d r361e61b  
    9494    uint16_t, uint16_t, void *, size_t, size_t *);
    9595
     96int usb_request_get_status(usb_endpoint_pipe_t *, usb_request_recipient_t,
     97    uint16_t, uint16_t *);
     98int usb_request_clear_feature(usb_endpoint_pipe_t *, usb_request_type_t,
     99    usb_request_recipient_t, uint16_t, uint16_t);
     100int usb_request_set_feature(usb_endpoint_pipe_t *, usb_request_type_t,
     101    usb_request_recipient_t, uint16_t, uint16_t);
    96102int usb_request_set_address(usb_endpoint_pipe_t *, usb_address_t);
    97103int usb_request_get_descriptor(usb_endpoint_pipe_t *, usb_request_type_t,
     
    108114int usb_request_get_full_configuration_descriptor_alloc(usb_endpoint_pipe_t *,
    109115    int, void **, size_t *);
     116int usb_request_set_descriptor(usb_endpoint_pipe_t *, usb_request_type_t,
     117    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t);
     118int usb_request_get_configuration(usb_endpoint_pipe_t *, uint8_t *);
    110119int usb_request_set_configuration(usb_endpoint_pipe_t *, uint8_t);
     120int usb_request_get_interface(usb_endpoint_pipe_t *, uint8_t, uint8_t *);
     121int usb_request_set_interface(usb_endpoint_pipe_t *, uint8_t, uint8_t);
    111122
    112123int usb_request_get_supported_languages(usb_endpoint_pipe_t *,
  • uspace/lib/usb/src/dp.c

    rc32688d r361e61b  
    258258}
    259259
     260/** Browser of the descriptor tree.
     261 *
     262 * @see usb_dp_walk_simple
     263 *
     264 * @param parser Descriptor parser.
     265 * @param data Data for descriptor parser.
     266 * @param root Pointer to current root of the tree.
     267 * @param depth Current nesting depth.
     268 * @param callback Callback for each found descriptor.
     269 * @param arg Custom (user) argument.
     270 */
     271static void usb_dp_browse_simple_internal(usb_dp_parser_t *parser,
     272    usb_dp_parser_data_t *data, uint8_t *root, size_t depth,
     273    void (*callback)(uint8_t *, size_t, void *), void *arg)
     274{
     275        if (root == NULL) {
     276                return;
     277        }
     278        callback(root, depth, arg);
     279        uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
     280        do {
     281                usb_dp_browse_simple_internal(parser, data, child, depth + 1,
     282                    callback, arg);
     283                child = usb_dp_get_sibling_descriptor(parser, data,
     284                    root, child);
     285        } while (child != NULL);
     286}
     287
     288/** Browse flatten descriptor tree.
     289 *
     290 * The callback is called with following arguments: pointer to the start
     291 * of the descriptor (somewhere inside @p descriptors), depth of the nesting
     292 * (starting from 0 for the first descriptor) and the custom argument.
     293 * Note that the size of the descriptor is not passed because it can
     294 * be read from the first byte of the descriptor.
     295 *
     296 * @param descriptors Descriptor data.
     297 * @param descriptors_size Size of descriptor data (in bytes).
     298 * @param descriptor_nesting Possible descriptor nesting.
     299 * @param callback Callback for each found descriptor.
     300 * @param arg Custom (user) argument.
     301 */
     302void usb_dp_walk_simple(uint8_t *descriptors, size_t descriptors_size,
     303    usb_dp_descriptor_nesting_t *descriptor_nesting,
     304    void (*callback)(uint8_t *, size_t, void *), void *arg)
     305{
     306        if ((descriptors == NULL) || (descriptors_size == 0)
     307            || (descriptor_nesting == NULL) || (callback == NULL)) {
     308                return;
     309        }
     310
     311        usb_dp_parser_data_t data = {
     312                .data = descriptors,
     313                .size = descriptors_size,
     314                .arg = NULL
     315        };
     316
     317        usb_dp_parser_t parser = {
     318                .nesting = descriptor_nesting
     319        };
     320
     321        usb_dp_browse_simple_internal(&parser, &data, descriptors,
     322            0, callback, arg);
     323}
    260324
    261325/** @}
  • uspace/lib/usb/src/host/device_keeper.c

    rc32688d r361e61b  
    2727 */
    2828
    29 /** @addtogroup drvusbuhci
     29/** @addtogroup libusb
    3030 * @{
    3131 */
     
    3636#include <errno.h>
    3737#include <usb/debug.h>
    38 
    39 #include "device_keeper.h"
    40 
    41 /*----------------------------------------------------------------------------*/
    42 /** Initializes device keeper structure.
     38#include <usb/host/device_keeper.h>
     39
     40/*----------------------------------------------------------------------------*/
     41/** Initialize device keeper structure.
    4342 *
    4443 * @param[in] instance Memory place to initialize.
     44 *
     45 * Set all values to false/0.
    4546 */
    4647void device_keeper_init(device_keeper_t *instance)
     
    5455                instance->devices[i].occupied = false;
    5556                instance->devices[i].handle = 0;
    56                 instance->devices[i].toggle_status = 0;
    57         }
    58 }
    59 /*----------------------------------------------------------------------------*/
    60 /** Attempts to obtain address 0, blocks.
     57                instance->devices[i].toggle_status[0] = 0;
     58                instance->devices[i].toggle_status[1] = 0;
     59        }
     60}
     61/*----------------------------------------------------------------------------*/
     62/** Attempt to obtain address 0, blocks.
    6163 *
    6264 * @param[in] instance Device keeper structure to use.
     
    7678}
    7779/*----------------------------------------------------------------------------*/
    78 /** Attempts to obtain address 0, blocks.
     80/** Attempt to obtain address 0, blocks.
    7981 *
    8082 * @param[in] instance Device keeper structure to use.
     
    9092}
    9193/*----------------------------------------------------------------------------*/
    92 /** Checks setup data for signs of toggle reset.
     94/** Check setup packet data for signs of toggle reset.
    9395 *
    9496 * @param[in] instance Device keeper structure to use.
    9597 * @param[in] target Device to receive setup packet.
    9698 * @param[in] data Setup packet data.
     99 *
     100 * Really ugly one.
    97101 */
    98102void device_keeper_reset_if_need(
     
    105109            || !instance->devices[target.address].occupied) {
    106110                fibril_mutex_unlock(&instance->guard);
     111                usb_log_error("Invalid data when checking for toggle reset.\n");
    107112                return;
    108113        }
     
    114119                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    115120                        /* endpoint number is < 16, thus first byte is enough */
    116                         instance->devices[target.address].toggle_status &=
     121                        instance->devices[target.address].toggle_status[0] &=
     122                            ~(1 << data[4]);
     123                        instance->devices[target.address].toggle_status[1] &=
    117124                            ~(1 << data[4]);
    118125                }
     
    123130                /* target must be device */
    124131                if ((data[0] & 0xf) == 0) {
    125                         instance->devices[target.address].toggle_status = 0;
     132                        instance->devices[target.address].toggle_status[0] = 0;
     133                        instance->devices[target.address].toggle_status[1] = 0;
    126134                }
    127135        break;
     
    130138}
    131139/*----------------------------------------------------------------------------*/
    132 /** Gets current value of endpoint toggle.
     140/** Get current value of endpoint toggle.
    133141 *
    134142 * @param[in] instance Device keeper structure to use.
     
    136144 * @return Error code
    137145 */
    138 int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)
    139 {
    140         assert(instance);
     146int device_keeper_get_toggle(
     147    device_keeper_t *instance, usb_target_t target, usb_direction_t direction)
     148{
     149        assert(instance);
     150        /* only control pipes are bi-directional and those do not need toggle */
     151        if (direction == USB_DIRECTION_BOTH)
     152                return ENOENT;
    141153        int ret;
    142154        fibril_mutex_lock(&instance->guard);
     
    144156            || target.address >= USB_ADDRESS_COUNT || target.address < 0
    145157            || !instance->devices[target.address].occupied) {
     158                usb_log_error("Invalid data when asking for toggle value.\n");
    146159                ret = EINVAL;
    147160        } else {
    148                 ret =
    149                     (instance->devices[target.address].toggle_status
     161                ret = (instance->devices[target.address].toggle_status[direction]
    150162                        >> target.endpoint) & 1;
    151163        }
     
    154166}
    155167/*----------------------------------------------------------------------------*/
    156 /** Sets current value of endpoint toggle.
     168/** Set current value of endpoint toggle.
    157169 *
    158170 * @param[in] instance Device keeper structure to use.
    159171 * @param[in] target Device and endpoint used.
    160  * @param[in] toggle Current toggle value.
     172 * @param[in] toggle Toggle value.
    161173 * @return Error code.
    162174 */
    163 int device_keeper_set_toggle(
    164     device_keeper_t *instance, usb_target_t target, bool toggle)
    165 {
    166         assert(instance);
     175int device_keeper_set_toggle(device_keeper_t *instance,
     176    usb_target_t target, usb_direction_t direction, bool toggle)
     177{
     178        assert(instance);
     179        /* only control pipes are bi-directional and those do not need toggle */
     180        if (direction == USB_DIRECTION_BOTH)
     181                return ENOENT;
    167182        int ret;
    168183        fibril_mutex_lock(&instance->guard);
     
    170185            || target.address >= USB_ADDRESS_COUNT || target.address < 0
    171186            || !instance->devices[target.address].occupied) {
     187                usb_log_error("Invalid data when setting toggle value.\n");
    172188                ret = EINVAL;
    173189        } else {
    174190                if (toggle) {
    175                         instance->devices[target.address].toggle_status |= (1 << target.endpoint);
     191                        instance->devices[target.address].toggle_status[direction]
     192                            |= (1 << target.endpoint);
    176193                } else {
    177                         instance->devices[target.address].toggle_status &= ~(1 << target.endpoint);
     194                        instance->devices[target.address].toggle_status[direction]
     195                            &= ~(1 << target.endpoint);
    178196                }
    179197                ret = EOK;
     
    183201}
    184202/*----------------------------------------------------------------------------*/
    185 /** Gets a free USB address
     203/** Get a free USB address
    186204 *
    187205 * @param[in] instance Device keeper structure to use.
     
    210228        instance->devices[new_address].occupied = true;
    211229        instance->devices[new_address].speed = speed;
    212         instance->devices[new_address].toggle_status = 0;
     230        instance->devices[new_address].toggle_status[0] = 0;
     231        instance->devices[new_address].toggle_status[1] = 0;
    213232        instance->last_address = new_address;
    214233        fibril_mutex_unlock(&instance->guard);
     
    216235}
    217236/*----------------------------------------------------------------------------*/
    218 /** Binds USB address to devman handle.
     237/** Bind USB address to devman handle.
    219238 *
    220239 * @param[in] instance Device keeper structure to use.
     
    234253}
    235254/*----------------------------------------------------------------------------*/
    236 /** Releases used USB address.
     255/** Release used USB address.
    237256 *
    238257 * @param[in] instance Device keeper structure to use.
     
    251270}
    252271/*----------------------------------------------------------------------------*/
    253 /** Finds USB address associated with the device
     272/** Find USB address associated with the device
    254273 *
    255274 * @param[in] instance Device keeper structure to use.
     
    274293}
    275294/*----------------------------------------------------------------------------*/
    276 /** Gets speed associated with the address
     295/** Get speed associated with the address
    277296 *
    278297 * @param[in] instance Device keeper structure to use.
  • uspace/lib/usb/src/hub.c

    rc32688d r361e61b  
    235235                goto leave_release_default_address;
    236236        }
     237        rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
     238        if (rc != EOK) {
     239                rc = ENOTCONN;
     240                goto leave_release_default_address;
     241        }
    237242
    238243        rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
  • uspace/lib/usb/src/pipes.c

    rc32688d r361e61b  
    4242#include <assert.h>
    4343
     44#define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
     45
    4446/** Tell USB address assigned to given device.
    4547 *
     
    5153{
    5254        sysarg_t address;
    53 
    5455
    5556        /*
     
    9697}
    9798
     99/** Tell USB address assigned to given device.
     100 *
     101 * @param dev_handle Devman handle of the USB device in question.
     102 * @return USB address or negative error code.
     103 */
     104usb_address_t usb_device_get_assigned_address(devman_handle_t dev_handle)
     105{
     106        int parent_phone = devman_parent_device_connect(dev_handle,
     107            IPC_FLAG_BLOCKING);
     108        if (parent_phone < 0) {
     109                return parent_phone;
     110        }
     111
     112        sysarg_t address;
     113
     114        int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
     115            IPC_M_USB_GET_ADDRESS,
     116            dev_handle, &address);
     117
     118        if (rc != EOK) {
     119                return rc;
     120        }
     121
     122        async_hangup(parent_phone);
     123
     124        return (usb_address_t) address;
     125}
     126
    98127/** Initialize connection to USB device.
    99128 *
     
    123152        }
    124153
    125         my_address = get_my_address(parent_phone, dev);
    126         if (my_address < 0) {
    127                 rc = my_address;
    128                 goto leave;
    129         }
     154        /*
     155         * Asking for "my" address may require several attempts.
     156         * That is because following scenario may happen:
     157         *  - parent driver (i.e. driver of parent device) announces new device
     158         *    and devman launches current driver
     159         *  - parent driver is preempted and thus does not send address-handle
     160         *    binding to HC driver
     161         *  - this driver gets here and wants the binding
     162         *  - the HC does not know the binding yet and thus it answers ENOENT
     163         *  So, we need to wait for the HC to learn the binding.
     164         */
     165        do {
     166                my_address = get_my_address(parent_phone, dev);
     167
     168                if (my_address == ENOENT) {
     169                        /* Be nice, let other fibrils run and try again. */
     170                        async_usleep(IPC_AGAIN_DELAY);
     171                } else if (my_address < 0) {
     172                        /* Some other problem, no sense trying again. */
     173                        rc = my_address;
     174                        goto leave;
     175                }
     176
     177        } while (my_address < 0);
    130178
    131179        rc = usb_device_connection_initialize(connection,
  • uspace/lib/usb/src/pipesinit.c

    rc32688d r361e61b  
    3737#include <usb/pipes.h>
    3838#include <usb/dp.h>
     39#include <usb/request.h>
     40#include <usbhc_iface.h>
    3941#include <errno.h>
    4042#include <assert.h>
     43
     44#define CTRL_PIPE_MIN_PACKET_SIZE 8
     45#define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7
    4146
    4247
     
    369374
    370375        int rc = usb_endpoint_pipe_initialize(pipe, connection,
    371             0, USB_TRANSFER_CONTROL, 8, USB_DIRECTION_BOTH);
     376            0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
     377            USB_DIRECTION_BOTH);
    372378
    373379        return rc;
     380}
     381
     382/** Probe default control pipe for max packet size.
     383 *
     384 * The function tries to get the correct value of max packet size several
     385 * time before giving up.
     386 *
     387 * The session on the pipe shall not be started.
     388 *
     389 * @param pipe Default control pipe.
     390 * @return Error code.
     391 */
     392int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *pipe)
     393{
     394        assert(pipe);
     395        assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE);
     396
     397        if ((pipe->direction != USB_DIRECTION_BOTH) ||
     398            (pipe->transfer_type != USB_TRANSFER_CONTROL) ||
     399            (pipe->endpoint_no != 0)) {
     400                return EINVAL;
     401        }
     402
     403#define TRY_LOOP(attempt_var) \
     404        for (attempt_var = 0; attempt_var < 3; attempt_var++)
     405
     406        size_t failed_attempts;
     407        int rc;
     408
     409        TRY_LOOP(failed_attempts) {
     410                rc = usb_endpoint_pipe_start_session(pipe);
     411                if (rc == EOK) {
     412                        break;
     413                }
     414        }
     415        if (rc != EOK) {
     416                return rc;
     417        }
     418
     419
     420        uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];
     421        size_t transferred_size;
     422        TRY_LOOP(failed_attempts) {
     423                rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD,
     424                    USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE,
     425                    0, 0, dev_descr_start, CTRL_PIPE_MIN_PACKET_SIZE,
     426                    &transferred_size);
     427                if (rc == EOK) {
     428                        if (transferred_size != CTRL_PIPE_MIN_PACKET_SIZE) {
     429                                rc = ELIMIT;
     430                                continue;
     431                        }
     432                        break;
     433                }
     434        }
     435        usb_endpoint_pipe_end_session(pipe);
     436        if (rc != EOK) {
     437                return rc;
     438        }
     439
     440        pipe->max_packet_size
     441            = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET];
     442
     443        return EOK;
     444}
     445
     446/** Register endpoint with the host controller.
     447 *
     448 * @param pipe Pipe to be registered.
     449 * @param interval Polling interval.
     450 * @param hc_connection Connection to the host controller (must be opened).
     451 * @return Error code.
     452 */
     453int usb_endpoint_pipe_register(usb_endpoint_pipe_t *pipe,
     454    unsigned int interval,
     455    usb_hc_connection_t *hc_connection)
     456{
     457        assert(pipe);
     458        assert(hc_connection);
     459
     460        if (!usb_hc_connection_is_opened(hc_connection)) {
     461                return EBADF;
     462        }
     463
     464#define _PACK(high, low) ((high) * 256 + (low))
     465
     466        return async_req_5_0(hc_connection->hc_phone,
     467            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,
     468            _PACK(pipe->wire->address, pipe->endpoint_no),
     469            _PACK(pipe->transfer_type, pipe->direction),
     470            pipe->max_packet_size, interval);
     471
     472#undef _PACK
     473}
     474
     475/** Revert endpoint registration with the host controller.
     476 *
     477 * @param pipe Pipe to be unregistered.
     478 * @param hc_connection Connection to the host controller (must be opened).
     479 * @return Error code.
     480 */
     481int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *pipe,
     482    usb_hc_connection_t *hc_connection)
     483{
     484        assert(pipe);
     485        assert(hc_connection);
     486
     487        if (!usb_hc_connection_is_opened(hc_connection)) {
     488                return EBADF;
     489        }
     490
     491        return async_req_4_0(hc_connection->hc_phone,
     492            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_UNREGISTER_ENDPOINT,
     493            pipe->wire->address, pipe->endpoint_no, pipe->direction);
    374494}
    375495
  • uspace/lib/usb/src/recognise.c

    rc32688d r361e61b  
    247247#undef VENDOR_ONLY_FMT
    248248#undef VENDOR_ONLY_ARGS
     249
     250        /* As a last resort, try fallback driver. */
     251        ADD_MATCHID_OR_RETURN(matches, 10, "usb&interface&fallback");
    249252
    250253        return EOK;
     
    291294        }
    292295       
     296        /* As a last resort, try fallback driver. */
     297        ADD_MATCHID_OR_RETURN(matches, 10, "usb&fallback");
     298
    293299        return EOK;
    294300}
     
    369375                goto failure;
    370376        }
     377        rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);
     378        if (rc != EOK) {
     379                goto failure;
     380        }
    371381
    372382        /*
     
    374384         * naming etc., something more descriptive could be created.
    375385         */
    376         rc = asprintf(&child_name, "usbdev%02zu", this_device_name_index);
     386        rc = asprintf(&child_name, "usb%02zu_a%d",
     387            this_device_name_index, address);
    377388        if (rc < 0) {
    378389                goto failure;
  • uspace/lib/usb/src/request.c

    rc32688d r361e61b  
    157157}
    158158
     159/** Retrieve status of a USB device.
     160 *
     161 * @param[in] pipe Control endpoint pipe (session must be already started).
     162 * @param[in] index Recipient index (in native endianness).
     163 * @param[in] recipient Recipient of the GET_STATUS request.
     164 * @param[out] status Recipient status (in native endianness).
     165 * @return Error code.
     166 */
     167int usb_request_get_status(usb_endpoint_pipe_t *pipe,
     168    usb_request_recipient_t recipient, uint16_t index,
     169    uint16_t *status)
     170{
     171        if ((recipient == USB_REQUEST_RECIPIENT_DEVICE) && (index != 0)) {
     172                return EINVAL;
     173        }
     174
     175        if (status == NULL) {
     176                return EBADMEM;
     177        }
     178
     179        uint16_t status_usb_endianess;
     180        size_t data_transfered_size;
     181        int rc = usb_control_request_get(pipe, USB_REQUEST_TYPE_STANDARD,
     182            recipient, USB_DEVREQ_GET_STATUS, 0, uint16_host2usb(index),
     183            &status_usb_endianess, 2, &data_transfered_size);
     184        if (rc != EOK) {
     185                return rc;
     186        }
     187        if (data_transfered_size != 2) {
     188                return ELIMIT;
     189        }
     190
     191        *status = uint16_usb2host(status_usb_endianess);
     192
     193        return EOK;
     194}
     195
     196/** Clear or disable specific device feature.
     197 *
     198 * @param[in] pipe Control endpoint pipe (session must be already started).
     199 * @param[in] request_type Request type (standard/class/vendor).
     200 * @param[in] recipient Recipient of the CLEAR_FEATURE request.
     201 * @param[in] feature_selector Feature selector (in native endianness).
     202 * @param[in] index Recipient index (in native endianness).
     203 * @return Error code.
     204 */
     205int usb_request_clear_feature(usb_endpoint_pipe_t *pipe,
     206    usb_request_type_t request_type, usb_request_recipient_t recipient,
     207    uint16_t feature_selector, uint16_t index)
     208{
     209        if (request_type == USB_REQUEST_TYPE_STANDARD) {
     210                if ((recipient == USB_REQUEST_RECIPIENT_DEVICE)
     211                    && (index != 0)) {
     212                        return EINVAL;
     213                }
     214        }
     215
     216        int rc = usb_control_request_set(pipe, request_type, recipient,
     217            USB_DEVREQ_CLEAR_FEATURE,
     218            uint16_host2usb(feature_selector), uint16_host2usb(index),
     219            NULL, 0);
     220
     221        return rc;
     222}
     223
     224/** Set or enable specific device feature.
     225 *
     226 * @param[in] pipe Control endpoint pipe (session must be already started).
     227 * @param[in] request_type Request type (standard/class/vendor).
     228 * @param[in] recipient Recipient of the SET_FEATURE request.
     229 * @param[in] feature_selector Feature selector (in native endianness).
     230 * @param[in] index Recipient index (in native endianness).
     231 * @return Error code.
     232 */
     233int usb_request_set_feature(usb_endpoint_pipe_t *pipe,
     234    usb_request_type_t request_type, usb_request_recipient_t recipient,
     235    uint16_t feature_selector, uint16_t index)
     236{
     237        if (request_type == USB_REQUEST_TYPE_STANDARD) {
     238                if ((recipient == USB_REQUEST_RECIPIENT_DEVICE)
     239                    && (index != 0)) {
     240                        return EINVAL;
     241                }
     242        }
     243
     244        int rc = usb_control_request_set(pipe, request_type, recipient,
     245            USB_DEVREQ_SET_FEATURE,
     246            uint16_host2usb(feature_selector), uint16_host2usb(index),
     247            NULL, 0);
     248
     249        return rc;
     250}
     251
    159252/** Change address of connected device.
    160253 * This function automatically updates the backing connection to point to
     
    473566}
    474567
     568/** Update existing or add new USB descriptor to a USB device.
     569 *
     570 * @param[in] pipe Control endpoint pipe (session must be already started).
     571 * @param[in] request_type Request type (standard/class/vendor).
     572 * @param[in] recipient Request recipient (device/interface/endpoint).
     573 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
     574 * @param[in] descriptor_index Descriptor index.
     575 * @param[in] language Language index (in native endianness).
     576 * @param[in] buffer Buffer with the new descriptor (in USB endianness).
     577 * @param[in] size Size of the @p buffer in bytes (in native endianness).
     578 * @return Error code.
     579 */
     580int usb_request_set_descriptor(usb_endpoint_pipe_t *pipe,
     581    usb_request_type_t request_type, usb_request_recipient_t recipient,
     582    uint8_t descriptor_type, uint8_t descriptor_index,
     583    uint16_t language,
     584    void *buffer, size_t size)
     585{
     586        if (buffer == NULL) {
     587                return EBADMEM;
     588        }
     589        if (size == 0) {
     590                return EINVAL;
     591        }
     592
     593        /* FIXME: proper endianness. */
     594        uint16_t wValue = descriptor_index | (descriptor_type << 8);
     595
     596        return usb_control_request_set(pipe,
     597            request_type, recipient,
     598            USB_DEVREQ_SET_DESCRIPTOR,
     599            wValue, language,
     600            buffer, size);
     601}
     602
     603/** Get current configuration value of USB device.
     604 *
     605 * @param[in] pipe Control endpoint pipe (session must be already started).
     606 * @param[out] configuration_value Current configuration value.
     607 * @return Error code.
     608 */
     609int usb_request_get_configuration(usb_endpoint_pipe_t *pipe,
     610    uint8_t *configuration_value)
     611{
     612        uint8_t value;
     613        size_t actual_size;
     614
     615        int rc = usb_control_request_get(pipe,
     616            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
     617            USB_DEVREQ_GET_CONFIGURATION,
     618            0, 0,
     619            &value, 1, &actual_size);
     620
     621        if (rc != EOK) {
     622                return rc;
     623        }
     624        if (actual_size != 1) {
     625                return ELIMIT;
     626        }
     627
     628        if (configuration_value != NULL) {
     629                *configuration_value = value;
     630        }
     631
     632        return EOK;
     633}
     634
    475635/** Set configuration of USB device.
    476636 *
     
    488648            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
    489649            USB_DEVREQ_SET_CONFIGURATION, config_value, 0,
     650            NULL, 0);
     651}
     652
     653/** Get selected alternate setting for USB interface.
     654 *
     655 * @param[in] pipe Control endpoint pipe (session must be already started).
     656 * @param[in] interface_index Interface index.
     657 * @param[out] alternate_setting Alternate setting for the interface.
     658 * @return Error code.
     659 */
     660int usb_request_get_interface(usb_endpoint_pipe_t *pipe,
     661    uint8_t interface_index, uint8_t *alternate_setting)
     662{
     663        uint8_t value;
     664        size_t actual_size;
     665
     666        int rc = usb_control_request_get(pipe,
     667            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
     668            USB_DEVREQ_GET_INTERFACE,
     669            0, uint16_host2usb((uint16_t) interface_index),
     670            &value, 1, &actual_size);
     671
     672        if (rc != EOK) {
     673                return rc;
     674        }
     675        if (actual_size != 1) {
     676                return ELIMIT;
     677        }
     678
     679        if (alternate_setting != NULL) {
     680                *alternate_setting = value;
     681        }
     682
     683        return EOK;
     684}
     685
     686/** Select alternate setting for USB interface.
     687 *
     688 * @param[in] pipe Control endpoint pipe (session must be already started).
     689 * @param[in] interface_index Interface index.
     690 * @param[in] alternate_setting Alternate setting to select.
     691 * @return Error code.
     692 */
     693int usb_request_set_interface(usb_endpoint_pipe_t *pipe,
     694    uint8_t interface_index, uint8_t alternate_setting)
     695{
     696        return usb_control_request_set(pipe,
     697            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
     698            USB_DEVREQ_SET_INTERFACE,
     699            uint16_host2usb((uint16_t) alternate_setting),
     700            uint16_host2usb((uint16_t) interface_index),
    490701            NULL, 0);
    491702}
Note: See TracChangeset for help on using the changeset viewer.