Changeset e50cd7f in mainline for uspace/lib


Ignore:
Timestamp:
2011-04-17T19:17:55Z (15 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
63517c2, cfbbe1d3
Parents:
ef354b6 (diff), 8595577b (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:

new report structure fixes

Location:
uspace/lib
Files:
10 added
46 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/arch/mips32/include/atomic.h

    ref354b6 re50cd7f  
    7070                "       sc %0, %1\n"
    7171                "       beq %0, %4, 1b\n"       /* if the atomic operation failed, try again */
    72                 /*      nop     */              /* nop is inserted automatically by compiler */
    7372                "       nop\n"
    7473                : "=&r" (tmp),
  • uspace/lib/c/generic/adt/measured_strings.c

    ref354b6 re50cd7f  
    7474        new->length = length;
    7575        new->value = ((uint8_t *) new) + sizeof(measured_string_t);
    76         // append terminating zero explicitly - to be safe
     76        /* Append terminating zero explicitly - to be safe */
    7777        memcpy(new->value, string, new->length);
    7878        new->value[new->length] = '\0';
  • uspace/lib/c/generic/async.c

    ref354b6 re50cd7f  
    15861586 * @param dst     Address of the beginning of the destination buffer.
    15871587 * @param size    Size of the destination buffer.
     1588 * @param flags   Flags to control the data transfer.
    15881589 *
    15891590 * @return Zero on success or a negative error code from errno.h.
    15901591 *
    15911592 */
    1592 int async_data_read_start(int phoneid, void *dst, size_t size)
    1593 {
    1594         return async_req_2_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
    1595             (sysarg_t) size);
     1593int
     1594async_data_read_start_generic(int phoneid, void *dst, size_t size, int flags)
     1595{
     1596        return async_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
     1597            (sysarg_t) size, (sysarg_t) flags);
    15961598}
    15971599
     
    16831685 * @param src     Address of the beginning of the source buffer.
    16841686 * @param size    Size of the source buffer.
     1687 * @param flags   Flags to control the data transfer.
    16851688 *
    16861689 * @return Zero on success or a negative error code from errno.h.
    16871690 *
    16881691 */
    1689 int async_data_write_start(int phoneid, const void *src, size_t size)
    1690 {
    1691         return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
    1692             (sysarg_t) size);
     1692int
     1693async_data_write_start_generic(int phoneid, const void *src, size_t size,
     1694    int flags)
     1695{
     1696        return async_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
     1697            (sysarg_t) size, (sysarg_t) flags);
    16931698}
    16941699
  • uspace/lib/c/generic/vfs/vfs.c

    ref354b6 re50cd7f  
    378378       
    379379        req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
    380         rc = async_data_read_start(vfs_phone, (void *)buf, nbyte);
     380        rc = async_data_read_start_generic(vfs_phone, (void *) buf, nbyte,
     381            IPC_XF_RESTRICT);
    381382        if (rc != EOK) {
    382383                vfs_exchange_end(vfs_phone);
     
    407408       
    408409        req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
    409         rc = async_data_write_start(vfs_phone, (void *)buf, nbyte);
     410        rc = async_data_write_start_generic(vfs_phone, (void *) buf, nbyte,
     411            IPC_XF_RESTRICT);
    410412        if (rc != EOK) {
    411413                vfs_exchange_end(vfs_phone);
  • uspace/lib/c/include/async.h

    ref354b6 re50cd7f  
    341341
    342342extern aid_t async_data_read(int, void *, size_t, ipc_call_t *);
    343 extern int async_data_read_start(int, void *, size_t);
     343#define async_data_read_start(p, buf, len) \
     344        async_data_read_start_generic((p), (buf), (len), IPC_XF_NONE)
     345
     346extern int async_data_read_start_generic(int, void *, size_t, int);
    344347extern bool async_data_read_receive(ipc_callid_t *, size_t *);
    345348extern int async_data_read_finalize(ipc_callid_t, const void *, size_t);
     
    380383            (arg4), (answer))
    381384
    382 extern int async_data_write_start(int, const void *, size_t);
     385#define async_data_write_start(p, buf, len) \
     386        async_data_write_start_generic((p), (buf), (len), IPC_XF_NONE)
     387
     388extern int async_data_write_start_generic(int, const void *, size_t, int);
    383389extern bool async_data_write_receive(ipc_callid_t *, size_t *);
    384390extern int async_data_write_finalize(ipc_callid_t, void *, size_t);
  • uspace/lib/c/include/ipc/dev_iface.h

    ref354b6 re50cd7f  
    4545        /** Interface provided by USB host controller. */
    4646        USBHC_DEV_IFACE,
     47        /** Interface provided by USB HID devices. */
     48        USBHID_DEV_IFACE,
    4749
    4850        DEV_IFACE_MAX
  • uspace/lib/drv/generic/dev_iface.c

    ref354b6 re50cd7f  
    4343#include "remote_usb.h"
    4444#include "remote_usbhc.h"
     45#include "remote_usbhid.h"
    4546#include "remote_pci.h"
    4647
     
    5152                &remote_pci_iface,
    5253                &remote_usb_iface,
    53                 &remote_usbhc_iface
     54                &remote_usbhc_iface,
     55                &remote_usbhid_iface
    5456        }
    5557};
  • uspace/lib/drv/generic/driver.c

    ref354b6 re50cd7f  
    4747#include <stdlib.h>
    4848#include <str.h>
     49#include <str_error.h>
    4950#include <ctype.h>
    5051#include <errno.h>
     
    402403                            get_remote_method(rem_iface, iface_method_idx);
    403404                        if (iface_method_ptr == NULL) {
    404                                 // the interface has not such method
     405                                /* The interface has not such method */
    405406                                printf("%s: driver_connection_gen error - "
    406407                                    "invalid interface method.", driver->name);
     
    655656int ddf_driver_main(driver_t *drv)
    656657{
     658        int rc;
     659
    657660        /*
    658661         * Remember the driver structure - driver_ops will be called by generic
     
    668671       
    669672        /*
    670          * Register driver by device manager with generic handler for incoming
    671          * connections.
     673         * Register driver with device manager using generic handler for
     674         * incoming connections.
    672675         */
    673         devman_driver_register(driver->name, driver_connection);
    674        
     676        rc = devman_driver_register(driver->name, driver_connection);
     677        if (rc != EOK) {
     678                printf("Error: Failed to register driver with device manager "
     679                    "(%s).\n", (rc == EEXISTS) ? "driver already started" :
     680                    str_error(rc));
     681               
     682                return 1;
     683        }
     684       
     685        /* Return success from the task since server has started. */
     686        rc = task_retval(0);
     687        if (rc != EOK)
     688                return 1;
     689
    675690        async_manager();
    676691       
  • uspace/lib/drv/generic/remote_usbhc.c

    ref354b6 re50cd7f  
    5050static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5151static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    52 static void remote_usbhc_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    53 static void remote_usbhc_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5452static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5553static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     
    6159/** Remote USB host controller interface operations. */
    6260static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
    63         remote_usbhc_reserve_default_address,
    64         remote_usbhc_release_default_address,
    65 
    6661        remote_usbhc_request_address,
    6762        remote_usbhc_bind_address,
     
    129124}
    130125
    131 void remote_usbhc_reserve_default_address(ddf_fun_t *fun, void *iface,
    132     ipc_callid_t callid, ipc_call_t *call)
    133 {
    134         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    135 
    136         if (!usb_iface->reserve_default_address) {
    137                 async_answer_0(callid, ENOTSUP);
    138                 return;
    139         }
    140        
    141         usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    142        
    143         int rc = usb_iface->reserve_default_address(fun, speed);
    144 
    145         async_answer_0(callid, rc);
    146 }
    147 
    148 void remote_usbhc_release_default_address(ddf_fun_t *fun, void *iface,
    149     ipc_callid_t callid, ipc_call_t *call)
    150 {
    151         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    152 
    153         if (!usb_iface->release_default_address) {
    154                 async_answer_0(callid, ENOTSUP);
    155                 return;
    156         }
    157 
    158         int rc = usb_iface->release_default_address(fun);
    159 
    160         async_answer_0(callid, rc);
    161 }
    162 
    163126void remote_usbhc_request_address(ddf_fun_t *fun, void *iface,
    164127    ipc_callid_t callid, ipc_call_t *call)
     
    270233        }
    271234
    272         size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    273235        usb_target_t target = {
    274236                .address = DEV_IPC_GET_ARG1(*call),
     
    300262        trans->size = len;
    301263
    302         rc = transfer_func(fun, target, max_packet_size,
     264        rc = transfer_func(fun, target,
    303265            buffer, len,
    304266            callback_out, trans);
     
    326288        }
    327289
    328         size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    329290        usb_target_t target = {
    330291                .address = DEV_IPC_GET_ARG1(*call),
     
    348309        trans->size = len;
    349310
    350         int rc = transfer_func(fun, target, max_packet_size,
     311        int rc = transfer_func(fun, target,
    351312            trans->buffer, len,
    352313            callback_in, trans);
     
    414375        };
    415376        size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
    416         size_t max_packet_size = DEV_IPC_GET_ARG4(*call);
    417377
    418378        int rc;
     
    450410        trans->size = data_buffer_len;
    451411
    452         rc = usb_iface->control_write(fun, target, max_packet_size,
     412        rc = usb_iface->control_write(fun, target,
    453413            setup_packet, setup_packet_len,
    454414            data_buffer, data_buffer_len,
     
    477437                .endpoint = DEV_IPC_GET_ARG2(*call)
    478438        };
    479         size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    480439
    481440        int rc;
     
    515474        }
    516475
    517         rc = usb_iface->control_read(fun, target, max_packet_size,
     476        rc = usb_iface->control_read(fun, target,
    518477            setup_packet, setup_packet_len,
    519478            trans->buffer, trans->size,
     
    537496        }
    538497
    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,
     498#define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \
     499        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)
     500#define _INIT_FROM_LOW_DATA2(type, var, arg_no) \
     501        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 16)
     502#define _INIT_FROM_HIGH_DATA3(type, var, arg_no) \
     503        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)
     504#define _INIT_FROM_MIDDLE_DATA3(type, var, arg_no) \
     505        type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) / (1 << 8)) % (1 << 8)
     506#define _INIT_FROM_LOW_DATA3(type, var, arg_no) \
     507        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8)
     508
     509        _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1);
     510        _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1);
     511
     512        _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2);
     513        _INIT_FROM_MIDDLE_DATA3(usb_transfer_type_t, transfer_type, 2);
     514        _INIT_FROM_LOW_DATA3(usb_direction_t, direction, 2);
     515
     516        _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3);
     517        _INIT_FROM_LOW_DATA2(unsigned int, interval, 3);
     518
     519#undef _INIT_FROM_HIGH_DATA2
     520#undef _INIT_FROM_LOW_DATA2
     521#undef _INIT_FROM_HIGH_DATA3
     522#undef _INIT_FROM_MIDDLE_DATA3
     523#undef _INIT_FROM_LOW_DATA3
     524
     525        int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,
    556526            transfer_type, direction, max_packet_size, interval);
    557527
  • uspace/lib/drv/include/usbhc_iface.h

    ref354b6 re50cd7f  
    6666 *   - argument #1 is target address
    6767 *   - argument #2 is target endpoint
    68  *   - argument #3 is max packet size of the endpoint
    6968 * - this call is immediately followed by IPC data read (async version)
    7069 * - the call is not answered until the device returns some data (or until
     
    8584 */
    8685typedef enum {
    87         /** Reserve usage of default address.
    88          * This call informs the host controller that the caller will be
    89          * using default USB address. It is duty of the HC driver to ensure
    90          * that only single entity will have it reserved.
    91          * The address is returned via IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS.
    92          * The caller can start using the address after receiving EOK
    93          * answer.
    94          */
    95         IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS,
    96 
    97         /** Release usage of default address.
    98          * @see IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS
    99          */
    100         IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS,
    101 
    10286        /** Asks for address assignment by host controller.
    10387         * Answer:
     
    169153        /** Register endpoint attributes at host controller.
    170154         * This is used to reserve portion of USB bandwidth.
     155         * When speed is invalid, speed of the device is used.
    171156         * Parameters:
    172          * - USB address + endpoint number (ADDR * 256 + EP)
    173          * - transfer type + direction (TYPE * 256 + DIR)
    174          * - maximum packet size
    175          * - interval (in milliseconds)
     157         * - USB address + endpoint number
     158         *   - packed as ADDR << 16 + EP
     159         * - speed + transfer type + direction
     160         *   - packed as ( SPEED << 8 + TYPE ) << 8 + DIR
     161         * - maximum packet size + interval (in milliseconds)
     162         *   - packed as MPS << 16 + INT
    176163         * Answer:
    177164         * - EOK - reservation successful
     
    202189
    203190/** Out transfer processing function prototype. */
    204 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, size_t,
     191typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t,
    205192    void *, size_t,
    206193    usbhc_iface_transfer_out_callback_t, void *);
     
    210197
    211198/** In transfer processing function prototype. */
    212 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, size_t,
     199typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t,
    213200    void *, size_t,
    214201    usbhc_iface_transfer_in_callback_t, void *);
     
    222209        int (*release_address)(ddf_fun_t *, usb_address_t);
    223210
    224         int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
     211        int (*register_endpoint)(ddf_fun_t *,
     212            usb_address_t, usb_speed_t, usb_endpoint_t,
    225213            usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
    226214        int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
     
    234222
    235223        int (*control_write)(ddf_fun_t *, usb_target_t,
    236             size_t,
    237224            void *, size_t, void *, size_t,
    238225            usbhc_iface_transfer_out_callback_t, void *);
    239226
    240227        int (*control_read)(ddf_fun_t *, usb_target_t,
    241             size_t,
    242228            void *, size_t, void *, size_t,
    243229            usbhc_iface_transfer_in_callback_t, void *);
  • uspace/lib/net/generic/generic.c

    ref354b6 re50cd7f  
    106106                return EBADMEM;
    107107
    108         // request the address
     108        /* Request the address */
    109109        message_id = async_send_1(phone, (sysarg_t) message,
    110110            (sysarg_t) device_id, NULL);
     
    112112        async_wait_for(message_id, &result);
    113113
    114         // if not successful
     114        /* If not successful */
    115115        if ((string == EOK) && (result != EOK)) {
    116                 // clear the data
     116                /* Clear the data */
    117117                free(*address);
    118118                free(*data);
     
    242242                return EBADMEM;
    243243
    244         // request the translation
     244        /* Request the translation */
    245245        message_id = async_send_3(phone, (sysarg_t) message,
    246246            (sysarg_t) device_id, (sysarg_t) count, (sysarg_t) service, NULL);
     
    249249        async_wait_for(message_id, &result);
    250250
    251         // if not successful
     251        /* If not successful */
    252252        if ((string == EOK) && (result != EOK)) {
    253                 // clear the data
     253                /* Clear the data */
    254254                free(*translation);
    255255                free(*data);
  • uspace/lib/net/generic/net_checksum.c

    ref354b6 re50cd7f  
    5252uint16_t compact_checksum(uint32_t sum)
    5353{
    54         // shorten to the 16 bits
     54        /* Shorten to the 16 bits */
    5555        while (sum >> 16)
    5656                sum = (sum & 0xffff) + (sum >> 16);
     
    7272        size_t index;
    7373
    74         // sum all the 16 bit fields
     74        /* Sum all the 16 bit fields */
    7575        for (index = 0; index + 1 < length; index += 2)
    7676                seed += (data[index] << 8) + data[index + 1];
    7777
    78         // last odd byte with zero padding
     78        /* Last odd byte with zero padding */
    7979        if (index + 1 == length)
    8080                seed += data[index] << 8;
     
    9494        size_t index;
    9595
    96         // process full bytes
     96        /* Process full bytes */
    9797        while (length >= 8) {
    98                 // add the data
     98                /* Add the data */
    9999                seed ^= (*data) << 24;
    100100               
    101                 // for each added bit
     101                /* For each added bit */
    102102                for (index = 0; index < 8; ++index) {
    103                         // if the first bit is set
     103                        /* If the first bit is set */
    104104                        if (seed & 0x80000000) {
    105                                 // shift and divide the checksum
     105                                /* Shift and divide the checksum */
    106106                                seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
    107107                        } else {
    108                                 // shift otherwise
     108                                /* Shift otherwise */
    109109                                seed <<= 1;
    110110                        }
    111111                }
    112112               
    113                 // move to the next byte
     113                /* Move to the next byte */
    114114                ++data;
    115115                length -= 8;
    116116        }
    117117
    118         // process the odd bits
     118        /* Process the odd bits */
    119119        if (length > 0) {
    120                 // add the data with zero padding
     120                /* Add the data with zero padding */
    121121                seed ^= ((*data) & (0xff << (8 - length))) << 24;
    122122               
    123                 // for each added bit
     123                /* For each added bit */
    124124                for (index = 0; index < length; ++index) {
    125                         // if the first bit is set
     125                        /* If the first bit is set */
    126126                        if (seed & 0x80000000) {
    127                                 // shift and divide the checksum
     127                                /* Shift and divide the checksum */
    128128                                seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
    129129                        } else {
    130                                 // shift otherwise
     130                                /* Shift otherwise */
    131131                                seed <<= 1;
    132132                        }
     
    148148        size_t index;
    149149
    150         // process full bytes
     150        /* Process full bytes */
    151151        while (length >= 8) {
    152                 // add the data
     152                /* Add the data */
    153153                seed ^= (*data);
    154154               
    155                 // for each added bit
     155                /* For each added bit */
    156156                for (index = 0; index < 8; ++index) {
    157                         // if the last bit is set
     157                        /* If the last bit is set */
    158158                        if (seed & 1) {
    159                                 // shift and divide the checksum
     159                                /* Shift and divide the checksum */
    160160                                seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
    161161                        } else {
    162                                 // shift otherwise
     162                                /* Shift otherwise */
    163163                                seed >>= 1;
    164164                        }
    165165                }
    166166               
    167                 // move to the next byte
     167                /* Move to the next byte */
    168168                ++data;
    169169                length -= 8;
    170170        }
    171171
    172         // process the odd bits
     172        /* Process the odd bits */
    173173        if (length > 0) {
    174                 // add the data with zero padding
     174                /* Add the data with zero padding */
    175175                seed ^= (*data) >> (8 - length);
    176176               
    177177                for (index = 0; index < length; ++index) {
    178                         // if the last bit is set
     178                        /* If the last bit is set */
    179179                        if (seed & 1) {
    180                                 // shift and divide the checksum
     180                                /* Shift and divide the checksum */
    181181                                seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
    182182                        } else {
    183                                 // shift otherwise
     183                                /* Shift otherwise */
    184184                                seed >>= 1;
    185185                        }
     
    198198uint16_t flip_checksum(uint16_t checksum)
    199199{
    200         // flip, zero is returned as 0xFFFF (not flipped)
     200        /* Flip, zero is returned as 0xFFFF (not flipped) */
    201201        checksum = ~checksum;
    202202        return checksum ? checksum : IP_CHECKSUM_ZERO;
     
    216216uint16_t ip_checksum(uint8_t *data, size_t length)
    217217{
    218         // compute, compact and flip the data checksum
     218        /* Compute, compact and flip the data checksum */
    219219        return flip_checksum(compact_checksum(compute_checksum(0, data,
    220220            length)));
  • uspace/lib/net/generic/packet_client.c

    ref354b6 re50cd7f  
    267267                return NULL;
    268268
    269         // get a new packet
     269        /* Get a new packet */
    270270        copy = packet_get_4_remote(phone, PACKET_DATA_LENGTH(packet),
    271271            PACKET_MAX_ADDRESS_LENGTH(packet), packet->max_prefix,
     
    274274                return NULL;
    275275
    276         // get addresses
     276        /* Get addresses */
    277277        addrlen = packet_get_addr(packet, &src, &dest);
    278         // copy data
     278        /* Copy data */
    279279        if ((packet_copy_data(copy, packet_get_data(packet),
    280280            PACKET_DATA_LENGTH(packet)) == EOK) &&
    281             // copy addresses if present
     281            /* Copy addresses if present */
    282282            ((addrlen <= 0) ||
    283283            (packet_set_addr(copy, src, dest, addrlen) == EOK))) {
  • uspace/lib/net/il/ip_client.c

    ref354b6 re50cd7f  
    124124
    125125        // TODO IPv6
    126 /*      case AF_INET6:
     126#if 0
     127        case AF_INET6:
    127128                if (addrlen != sizeof(struct sockaddr_in6))
    128129                        return EINVAL;
     
    130131                address_in6 = (struct sockaddr_in6 *) addr;
    131132                return EOK;
    132 */
     133#endif
    133134
    134135        default:
     
    159160        size_t padding;
    160161
    161         // compute the padding if IP options are set
    162         // multiple of 4 bytes
     162        /*
     163         * Compute the padding if IP options are set
     164         * multiple of 4 bytes
     165         */
    163166        padding =  ipopt_length % 4;
    164167        if (padding) {
     
    167170        }
    168171
    169         // prefix the header
     172        /* Prefix the header */
    170173        data = (uint8_t *) packet_prefix(packet, sizeof(ip_header_t) + padding);
    171174        if (!data)
    172175                return ENOMEM;
    173176
    174         // add the padding
     177        /* Add the padding */
    175178        while (padding--)
    176179                data[sizeof(ip_header_t) + padding] = IPOPT_NOOP;
    177180
    178         // set the header
     181        /* Set the header */
    179182        header = (ip_header_t *) data;
    180183        header->header_length = IP_COMPUTE_HEADER_LENGTH(sizeof(ip_header_t) +
  • uspace/lib/net/tl/icmp_client.c

    ref354b6 re50cd7f  
    8181                *mtu = header->un.frag.mtu;
    8282
    83         // remove debug dump
     83        /* Remove debug dump */
    8484#ifdef CONFIG_DEBUG
    8585        printf("ICMP error %d (%d) in packet %d\n", header->type, header->code,
  • uspace/lib/net/tl/socket_core.c

    ref354b6 re50cd7f  
    9191        int packet_id;
    9292
    93         // if bound
     93        /* If bound */
    9494        if (socket->port) {
    95                 // release the port
     95                /* Release the port */
    9696                socket_port_release(global_sockets, socket);
    9797        }
    9898       
    99         // release all received packets
     99        /* Release all received packets */
    100100        while ((packet_id = dyn_fifo_pop(&socket->received)) >= 0)
    101101                pq_release_remote(packet_phone, packet_id);
     
    166166        int rc;
    167167
    168         // create a wrapper
     168        /* Create a wrapper */
    169169        socket_ref = malloc(sizeof(*socket_ref));
    170170        if (!socket_ref)
     
    172172
    173173        *socket_ref = socket;
    174         // add the wrapper
     174        /* Add the wrapper */
    175175        rc = socket_port_map_add(&socket_port->map, key, key_length,
    176176            socket_ref);
     
    206206        int rc;
    207207
    208         // create a wrapper
     208        /* Create a wrapper */
    209209        socket_port = malloc(sizeof(*socket_port));
    210210        if (!socket_port)
     
    221221                goto fail;
    222222       
    223         // register the incomming port
     223        /* Register the incoming port */
    224224        rc = socket_ports_add(global_sockets, port, socket_port);
    225225        if (rc < 0)
     
    277277               
    278278                address_in = (struct sockaddr_in *) addr;
    279                 // find the socket
     279                /* Find the socket */
    280280                socket = socket_cores_find(local_sockets, socket_id);
    281281                if (!socket)
    282282                        return ENOTSOCK;
    283283               
    284                 // bind a free port?
     284                /* Bind a free port? */
    285285                if (address_in->sin_port <= 0)
    286286                        return socket_bind_free_port(global_sockets, socket,
    287287                             free_ports_start, free_ports_end, last_used_port);
    288288               
    289                 // try to find the port
     289                /* Try to find the port */
    290290                socket_port = socket_ports_find(global_sockets,
    291291                    ntohs(address_in->sin_port));
    292292                if (socket_port) {
    293                         // already used
     293                        /* Already used */
    294294                        return EADDRINUSE;
    295295                }
    296296               
    297                 // if bound
     297                /* If bound */
    298298                if (socket->port) {
    299                         // release the port
     299                        /* Release the port */
    300300                        socket_port_release(global_sockets, socket);
    301301                }
     
    333333        int index;
    334334
    335         // from the last used one
     335        /* From the last used one */
    336336        index = last_used_port;
    337337       
     
    339339                ++index;
    340340               
    341                 // til the range end
     341                /* Till the range end */
    342342                if (index >= free_ports_end) {
    343                         // start from the range beginning
     343                        /* Start from the range beginning */
    344344                        index = free_ports_start - 1;
    345345                        do {
    346346                                ++index;
    347                                 // til the last used one
     347                                /* Till the last used one */
    348348                                if (index >= last_used_port) {
    349                                         // none found
     349                                        /* None found */
    350350                                        return ENOTCONN;
    351351                                }
    352352                        } while (socket_ports_find(global_sockets, index));
    353353                       
    354                         // found, break immediately
     354                        /* Found, break immediately */
    355355                        break;
    356356                }
     
    376376
    377377        count = 0;
    378 //      socket_id = socket_globals.last_id;
     378#if 0
     379        socket_id = socket_globals.last_id;
     380#endif
    379381        do {
    380382                if (count < SOCKET_ID_TRIES) {
     
    384386                        socket_id = 1;
    385387                        ++count;
    386                 // only this branch for last_id
     388                /* Only this branch for last_id */
    387389                } else {
    388390                        if (socket_id < INT_MAX) {
    389391                                ++ socket_id;
    390 /*                      } else if(socket_globals.last_id) {
    391 *                               socket_globals.last_id = 0;
    392 *                               socket_id = 1;
    393 */                      } else {
     392#if 0
     393                        } else if(socket_globals.last_id) {
     394                                socket_globals.last_id = 0;
     395                                socket_id = 1;
     396#endif
     397                        } else {
    394398                                return ELIMIT;
    395399                        }
     
    425429                return EINVAL;
    426430       
    427         // store the socket
     431        /* Store the socket */
    428432        if (*socket_id <= 0) {
    429433                positive = (*socket_id == 0);
     
    441445                return ENOMEM;
    442446       
    443         // initialize
     447        /* Initialize */
    444448        socket->phone = app_phone;
    445449        socket->port = -1;
     
    493497        int accepted_id;
    494498
    495         // find the socket
     499        /* Find the socket */
    496500        socket = socket_cores_find(local_sockets, socket_id);
    497501        if (!socket)
    498502                return ENOTSOCK;
    499503       
    500         // destroy all accepted sockets
     504        /* Destroy all accepted sockets */
    501505        while ((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0)
    502506                socket_destroy(packet_phone, accepted_id, local_sockets,
     
    535539        next_packet = pq_next(packet);
    536540        if (!next_packet) {
    537                 // write all if only one fragment
     541                /* Write all if only one fragment */
    538542                rc = data_reply(packet_get_data(packet),
    539543                    packet_get_data_length(packet));
    540544                if (rc != EOK)
    541545                        return rc;
    542                 // store the total length
     546                /* Store the total length */
    543547                *length = packet_get_data_length(packet);
    544548        } else {
    545                 // count the packet fragments
     549                /* Count the packet fragments */
    546550                fragments = 1;
    547551                next_packet = pq_next(packet);
     
    549553                        ++fragments;
    550554               
    551                 // compute and store the fragment lengths
     555                /* Compute and store the fragment lengths */
    552556                lengths = (size_t *) malloc(sizeof(size_t) * fragments +
    553557                    sizeof(size_t));
     
    565569                }
    566570               
    567                 // write the fragment lengths
     571                /* Write the fragment lengths */
    568572                rc = data_reply(lengths, sizeof(int) * (fragments + 1));
    569573                if (rc != EOK) {
     
    573577                next_packet = packet;
    574578               
    575                 // write the fragments
     579                /* Write the fragments */
    576580                for (index = 0; index < fragments; ++index) {
    577581                        rc = data_reply(packet_get_data(next_packet),
     
    584588                }
    585589               
    586                 // store the total length
     590                /* Store the total length */
    587591                *length = lengths[fragments];
    588592                free(lengths);
     
    636640                return;
    637641       
    638         // find ports
     642        /* Find ports */
    639643        socket_port = socket_ports_find(global_sockets, socket->port);
    640644        if (socket_port) {
    641                 // find the socket
     645                /* Find the socket */
    642646                socket_ref = socket_port_map_find(&socket_port->map,
    643647                    socket->key, socket->key_length);
     
    646650                        --socket_port->count;
    647651                       
    648                         // release if empty
     652                        /* Release if empty */
    649653                        if (socket_port->count <= 0) {
    650                                 // destroy the map
     654                                /* Destroy the map */
    651655                                socket_port_map_destroy(&socket_port->map, free);
    652                                 // release the port
     656                                /* Release the port */
    653657                                socket_ports_exclude(global_sockets,
    654658                                    socket->port, free);
    655659                        } else {
    656                                 // remove
     660                                /* Remove */
    657661                                socket_port_map_exclude(&socket_port->map,
    658662                                    socket->key, socket->key_length, free);
     
    685689        int rc;
    686690
    687         // find ports
     691        /* Find ports */
    688692        socket_port = socket_ports_find(global_sockets, port);
    689693        if (!socket_port)
    690694                return ENOENT;
    691695       
    692         // add the socket
     696        /* Add the socket */
    693697        rc = socket_port_add_core(socket_port, socket, key, key_length);
    694698        if (rc != EOK)
  • uspace/lib/net/tl/tl_common.c

    ref354b6 re50cd7f  
    255255        int length;
    256256
    257         // detach the first packet and release the others
     257        /* Detach the first packet and release the others */
    258258        next = pq_detach(packet);
    259259        if (next)
     
    262262        length = packet_get_addr(packet, &src, NULL);
    263263        if ((length > 0) && (!error) && (icmp_phone >= 0) &&
    264             // set both addresses to the source one (avoids the source address
    265             // deletion before setting the destination one)
     264            /*
     265             * Set both addresses to the source one (avoids the source address
     266             * deletion before setting the destination one)
     267             */
    266268            (packet_set_addr(packet, src, src, (size_t) length) == EOK)) {
    267269                return EOK;
     
    299301                return EINVAL;
    300302
    301         // get the data length
     303        /* Get the data length */
    302304        if (!async_data_write_receive(&callid, &length))
    303305                return EINVAL;
    304306
    305         // get a new packet
     307        /* Get a new packet */
    306308        *packet = packet_get_4_remote(packet_phone, length, dimension->addr_len,
    307309            prefix + dimension->prefix, dimension->suffix);
     
    309311                return ENOMEM;
    310312
    311         // allocate space in the packet
     313        /* Allocate space in the packet */
    312314        data = packet_suffix(*packet, length);
    313315        if (!data) {
     
    316318        }
    317319
    318         // read the data into the packet
     320        /* Read the data into the packet */
    319321        rc = async_data_write_finalize(callid, data, length);
    320322        if (rc != EOK) {
     
    323325        }
    324326       
    325         // set the packet destination address
     327        /* Set the packet destination address */
    326328        rc = packet_set_addr(*packet, NULL, (uint8_t *) addr, addrlen);
    327329        if (rc != EOK) {
  • uspace/lib/packet/generic/packet_server.c

    ref354b6 re50cd7f  
    112112    size_t max_content, size_t max_suffix)
    113113{
    114         // clear the packet content
     114        /* Clear the packet content */
    115115        bzero(((void *) packet) + sizeof(packet_t),
    116116            packet->length - sizeof(packet_t));
    117117       
    118         // clear the packet header
     118        /* Clear the packet header */
    119119        packet->order = 0;
    120120        packet->metric = 0;
     
    151151        assert(fibril_mutex_is_locked(&ps_globals.lock));
    152152
    153         // already locked
     153        /* Already locked */
    154154        packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE,
    155155            MAP_SHARED | MAP_ANONYMOUS, 0, 0);
  • uspace/lib/softint/generic/multiplication.c

    ref354b6 re50cd7f  
    109109         * result does not fit in signed one */
    110110        if (SOFTINT_CHECK_OF && ((t2 < t1) || (t2 & (1ull << 63)))) {
    111                 // error, overflow
     111                /* Error, overflow */
    112112                return (neg ? INT64_MIN : INT64_MAX);
    113113        }
  • uspace/lib/usb/Makefile

    ref354b6 re50cd7f  
    3434SOURCES = \
    3535        src/addrkeep.c \
     36        src/altiface.c \
    3637        src/class.c \
    3738        src/ddfiface.c \
     
    4142        src/dp.c \
    4243        src/dump.c \
     44        src/hidiface.c \
    4345        src/hidparser.c \
    4446        src/hub.c \
     47        src/pipepriv.c \
    4548        src/pipes.c \
    4649        src/pipesinit.c \
  • uspace/lib/usb/include/usb/classes/hidparser.h

    ref354b6 re50cd7f  
    317317usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);
    318318
     319usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, usb_hid_report_type_t type);
    319320
    320321/*
  • uspace/lib/usb/include/usb/classes/hub.h

    ref354b6 re50cd7f  
    4343 */
    4444typedef enum {
     45        USB_HUB_FEATURE_HUB_LOCAL_POWER = 0,
     46        USB_HUB_FEATURE_HUB_OVER_CURRENT = 1,
    4547        USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0,
    4648        USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1,
     
    5961        /* USB_HUB_FEATURE_ = , */
    6062} usb_hub_class_feature_t;
     63
    6164
    6265/** Header of standard hub descriptor without the "variadic" part. */
     
    149152            maximum of 255 ports).
    150153     */
    151     uint8_t * devices_removable;
     154    uint8_t devices_removable[32];
    152155
    153156    /**
  • uspace/lib/usb/include/usb/devdrv.h

    ref354b6 re50cd7f  
    162162    usb_endpoint_description_t **);
    163163
    164 typedef bool (*usb_polling_callback_t)(usb_device_t *,
    165     uint8_t *, size_t, void *);
    166 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *);
     164int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
     165int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *,
     166    usb_endpoint_description_t **, uint8_t *, size_t, int, int,
     167    usb_endpoint_mapping_t **, size_t *);
     168int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
     169int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **);
    167170
    168 int usb_device_auto_poll(usb_device_t *, size_t,
    169     usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
     171size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t);
     172int usb_alternate_interfaces_create(uint8_t *, size_t, int,
     173    usb_alternate_interfaces_t **);
    170174
    171175#endif
  • uspace/lib/usb/include/usb/host/batch.h

    ref354b6 re50cd7f  
    4343typedef struct usb_transfer_batch usb_transfer_batch_t;
    4444struct usb_transfer_batch {
     45        endpoint_t *ep;
    4546        link_t link;
    46         usb_target_t target;
    47         usb_transfer_type_t transfer_type;
    48         usb_speed_t speed;
    49         usb_direction_t direction;
    5047        usbhc_iface_transfer_in_callback_t callback_in;
    5148        usbhc_iface_transfer_out_callback_t callback_out;
     49        void *arg;
    5250        char *buffer;
    53         char *transport_buffer;
     51        char *data_buffer;
    5452        size_t buffer_size;
    5553        char *setup_buffer;
    5654        size_t setup_size;
    57         size_t max_packet_size;
    5855        size_t transfered_size;
    5956        void (*next_step)(usb_transfer_batch_t *);
    6057        int error;
    6158        ddf_fun_t *fun;
    62         void *arg;
    63         endpoint_t *ep;
    6459        void *private_data;
     60        void (*private_data_dtor)(void *p_data);
    6561};
    6662
    6763void usb_transfer_batch_init(
    6864    usb_transfer_batch_t *instance,
    69     usb_target_t target,
    70     usb_transfer_type_t transfer_type,
    71     usb_speed_t speed,
    72     size_t max_packet_size,
     65    endpoint_t *ep,
    7366    char *buffer,
    74     char *transport_buffer,
     67    char *data_buffer,
    7568    size_t buffer_size,
    7669    char *setup_buffer,
     
    8073    void *arg,
    8174    ddf_fun_t *fun,
    82                 endpoint_t *ep,
    83     void *private_data
     75    void *private_data,
     76    void (*private_data_dtor)(void *p_data)
    8477);
     78
     79void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance);
     80void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance);
     81void usb_transfer_batch_finish(usb_transfer_batch_t *instance);
     82void usb_transfer_batch_dispose(usb_transfer_batch_t *instance);
     83
     84static inline void usb_transfer_batch_finish_error(
     85    usb_transfer_batch_t *instance, int error)
     86{
     87        assert(instance);
     88        instance->error = error;
     89        usb_transfer_batch_finish(instance);
     90}
    8591
    8692static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
     
    9096}
    9197
    92 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
    93 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
    94 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error);
    95 
    9698#endif
    9799/**
  • uspace/lib/usb/include/usb/host/device_keeper.h

    ref354b6 re50cd7f  
    5454        usb_speed_t speed;
    5555        bool occupied;
    56         link_t endpoints;
    57         uint16_t control_used;
    5856        devman_handle_t handle;
    5957};
     
    6563        struct usb_device_info devices[USB_ADDRESS_COUNT];
    6664        fibril_mutex_t guard;
    67         fibril_condvar_t change;
    6865        usb_address_t last_address;
    6966} usb_device_keeper_t;
    7067
    7168void usb_device_keeper_init(usb_device_keeper_t *instance);
    72 
    73 void usb_device_keeper_add_ep(
    74     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);
    75 
    76 void usb_device_keeper_reserve_default_address(
    77     usb_device_keeper_t *instance, usb_speed_t speed);
    78 
    79 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance);
    80 
    81 void usb_device_keeper_reset_if_need(usb_device_keeper_t *instance,
    82     usb_target_t target, const uint8_t *setup_data);
    8369
    8470usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,
     
    9682usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance,
    9783    usb_address_t address);
    98 
    99 void usb_device_keeper_use_control(usb_device_keeper_t *instance,
    100     usb_target_t target);
    101 
    102 void usb_device_keeper_release_control(usb_device_keeper_t *instance,
    103     usb_target_t target);
    104 
    10584#endif
    10685/**
  • uspace/lib/usb/include/usb/host/endpoint.h

    ref354b6 re50cd7f  
    3939#include <bool.h>
    4040#include <adt/list.h>
     41#include <fibril_synch.h>
     42
    4143#include <usb/usb.h>
    4244
     
    4850        usb_speed_t speed;
    4951        size_t max_packet_size;
    50         bool active;
    5152        unsigned toggle:1;
    52         link_t same_device_eps;
     53        fibril_mutex_t guard;
     54        fibril_condvar_t avail;
     55        volatile bool active;
     56        struct {
     57                void *data;
     58                int (*toggle_get)(void *);
     59                void (*toggle_set)(void *, int);
     60        } hc_data;
    5361} endpoint_t;
    5462
     
    5967void endpoint_destroy(endpoint_t *instance);
    6068
     69void endpoint_set_hc_data(endpoint_t *instance,
     70    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
     71
     72void endpoint_clear_hc_data(endpoint_t *instance);
     73
     74void endpoint_use(endpoint_t *instance);
     75
     76void endpoint_release(endpoint_t *instance);
     77
    6178int endpoint_toggle_get(endpoint_t *instance);
    6279
    6380void endpoint_toggle_set(endpoint_t *instance, int toggle);
    6481
    65 void endpoint_toggle_reset(link_t *ep);
    66 
    67 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn);
    68 
     82void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target);
    6983#endif
    7084/**
  • uspace/lib/usb/include/usb/host/usb_endpoint_manager.h

    ref354b6 re50cd7f  
    6666    endpoint_t *ep, size_t data_size);
    6767
    68 int usb_endpoint_manager_register_ep_wait(usb_endpoint_manager_t *instance,
    69     usb_address_t address, usb_endpoint_t ep, usb_direction_t direction,
    70     void *data, void (*data_remove_callback)(void* data, void* arg), void *arg,
    71     size_t bw);
    72 
    7368int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance,
    7469    usb_address_t address, usb_endpoint_t ep, usb_direction_t direction);
     
    7873    size_t *bw);
    7974
     75void usb_endpoint_manager_reset_if_need(
     76    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
     77
     78static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
     79    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
     80    usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size,
     81    size_t data_size)
     82{
     83        endpoint_t *ep = malloc(sizeof(endpoint_t));
     84        if (ep == NULL)
     85                return ENOMEM;
     86
     87        int ret = endpoint_init(ep, address, endpoint, direction, type, speed,
     88            max_packet_size);
     89        if (ret != EOK) {
     90                free(ep);
     91                return ret;
     92        }
     93
     94        ret = usb_endpoint_manager_register_ep(instance, ep, data_size);
     95        if (ret != EOK) {
     96                endpoint_destroy(ep);
     97                return ret;
     98        }
     99        return EOK;
     100}
    80101#endif
    81102/**
  • uspace/lib/usb/include/usb/hub.h

    ref354b6 re50cd7f  
    5959} usb_hc_attached_device_t;
    6060
    61 int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t);
    62 int usb_hc_release_default_address(usb_hc_connection_t *);
    63 
    6461usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
    6562int usb_hc_register_device(usb_hc_connection_t *,
  • uspace/lib/usb/include/usb/pipes.h

    ref354b6 re50cd7f  
    4242#include <ipc/devman.h>
    4343#include <ddf/driver.h>
     44#include <fibril_synch.h>
    4445
    4546/** Abstraction of a physical connection to the device.
     
    5960 * This endpoint must be bound with existing usb_device_connection_t
    6061 * (i.e. the wire to send data over).
     62 *
     63 * Locking order: if you want to lock both mutexes
     64 * (@c guard and @c hc_phone_mutex), lock @c guard first.
     65 * It is not necessary to lock @c guard if you want to lock @c hc_phone_mutex
     66 * only.
    6167 */
    6268typedef struct {
     69        /** Guard of the whole pipe. */
     70        fibril_mutex_t guard;
     71
    6372        /** The connection used for sending the data. */
    6473        usb_device_connection_t *wire;
     
    7887        /** Phone to the host controller.
    7988         * Negative when no session is active.
     89         * It is an error to access this member without @c hc_phone_mutex
     90         * being locked.
     91         * If call over the phone is to be made, it must be preceeded by
     92         * call to pipe_add_ref() [internal libusb function].
    8093         */
    8194        int hc_phone;
     95
     96        /** Guard for serialization of requests over the phone. */
     97        fibril_mutex_t hc_phone_mutex;
     98
     99        /** Number of active transfers over the pipe. */
     100        int refcount;
     101
     102        /** Whether to automatically reset halt on the endpoint.
     103         * Valid only for control endpoint zero.
     104         */
     105        bool auto_reset_halt;
    82106} usb_pipe_t;
    83107
     
    134158int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    135159    size_t, uint8_t *, size_t, usb_device_connection_t *);
     160int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t,
     161    unsigned int, usb_hc_connection_t *);
    136162int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);
    137163int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
     
    140166int usb_pipe_end_session(usb_pipe_t *);
    141167bool usb_pipe_is_session_started(usb_pipe_t *);
     168
     169int usb_pipe_start_long_transfer(usb_pipe_t *);
     170void usb_pipe_end_long_transfer(usb_pipe_t *);
    142171
    143172int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *);
  • uspace/lib/usb/include/usb/request.h

    ref354b6 re50cd7f  
    5050/** USB endpoint status - endpoint is halted (stalled). */
    5151#define USB_ENDPOINT_STATUS_HALTED ((uint16_t)(1 << 0))
     52
     53/** USB feature selector - endpoint halt (stall). */
     54#define USB_FEATURE_SELECTOR_ENDPOINT_HALT (0)
     55
     56/** USB feature selector - device remote wake-up. */
     57#define USB_FEATURE_SELECTOR_REMOTE_WAKEUP (1)
    5258
    5359/** Standard device request. */
     
    135141    char **);
    136142
     143int usb_request_clear_endpoint_halt(usb_pipe_t *, uint16_t);
     144
    137145#endif
    138146/**
  • uspace/lib/usb/include/usb/usb.h

    ref354b6 re50cd7f  
    7777        USB_SPEED_FULL,
    7878        /** USB 2.0 high speed (480Mbits/s). */
    79         USB_SPEED_HIGH
     79        USB_SPEED_HIGH,
     80        /** Psuedo-speed serving as a boundary. */
     81        USB_SPEED_MAX
    8082} usb_speed_t;
    8183
  • uspace/lib/usb/src/devdrv.c

    ref354b6 re50cd7f  
    7272}
    7373
    74 /** Log out of memory error on given device.
    75  *
    76  * @param dev Device causing the trouble.
    77  */
    78 static void usb_log_oom(ddf_dev_t *dev)
    79 {
    80         usb_log_error("Out of memory when adding device `%s'.\n",
    81             dev->name);
    82 }
    83 
    8474/** Count number of pipes the driver expects.
    8575 *
     
    10898 */
    10999static int initialize_other_pipes(usb_endpoint_description_t **endpoints,
    110     usb_device_t *dev)
    111 {
    112         int rc;
    113 
    114         size_t pipe_count = count_other_pipes(endpoints);
    115         if (pipe_count == 0) {
     100    usb_device_t *dev, int alternate_setting)
     101{
     102        if (endpoints == NULL) {
     103                dev->pipes = NULL;
     104                dev->pipes_count = 0;
    116105                return EOK;
    117106        }
    118107
    119         dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
    120         if (dev->pipes == NULL) {
    121                 usb_log_oom(dev->ddf_dev);
    122                 return ENOMEM;
    123         }
    124 
    125         size_t i;
    126 
    127         /* Initialize to NULL first for rollback purposes. */
    128         for (i = 0; i < pipe_count; i++) {
    129                 dev->pipes[i].pipe = NULL;
    130         }
    131 
    132         for (i = 0; i < pipe_count; i++) {
    133                 dev->pipes[i].pipe = malloc(sizeof(usb_pipe_t));
    134                 if (dev->pipes[i].pipe == NULL) {
    135                         usb_log_oom(dev->ddf_dev);
    136                         rc = ENOMEM;
    137                         goto rollback;
    138                 }
    139 
    140                 dev->pipes[i].description = endpoints[i];
    141                 dev->pipes[i].interface_no = dev->interface_no;
    142                 dev->pipes[i].interface_setting = 0;
    143         }
    144 
    145         rc = usb_pipe_initialize_from_configuration(dev->pipes, pipe_count,
     108        usb_endpoint_mapping_t *pipes;
     109        size_t pipes_count;
     110
     111        int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints,
    146112            dev->descriptors.configuration, dev->descriptors.configuration_size,
    147             &dev->wire);
    148         if (rc != EOK) {
    149                 usb_log_error("Failed initializing USB endpoints: %s.\n",
    150                     str_error(rc));
    151                 goto rollback;
    152         }
    153 
    154         /* Register the endpoints. */
    155         usb_hc_connection_t hc_conn;
    156         rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev);
    157         if (rc != EOK) {
    158                 usb_log_error(
    159                     "Failed initializing connection to host controller: %s.\n",
    160                     str_error(rc));
    161                 goto rollback;
    162         }
    163         rc = usb_hc_connection_open(&hc_conn);
    164         if (rc != EOK) {
    165                 usb_log_error("Failed to connect to host controller: %s.\n",
    166                     str_error(rc));
    167                 goto rollback;
    168         }
    169         for (i = 0; i < pipe_count; i++) {
    170                 if (dev->pipes[i].present) {
    171                         rc = usb_pipe_register(dev->pipes[i].pipe,
    172                             dev->pipes[i].descriptor->poll_interval,
    173                             &hc_conn);
    174                         /* Ignore error when operation not supported by HC. */
    175                         if ((rc != EOK) && (rc != ENOTSUP)) {
    176                                 /* FIXME: what shall we do? */
    177                                 dev->pipes[i].present = false;
    178                                 free(dev->pipes[i].pipe);
    179                                 dev->pipes[i].pipe = NULL;
    180                         }
    181                 }
    182         }
    183         /* Ignoring errors here. */
    184         usb_hc_connection_close(&hc_conn);
    185 
    186         dev->pipes_count = pipe_count;
    187 
    188         return EOK;
    189 
    190 rollback:
    191         for (i = 0; i < pipe_count; i++) {
    192                 if (dev->pipes[i].pipe != NULL) {
    193                         free(dev->pipes[i].pipe);
    194                 }
    195         }
    196         free(dev->pipes);
    197 
    198         return rc;
    199 }
    200 
    201 /** Initialize all endpoint pipes.
    202  *
    203  * @param drv The driver.
    204  * @param dev The device to be initialized.
    205  * @return Error code.
    206  */
    207 static int initialize_pipes(usb_device_t *dev)
    208 {
    209         int rc;
    210 
    211         rc = usb_device_connection_initialize_from_device(&dev->wire,
    212             dev->ddf_dev);
    213         if (rc != EOK) {
    214                 usb_log_error(
    215                     "Failed initializing connection on device `%s'. %s.\n",
    216                     dev->ddf_dev->name, str_error(rc));
    217                 return rc;
    218         }
    219 
    220         rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
    221             &dev->wire);
    222         if (rc != EOK) {
    223                 usb_log_error("Failed to initialize default control pipe " \
    224                     "on device `%s': %s.\n",
    225                     dev->ddf_dev->name, str_error(rc));
    226                 return rc;
    227         }
    228 
    229         rc = usb_pipe_probe_default_control(&dev->ctrl_pipe);
    230         if (rc != EOK) {
    231                 usb_log_error(
    232                     "Probing default control pipe on device `%s' failed: %s.\n",
    233                     dev->ddf_dev->name, str_error(rc));
    234                 return rc;
    235         }
    236 
    237         /* Get our interface. */
    238         dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
    239 
    240         /*
    241          * For further actions, we need open session on default control pipe.
    242          */
    243         rc = usb_pipe_start_session(&dev->ctrl_pipe);
    244         if (rc != EOK) {
    245                 usb_log_error("Failed to start an IPC session: %s.\n",
    246                     str_error(rc));
    247                 return rc;
    248         }
    249 
    250         /* Get the device descriptor. */
    251         rc = usb_request_get_device_descriptor(&dev->ctrl_pipe,
    252             &dev->descriptors.device);
    253         if (rc != EOK) {
    254                 usb_log_error("Failed to retrieve device descriptor: %s.\n",
    255                     str_error(rc));
    256                 return rc;
    257         }
    258 
    259         /* Get the full configuration descriptor. */
    260         rc = usb_request_get_full_configuration_descriptor_alloc(
    261             &dev->ctrl_pipe, 0, (void **) &dev->descriptors.configuration,
    262             &dev->descriptors.configuration_size);
    263         if (rc != EOK) {
    264                 usb_log_error("Failed retrieving configuration descriptor: %s. %s\n",
    265                     dev->ddf_dev->name, str_error(rc));
    266                 return rc;
    267         }
    268 
    269         if (driver->endpoints != NULL) {
    270                 rc = initialize_other_pipes(driver->endpoints, dev);
    271         }
    272 
    273         /* No checking here. */
    274         usb_pipe_end_session(&dev->ctrl_pipe);
    275 
    276         /* Rollback actions. */
    277         if (rc != EOK) {
    278                 if (dev->descriptors.configuration != NULL) {
    279                         free(dev->descriptors.configuration);
    280                 }
    281         }
    282 
    283         return rc;
    284 }
    285 
    286 /** Count number of alternate settings of a interface.
    287  *
    288  * @param config_descr Full configuration descriptor.
    289  * @param config_descr_size Size of @p config_descr in bytes.
    290  * @param interface_no Interface number.
    291  * @return Number of alternate interfaces for @p interface_no interface.
    292  */
    293 static size_t count_alternate_interfaces(uint8_t *config_descr,
    294     size_t config_descr_size, int interface_no)
    295 {
    296         assert(config_descr != NULL);
    297         usb_dp_parser_t dp_parser = {
    298                 .nesting = usb_dp_standard_descriptor_nesting
    299         };
    300         usb_dp_parser_data_t dp_data = {
    301                 .data = config_descr,
    302                 .size = config_descr_size,
    303                 .arg = NULL
    304         };
    305 
    306         size_t alternate_count = 0;
    307 
    308         uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
    309             &dp_data, config_descr);
    310         while (iface_ptr != NULL) {
    311                 usb_standard_interface_descriptor_t *iface
    312                     = (usb_standard_interface_descriptor_t *) iface_ptr;
    313                 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) {
    314                         if (iface->interface_number == interface_no) {
    315                                 alternate_count++;
    316                         }
    317                 }
    318                 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
    319                     config_descr, iface_ptr);
    320         }
    321 
    322         return alternate_count;
    323 }
    324 
    325 /** Initialize structures related to alternate interfaces.
    326  *
    327  * @param dev Device where alternate settings shall be initialized.
    328  * @return Error code.
    329  */
    330 static int initialize_alternate_interfaces(usb_device_t *dev)
    331 {
    332         if (dev->interface_no < 0) {
    333                 dev->alternate_interfaces = NULL;
    334                 return EOK;
    335         }
    336 
    337         usb_alternate_interfaces_t *alternates
    338             = malloc(sizeof(usb_alternate_interfaces_t));
    339 
    340         if (alternates == NULL) {
    341                 return ENOMEM;
    342         }
    343 
    344         alternates->alternative_count
    345             = count_alternate_interfaces(dev->descriptors.configuration,
    346             dev->descriptors.configuration_size, dev->interface_no);
    347 
    348         if (alternates->alternative_count == 0) {
    349                 free(alternates);
    350                 return ENOENT;
    351         }
    352 
    353         alternates->alternatives = malloc(alternates->alternative_count
    354             * sizeof(usb_alternate_interface_descriptors_t));
    355         if (alternates->alternatives == NULL) {
    356                 free(alternates);
    357                 return ENOMEM;
    358         }
    359 
    360         alternates->current = 0;
    361 
    362         usb_dp_parser_t dp_parser = {
    363                 .nesting = usb_dp_standard_descriptor_nesting
    364         };
    365         usb_dp_parser_data_t dp_data = {
    366                 .data = dev->descriptors.configuration,
    367                 .size = dev->descriptors.configuration_size,
    368                 .arg = NULL
    369         };
    370 
    371         usb_alternate_interface_descriptors_t *cur_alt_iface
    372             = &alternates->alternatives[0];
    373 
    374         uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
    375             &dp_data, dp_data.data);
    376         while (iface_ptr != NULL) {
    377                 usb_standard_interface_descriptor_t *iface
    378                     = (usb_standard_interface_descriptor_t *) iface_ptr;
    379                 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE)
    380                     || (iface->interface_number != dev->interface_no)) {
    381                         iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
    382                             &dp_data,
    383                             dp_data.data, iface_ptr);
    384                         continue;
    385                 }
    386 
    387                 cur_alt_iface->interface = iface;
    388                 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);
    389 
    390                 /* Find next interface to count size of nested descriptors. */
    391                 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
    392                     dp_data.data, iface_ptr);
    393                 if (iface_ptr == NULL) {
    394                         uint8_t *next = dp_data.data + dp_data.size;
    395                         cur_alt_iface->nested_descriptors_size
    396                             = next - cur_alt_iface->nested_descriptors;
    397                 } else {
    398                         cur_alt_iface->nested_descriptors_size
    399                             = iface_ptr - cur_alt_iface->nested_descriptors;
    400                 }
    401 
    402                 cur_alt_iface++;
    403         }
    404 
    405         dev->alternate_interfaces = alternates;
     113            dev->interface_no, alternate_setting,
     114            &pipes, &pipes_count);
     115
     116        if (rc != EOK) {
     117                return rc;
     118        }
     119
     120        dev->pipes = pipes;
     121        dev->pipes_count = pipes_count;
    406122
    407123        return EOK;
     
    423139        int rc;
    424140
    425         usb_device_t *dev = malloc(sizeof(usb_device_t));
    426         if (dev == NULL) {
    427                 usb_log_error("Out of memory when adding device `%s'.\n",
    428                     gen_dev->name);
    429                 return ENOMEM;
    430         }
    431 
    432 
    433         dev->ddf_dev = gen_dev;
    434         dev->ddf_dev->driver_data = dev;
    435         dev->driver_data = NULL;
    436         dev->descriptors.configuration = NULL;
    437 
    438         dev->pipes_count = 0;
    439         dev->pipes = NULL;
    440 
    441         rc = initialize_pipes(dev);
    442         if (rc != EOK) {
    443                 free(dev);
    444                 return rc;
    445         }
    446 
    447         (void) initialize_alternate_interfaces(dev);
     141        usb_device_t *dev = NULL;
     142        const char *err_msg = NULL;
     143        rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg);
     144        if (rc != EOK) {
     145                usb_log_error("USB device `%s' creation failed (%s): %s.\n",
     146                    gen_dev->name, err_msg, str_error(rc));
     147                return rc;
     148        }
    448149
    449150        return driver->ops->add_device(dev);
     
    457158static int destroy_current_pipes(usb_device_t *dev)
    458159{
    459         size_t i;
    460         int rc;
    461 
    462         /* TODO: this shall be done under some device mutex. */
    463 
    464         /* First check that no session is opened. */
    465         for (i = 0; i < dev->pipes_count; i++) {
    466                 if (usb_pipe_is_session_started(dev->pipes[i].pipe)) {
    467                         return EBUSY;
    468                 }
    469         }
    470 
    471         /* Prepare connection to HC. */
    472         usb_hc_connection_t hc_conn;
    473         rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev);
    474         if (rc != EOK) {
    475                 return rc;
    476         }
    477         rc = usb_hc_connection_open(&hc_conn);
    478         if (rc != EOK) {
    479                 return rc;
    480         }
    481 
    482         /* Destroy the pipes. */
    483         for (i = 0; i < dev->pipes_count; i++) {
    484                 usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn);
    485                 free(dev->pipes[i].pipe);
    486         }
    487 
    488         usb_hc_connection_close(&hc_conn);
    489 
    490         free(dev->pipes);
     160        int rc = usb_device_destroy_pipes(dev->ddf_dev,
     161            dev->pipes, dev->pipes_count);
     162        if (rc != EOK) {
     163                return rc;
     164        }
     165
    491166        dev->pipes = NULL;
    492167        dev->pipes_count = 0;
     
    505180 * with usb_pipe_initialize_from_configuration().
    506181 *
     182 * @warning This is a wrapper function that does several operations that
     183 * can fail and that cannot be rollbacked easily. That means that a failure
     184 * during the SET_INTERFACE request would result in having a device with
     185 * no pipes at all (except the default control one). That is because the old
     186 * pipes needs to be unregistered at HC first and the new ones could not
     187 * be created.
     188 *
    507189 * @param dev USB device.
    508190 * @param alternate_setting Alternate setting to choose.
     
    519201        int rc;
    520202
    521         /* TODO: more transactional behavior. */
    522 
    523203        /* Destroy existing pipes. */
    524204        rc = destroy_current_pipes(dev);
     
    535215
    536216        /* Create new pipes. */
    537         rc = initialize_other_pipes(endpoints, dev);
     217        rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting);
    538218
    539219        return rc;
     220}
     221
     222/** Retrieve basic descriptors from the device.
     223 *
     224 * @param[in] ctrl_pipe Control endpoint pipe.
     225 * @param[out] descriptors Where to store the descriptors.
     226 * @return Error code.
     227 */
     228int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe,
     229    usb_device_descriptors_t *descriptors)
     230{
     231        assert(descriptors != NULL);
     232
     233        descriptors->configuration = NULL;
     234
     235        int rc;
     236
     237        /* It is worth to start a long transfer. */
     238        rc = usb_pipe_start_long_transfer(ctrl_pipe);
     239        if (rc != EOK) {
     240                return rc;
     241        }
     242
     243        /* Get the device descriptor. */
     244        rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);
     245        if (rc != EOK) {
     246                goto leave;
     247        }
     248
     249        /* Get the full configuration descriptor. */
     250        rc = usb_request_get_full_configuration_descriptor_alloc(
     251            ctrl_pipe, 0, (void **) &descriptors->configuration,
     252            &descriptors->configuration_size);
     253
     254leave:
     255        usb_pipe_end_long_transfer(ctrl_pipe);
     256
     257        return rc;
     258}
     259
     260/** Create pipes for a device.
     261 *
     262 * This is more or less a wrapper that does following actions:
     263 * - allocate and initialize pipes
     264 * - map endpoints to the pipes based on the descriptions
     265 * - registers endpoints with the host controller
     266 *
     267 * @param[in] dev Generic DDF device backing the USB one.
     268 * @param[in] wire Initialized backing connection to the host controller.
     269 * @param[in] endpoints Endpoints description, NULL terminated.
     270 * @param[in] config_descr Configuration descriptor of active configuration.
     271 * @param[in] config_descr_size Size of @p config_descr in bytes.
     272 * @param[in] interface_no Interface to map from.
     273 * @param[in] interface_setting Interface setting (default is usually 0).
     274 * @param[out] pipes_ptr Where to store array of created pipes
     275 *      (not NULL terminated).
     276 * @param[out] pipes_count_ptr Where to store number of pipes
     277 *      (set to if you wish to ignore the count).
     278 * @return Error code.
     279 */
     280int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire,
     281    usb_endpoint_description_t **endpoints,
     282    uint8_t *config_descr, size_t config_descr_size,
     283    int interface_no, int interface_setting,
     284    usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
     285{
     286        assert(dev != NULL);
     287        assert(wire != NULL);
     288        assert(endpoints != NULL);
     289        assert(config_descr != NULL);
     290        assert(config_descr_size > 0);
     291        assert(pipes_ptr != NULL);
     292
     293        size_t i;
     294        int rc;
     295
     296        size_t pipe_count = count_other_pipes(endpoints);
     297        if (pipe_count == 0) {
     298                *pipes_ptr = NULL;
     299                return EOK;
     300        }
     301
     302        usb_endpoint_mapping_t *pipes
     303            = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
     304        if (pipes == NULL) {
     305                return ENOMEM;
     306        }
     307
     308        /* Initialize to NULL to allow smooth rollback. */
     309        for (i = 0; i < pipe_count; i++) {
     310                pipes[i].pipe = NULL;
     311        }
     312
     313        /* Now allocate and fully initialize. */
     314        for (i = 0; i < pipe_count; i++) {
     315                pipes[i].pipe = malloc(sizeof(usb_pipe_t));
     316                if (pipes[i].pipe == NULL) {
     317                        rc = ENOMEM;
     318                        goto rollback_free_only;
     319                }
     320                pipes[i].description = endpoints[i];
     321                pipes[i].interface_no = interface_no;
     322                pipes[i].interface_setting = interface_setting;
     323        }
     324
     325        /* Find the mapping from configuration descriptor. */
     326        rc = usb_pipe_initialize_from_configuration(pipes, pipe_count,
     327            config_descr, config_descr_size, wire);
     328        if (rc != EOK) {
     329                goto rollback_free_only;
     330        }
     331
     332        /* Register the endpoints with HC. */
     333        usb_hc_connection_t hc_conn;
     334        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     335        if (rc != EOK) {
     336                goto rollback_free_only;
     337        }
     338
     339        rc = usb_hc_connection_open(&hc_conn);
     340        if (rc != EOK) {
     341                goto rollback_free_only;
     342        }
     343
     344        for (i = 0; i < pipe_count; i++) {
     345                if (pipes[i].present) {
     346                        rc = usb_pipe_register(pipes[i].pipe,
     347                            pipes[i].descriptor->poll_interval, &hc_conn);
     348                        if (rc != EOK) {
     349                                goto rollback_unregister_endpoints;
     350                        }
     351                }
     352        }
     353
     354        usb_hc_connection_close(&hc_conn);
     355
     356        *pipes_ptr = pipes;
     357        if (pipes_count_ptr != NULL) {
     358                *pipes_count_ptr = pipe_count;
     359        }
     360
     361        return EOK;
     362
     363        /*
     364         * Jump here if something went wrong after endpoints have
     365         * been registered.
     366         * This is also the target when the registration of
     367         * endpoints fails.
     368         */
     369rollback_unregister_endpoints:
     370        for (i = 0; i < pipe_count; i++) {
     371                if (pipes[i].present) {
     372                        usb_pipe_unregister(pipes[i].pipe, &hc_conn);
     373                }
     374        }
     375
     376        usb_hc_connection_close(&hc_conn);
     377
     378        /*
     379         * Jump here if something went wrong before some actual communication
     380         * with HC. Then the only thing that needs to be done is to free
     381         * allocated memory.
     382         */
     383rollback_free_only:
     384        for (i = 0; i < pipe_count; i++) {
     385                if (pipes[i].pipe != NULL) {
     386                        free(pipes[i].pipe);
     387                }
     388        }
     389        free(pipes);
     390
     391        return rc;
     392}
     393
     394/** Destroy pipes previously created by usb_device_create_pipes.
     395 *
     396 * @param[in] dev Generic DDF device backing the USB one.
     397 * @param[in] pipes Endpoint mapping to be destroyed.
     398 * @param[in] pipes_count Number of endpoints.
     399 */
     400int usb_device_destroy_pipes(ddf_dev_t *dev,
     401    usb_endpoint_mapping_t *pipes, size_t pipes_count)
     402{
     403        assert(dev != NULL);
     404        assert(((pipes != NULL) && (pipes_count > 0))
     405            || ((pipes == NULL) && (pipes_count == 0)));
     406
     407        if (pipes_count == 0) {
     408                return EOK;
     409        }
     410
     411        int rc;
     412
     413        /* Prepare connection to HC to allow endpoint unregistering. */
     414        usb_hc_connection_t hc_conn;
     415        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     416        if (rc != EOK) {
     417                return rc;
     418        }
     419        rc = usb_hc_connection_open(&hc_conn);
     420        if (rc != EOK) {
     421                return rc;
     422        }
     423
     424        /* Destroy the pipes. */
     425        size_t i;
     426        for (i = 0; i < pipes_count; i++) {
     427                usb_pipe_unregister(pipes[i].pipe, &hc_conn);
     428                free(pipes[i].pipe);
     429        }
     430
     431        usb_hc_connection_close(&hc_conn);
     432
     433        free(pipes);
     434
     435        return EOK;
     436}
     437
     438/** Initialize control pipe in a device.
     439 *
     440 * @param dev USB device in question.
     441 * @param errmsg Where to store error context.
     442 * @return
     443 */
     444static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)
     445{
     446        int rc;
     447
     448        rc = usb_device_connection_initialize_from_device(&dev->wire,
     449            dev->ddf_dev);
     450        if (rc != EOK) {
     451                *errmsg = "device connection initialization";
     452                return rc;
     453        }
     454
     455        rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
     456            &dev->wire);
     457        if (rc != EOK) {
     458                *errmsg = "default control pipe initialization";
     459                return rc;
     460        }
     461
     462        return EOK;
     463}
     464
     465
     466/** Create new instance of USB device.
     467 *
     468 * @param[in] ddf_dev Generic DDF device backing the USB one.
     469 * @param[in] endpoints NULL terminated array of endpoints (NULL for none).
     470 * @param[out] dev_ptr Where to store pointer to the new device.
     471 * @param[out] errstr_ptr Where to store description of context
     472 *      (in case error occurs).
     473 * @return Error code.
     474 */
     475int usb_device_create(ddf_dev_t *ddf_dev,
     476    usb_endpoint_description_t **endpoints,
     477    usb_device_t **dev_ptr, const char **errstr_ptr)
     478{
     479        assert(dev_ptr != NULL);
     480        assert(ddf_dev != NULL);
     481
     482        int rc;
     483
     484        usb_device_t *dev = malloc(sizeof(usb_device_t));
     485        if (dev == NULL) {
     486                *errstr_ptr = "structure allocation";
     487                return ENOMEM;
     488        }
     489
     490        // FIXME: proper deallocation in case of errors
     491
     492        dev->ddf_dev = ddf_dev;
     493        dev->driver_data = NULL;
     494        dev->descriptors.configuration = NULL;
     495        dev->alternate_interfaces = NULL;
     496
     497        dev->pipes_count = 0;
     498        dev->pipes = NULL;
     499
     500        /* Initialize backing wire and control pipe. */
     501        rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);
     502        if (rc != EOK) {
     503                return rc;
     504        }
     505
     506        /* Get our interface. */
     507        dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
     508
     509        /* Retrieve standard descriptors. */
     510        rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
     511            &dev->descriptors);
     512        if (rc != EOK) {
     513                *errstr_ptr = "descriptor retrieval";
     514                return rc;
     515        }
     516
     517        /* Create alternate interfaces. */
     518        rc = usb_alternate_interfaces_create(dev->descriptors.configuration,
     519            dev->descriptors.configuration_size, dev->interface_no,
     520            &dev->alternate_interfaces);
     521        if (rc != EOK) {
     522                /* We will try to silently ignore this. */
     523                dev->alternate_interfaces = NULL;
     524        }
     525
     526        rc = initialize_other_pipes(endpoints, dev, 0);
     527        if (rc != EOK) {
     528                *errstr_ptr = "pipes initialization";
     529                return rc;
     530        }
     531
     532        *errstr_ptr = NULL;
     533        *dev_ptr = dev;
     534
     535        return EOK;
    540536}
    541537
  • uspace/lib/usb/src/devpoll.c

    ref354b6 re50cd7f  
    3333 * USB device driver framework - automatic interrupt polling.
    3434 */
    35 #include <usb/devdrv.h>
     35#include <usb/devpoll.h>
    3636#include <usb/request.h>
    3737#include <usb/debug.h>
     38#include <usb/classes/classes.h>
    3839#include <errno.h>
    3940#include <str_error.h>
     
    4546/** Data needed for polling. */
    4647typedef struct {
     48        int debug;
     49        size_t max_failures;
     50        useconds_t delay;
     51        bool auto_clear_halt;
     52        bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *);
     53        void (*on_polling_end)(usb_device_t *, bool, void *);
     54        bool (*on_error)(usb_device_t *, int, void *);
     55
    4756        usb_device_t *dev;
    4857        size_t pipe_index;
    49         usb_polling_callback_t callback;
    50         usb_polling_terminted_callback_t terminated_callback;
    5158        size_t request_size;
    5259        uint8_t *buffer;
     
    5461} polling_data_t;
    5562
     63
    5664/** Polling fibril.
    5765 *
     
    6674        usb_pipe_t *pipe
    6775            = polling_data->dev->pipes[polling_data->pipe_index].pipe;
     76       
     77        if (polling_data->debug > 0) {
     78                usb_endpoint_mapping_t *mapping
     79                    = &polling_data->dev->pipes[polling_data->pipe_index];
     80                usb_log_debug("Poll0x%x: started polling of `%s' - " \
     81                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
     82                    polling_data,
     83                    polling_data->dev->ddf_dev->name,
     84                    (int) mapping->interface->interface_number,
     85                    usb_str_class(mapping->interface->interface_class),
     86                    (int) mapping->interface->interface_subclass,
     87                    (int) mapping->interface->interface_protocol,
     88                    polling_data->request_size, pipe->max_packet_size);
     89        }
    6890
    6991        size_t failed_attempts = 0;
    70         while (failed_attempts < MAX_FAILED_ATTEMPTS) {
     92        while (failed_attempts <= polling_data->max_failures) {
    7193                int rc;
    72 
    73                 rc = usb_pipe_start_session(pipe);
    74                 if (rc != EOK) {
    75                         failed_attempts++;
    76                         continue;
    77                 }
    7894
    7995                size_t actual_size;
     
    8197                    polling_data->request_size, &actual_size);
    8298
    83                 /* Quit the session regardless of errors. */
    84                 usb_pipe_end_session(pipe);
     99                if (polling_data->debug > 1) {
     100                        if (rc == EOK) {
     101                                usb_log_debug(
     102                                    "Poll0x%x: received: '%s' (%zuB).\n",
     103                                    polling_data,
     104                                    usb_debug_str_buffer(polling_data->buffer,
     105                                        actual_size, 16),
     106                                    actual_size);
     107                        } else {
     108                                usb_log_debug(
     109                                    "Poll0x%x: polling failed: %s.\n",
     110                                    polling_data, str_error(rc));
     111                        }
     112                }
     113
     114                /* If the pipe stalled, we can try to reset the stall. */
     115                if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
     116                        /*
     117                         * We ignore error here as this is usually a futile
     118                         * attempt anyway.
     119                         */
     120                        usb_request_clear_endpoint_halt(
     121                            &polling_data->dev->ctrl_pipe,
     122                            pipe->endpoint_no);
     123                }
    85124
    86125                if (rc != EOK) {
     126                        if (polling_data->on_error != NULL) {
     127                                bool cont = polling_data->on_error(
     128                                    polling_data->dev, rc,
     129                                    polling_data->custom_arg);
     130                                if (!cont) {
     131                                        failed_attempts
     132                                            = polling_data->max_failures;
     133                                }
     134                        }
    87135                        failed_attempts++;
    88136                        continue;
     
    90138
    91139                /* We have the data, execute the callback now. */
    92                 bool carry_on = polling_data->callback(polling_data->dev,
     140                bool carry_on = polling_data->on_data(polling_data->dev,
    93141                    polling_data->buffer, actual_size,
    94142                    polling_data->custom_arg);
     
    101149                /* Reset as something might be only a temporary problem. */
    102150                failed_attempts = 0;
    103         }
    104 
    105         if (failed_attempts > 0) {
    106                 usb_log_error(
    107                     "Polling of device `%s' terminated: recurring failures.\n",
    108                     polling_data->dev->ddf_dev->name);
    109         }
    110 
    111         if (polling_data->terminated_callback != NULL) {
    112                 polling_data->terminated_callback(polling_data->dev,
     151
     152                /* Take a rest before next request. */
     153                async_usleep(polling_data->delay);
     154        }
     155
     156        if (polling_data->on_polling_end != NULL) {
     157                polling_data->on_polling_end(polling_data->dev,
    113158                    failed_attempts > 0, polling_data->custom_arg);
     159        }
     160
     161        if (polling_data->debug > 0) {
     162                if (failed_attempts > 0) {
     163                        usb_log_error(
     164                            "Polling of device `%s' terminated: %s.\n",
     165                            polling_data->dev->ddf_dev->name,
     166                            "recurring failures");
     167                } else {
     168                        usb_log_debug(
     169                            "Polling of device `%s' terminated by user.\n",
     170                            polling_data->dev->ddf_dev->name
     171                        );
     172                }
    114173        }
    115174
     
    154213        }
    155214
     215        usb_device_auto_polling_t *auto_polling
     216            = malloc(sizeof(usb_device_auto_polling_t));
     217        if (auto_polling == NULL) {
     218                return ENOMEM;
     219        }
     220
     221        auto_polling->debug = 1;
     222        auto_polling->auto_clear_halt = true;
     223        auto_polling->delay = 0;
     224        auto_polling->max_failures = MAX_FAILED_ATTEMPTS;
     225        auto_polling->on_data = callback;
     226        auto_polling->on_polling_end = terminated_callback;
     227        auto_polling->on_error = NULL;
     228
     229        int rc = usb_device_auto_polling(dev, pipe_index, auto_polling,
     230           request_size, arg);
     231
     232        free(auto_polling);
     233
     234        return rc;
     235}
     236
     237/** Start automatic device polling over interrupt in pipe.
     238 *
     239 * The polling settings is copied thus it is okay to destroy the structure
     240 * after this function returns.
     241 *
     242 * @warning There is no guarantee when the request to the device
     243 * will be sent for the first time (it is possible that this
     244 * first request would be executed prior to return from this function).
     245 *
     246 * @param dev Device to be periodically polled.
     247 * @param pipe_index Index of the endpoint pipe used for polling.
     248 * @param polling Polling settings.
     249 * @param request_size How many bytes to ask for in each request.
     250 * @param arg Custom argument (passed as is to the callbacks).
     251 * @return Error code.
     252 * @retval EOK New fibril polling the device was already started.
     253 */
     254int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
     255    usb_device_auto_polling_t *polling,
     256    size_t request_size, void *arg)
     257{
     258        if (dev == NULL) {
     259                return EBADMEM;
     260        }
     261        if (pipe_index >= dev->pipes_count) {
     262                return EINVAL;
     263        }
     264        if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
     265            || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
     266                return EINVAL;
     267        }
     268        if ((polling == NULL) || (polling->on_data == NULL)) {
     269                return EBADMEM;
     270        }
     271
    156272        polling_data_t *polling_data = malloc(sizeof(polling_data_t));
    157273        if (polling_data == NULL) {
     
    159275        }
    160276
    161         /* Allocate now to prevent immediate failure in the polling fibril. */
    162         polling_data->buffer = malloc(request_size);
     277        /* Fill-in the data. */
     278        polling_data->buffer = malloc(sizeof(request_size));
    163279        if (polling_data->buffer == NULL) {
    164280                free(polling_data);
    165281                return ENOMEM;
    166282        }
     283        polling_data->request_size = request_size;
    167284        polling_data->dev = dev;
    168285        polling_data->pipe_index = pipe_index;
    169         polling_data->callback = callback;
    170         polling_data->terminated_callback = terminated_callback;
    171         polling_data->request_size = request_size;
    172286        polling_data->custom_arg = arg;
     287
     288        polling_data->debug = polling->debug;
     289        polling_data->max_failures = polling->max_failures;
     290        if (polling->delay >= 0) {
     291                polling_data->delay = (useconds_t) polling->delay;
     292        } else {
     293                polling_data->delay = (useconds_t) dev->pipes[pipe_index]
     294                    .descriptor->poll_interval;
     295        }
     296        polling_data->auto_clear_halt = polling->auto_clear_halt;
     297
     298        polling_data->on_data = polling->on_data;
     299        polling_data->on_polling_end = polling->on_polling_end;
     300        polling_data->on_error = polling->on_error;
    173301
    174302        fid_t fibril = fibril_create(polling_fibril, polling_data);
     
    176304                free(polling_data->buffer);
    177305                free(polling_data);
    178                 /* FIXME: better error code. */
    179306                return ENOMEM;
    180307        }
    181308        fibril_add_ready(fibril);
    182309
    183         /* The allocated buffer etc. will be freed by the fibril. */
     310        /* Fibril launched. That fibril will free the allocated data. */
    184311
    185312        return EOK;
  • uspace/lib/usb/src/hidparser.c

    ref354b6 re50cd7f  
    877877
    878878        offset = item->offset + (j * item->size);
    879        
    880879        // FIXME
    881880        if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
     
    13521351
    13531352                field = list_get_instance(field_it, usb_hid_report_field_t, link);
    1354                 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
    1355                 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
    1356                         ret++;
    1357                 }
    1358                 usb_hid_report_remove_last_item (field->collection_path);
     1353                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){
     1354                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1355                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     1356                                ret++;
     1357                        }
     1358                        usb_hid_report_remove_last_item (field->collection_path);
     1359                }
    13591360               
    13601361                field_it = field_it->next;
     
    15361537
    15371538/**
    1538  * Clones given report item structure and returns the new one
    1539  *
    1540  * @param item Report item structure to clone
    1541  * @return Clonned item
    1542  */
    1543 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
    1544 {
    1545         usb_hid_report_item_t *new_report_item;
    1546        
    1547         if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
    1548                 return NULL;
    1549         }                                       
    1550         memcpy(new_report_item,item, sizeof(usb_hid_report_item_t));
    1551         link_initialize(&(new_report_item->link));
    1552 
    1553         return new_report_item;
    1554 }
    1555 
    1556 
    1557 /**
    15581539 *
    15591540 *
     
    16041585}
    16051586
     1587
     1588usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
     1589{
     1590        usb_hid_report_item_t *new_report_item;
     1591       
     1592        if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
     1593                return NULL;
     1594        }                                       
     1595        memcpy(new_report_item,item, sizeof(usb_hid_report_item_t));
     1596        link_initialize(&(new_report_item->link));
     1597
     1598        return new_report_item;
     1599}
     1600
     1601
     1602usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
     1603                                                        usb_hid_report_field_t *field,
     1604                            usb_hid_report_path_t *path, int flags,
     1605                            usb_hid_report_type_t type)
     1606{
     1607        usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);
     1608        link_t *field_it;
     1609       
     1610        if(report_des == NULL){
     1611                return NULL;
     1612        }
     1613
     1614        if(field == NULL){
     1615                // vezmu prvni co mathuje podle path!!
     1616                field_it = report_des->report_items.next;
     1617        }
     1618        else {
     1619                field_it = field->link.next;
     1620        }
     1621
     1622        while(field_it != &report_des->report_items) {
     1623                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     1624                       
     1625                usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1626                if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
     1627                        usb_hid_report_remove_last_item (field->collection_path);
     1628                        usb_log_debug("....OK\n");
     1629                        return field;
     1630                }
     1631                usb_hid_report_remove_last_item (field->collection_path);
     1632
     1633                field_it = field_it->next;
     1634        }
     1635
     1636        return NULL;
     1637}
    16061638/**
    16071639 * @}
  • uspace/lib/usb/src/hidreport.c

    ref354b6 re50cd7f  
    8080                d = usb_dp_get_sibling_descriptor(&parser, &parser_data,
    8181                    dev->descriptors.configuration, d);
     82                ++i;
    8283        }
    8384       
     
    118119        uint16_t length =  hid_desc->report_desc_info.length;
    119120        size_t actual_size = 0;
    120        
    121         /*
    122          * Start session for the control transfer.
    123          */
    124         int sess_rc = usb_pipe_start_session(&dev->ctrl_pipe);
    125         if (sess_rc != EOK) {
    126                 usb_log_warning("Failed to start a session: %s.\n",
    127                     str_error(sess_rc));
    128                 return sess_rc;
    129         }
    130121
    131122        /*
     
    161152                    "%u)\n", actual_size, length);
    162153                return EINVAL;
    163         }
    164        
    165         /*
    166          * End session for the control transfer.
    167          */
    168         sess_rc = usb_pipe_end_session(&dev->ctrl_pipe);
    169         if (sess_rc != EOK) {
    170                 usb_log_warning("Failed to end a session: %s.\n",
    171                     str_error(sess_rc));
    172                 free(*report_desc);
    173                 *report_desc = NULL;
    174                 return sess_rc;
    175154        }
    176155       
  • uspace/lib/usb/src/hidreq.c

    ref354b6 re50cd7f  
    5656 * @retval EOK if successful.
    5757 * @retval EINVAL if no HID device is given.
    58  * @return Other value inherited from one of functions
    59  *         usb_pipe_start_session(), usb_pipe_end_session(),
    60  *         usb_control_request_set().
     58 * @return Other value inherited from function usb_control_request_set().
    6159 */
    6260int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
     
    7977         */
    8078       
    81         int rc, sess_rc;
    82        
    83         sess_rc = usb_pipe_start_session(ctrl_pipe);
    84         if (sess_rc != EOK) {
    85                 usb_log_warning("Failed to start a session: %s.\n",
    86                     str_error(sess_rc));
    87                 return sess_rc;
    88         }
     79        int rc;
    8980       
    9081        uint16_t value = 0;
     
    9788            USB_HIDREQ_SET_REPORT, value, iface_no, buffer, buf_size);
    9889
    99         sess_rc = usb_pipe_end_session(ctrl_pipe);
    100 
    101         if (rc != EOK) {
    102                 usb_log_warning("Error sending output report to the keyboard: "
    103                     "%s.\n", str_error(rc));
    104                 return rc;
    105         }
    106 
    107         if (sess_rc != EOK) {
    108                 usb_log_warning("Error closing session: %s.\n",
    109                     str_error(sess_rc));
    110                 return sess_rc;
     90        if (rc != EOK) {
     91                usb_log_warning("Error sending output report to the keyboard: "
     92                    "%s.\n", str_error(rc));
     93                return rc;
    11194        }
    11295       
     
    123106 * @retval EOK if successful.
    124107 * @retval EINVAL if no HID device is given.
    125  * @return Other value inherited from one of functions
    126  *         usb_pipe_start_session(), usb_pipe_end_session(),
    127  *         usb_control_request_set().
     108 * @return Other value inherited from function usb_control_request_set().
    128109 */
    129110int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
     
    146127         */
    147128       
    148         int rc, sess_rc;
    149        
    150         sess_rc = usb_pipe_start_session(ctrl_pipe);
    151         if (sess_rc != EOK) {
    152                 usb_log_warning("Failed to start a session: %s.\n",
    153                     str_error(sess_rc));
    154                 return sess_rc;
    155         }
     129        int rc;
    156130
    157131        usb_log_debug("Sending Set_Protocol request to the device ("
     
    162136            USB_HIDREQ_SET_PROTOCOL, protocol, iface_no, NULL, 0);
    163137
    164         sess_rc = usb_pipe_end_session(ctrl_pipe);
    165 
    166         if (rc != EOK) {
    167                 usb_log_warning("Error sending output report to the keyboard: "
    168                     "%s.\n", str_error(rc));
    169                 return rc;
    170         }
    171 
    172         if (sess_rc != EOK) {
    173                 usb_log_warning("Error closing session: %s.\n",
    174                     str_error(sess_rc));
    175                 return sess_rc;
     138        if (rc != EOK) {
     139                usb_log_warning("Error sending output report to the keyboard: "
     140                    "%s.\n", str_error(rc));
     141                return rc;
    176142        }
    177143       
     
    189155 * @retval EOK if successful.
    190156 * @retval EINVAL if no HID device is given.
    191  * @return Other value inherited from one of functions
    192  *         usb_pipe_start_session(), usb_pipe_end_session(),
    193  *         usb_control_request_set().
     157 * @return Other value inherited from function usb_control_request_set().
    194158 */
    195159int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration)
     
    211175         */
    212176       
    213         int rc, sess_rc;
    214        
    215         sess_rc = usb_pipe_start_session(ctrl_pipe);
    216         if (sess_rc != EOK) {
    217                 usb_log_warning("Failed to start a session: %s.\n",
    218                     str_error(sess_rc));
    219                 return sess_rc;
    220         }
     177        int rc;
    221178
    222179        usb_log_debug("Sending Set_Idle request to the device ("
     
    229186            USB_HIDREQ_SET_IDLE, value, iface_no, NULL, 0);
    230187
    231         sess_rc = usb_pipe_end_session(ctrl_pipe);
    232 
    233         if (rc != EOK) {
    234                 usb_log_warning("Error sending output report to the keyboard: "
    235                     "%s.\n", str_error(rc));
    236                 return rc;
    237         }
    238 
    239         if (sess_rc != EOK) {
    240                 usb_log_warning("Error closing session: %s.\n",
    241                     str_error(sess_rc));
    242                 return sess_rc;
     188        if (rc != EOK) {
     189                usb_log_warning("Error sending output report to the keyboard: "
     190                    "%s.\n", str_error(rc));
     191                return rc;
    243192        }
    244193       
     
    259208 * @retval EOK if successful.
    260209 * @retval EINVAL if no HID device is given.
    261  * @return Other value inherited from one of functions
    262  *         usb_pipe_start_session(), usb_pipe_end_session(),
    263  *         usb_control_request_set().
     210 * @return Other value inherited from function usb_control_request_set().
    264211 */
    265212int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no,
     
    283230         */
    284231       
    285         int rc, sess_rc;
    286        
    287         sess_rc = usb_pipe_start_session(ctrl_pipe);
    288         if (sess_rc != EOK) {
    289                 usb_log_warning("Failed to start a session: %s.\n",
    290                     str_error(sess_rc));
    291                 return sess_rc;
    292         }
     232        int rc;
    293233
    294234        uint16_t value = 0;
     
    302242            actual_size);
    303243
    304         sess_rc = usb_pipe_end_session(ctrl_pipe);
    305 
    306         if (rc != EOK) {
    307                 usb_log_warning("Error sending output report to the keyboard: "
    308                     "%s.\n", str_error(rc));
    309                 return rc;
    310         }
    311 
    312         if (sess_rc != EOK) {
    313                 usb_log_warning("Error closing session: %s.\n",
    314                     str_error(sess_rc));
    315                 return sess_rc;
     244        if (rc != EOK) {
     245                usb_log_warning("Error sending output report to the keyboard: "
     246                    "%s.\n", str_error(rc));
     247                return rc;
    316248        }
    317249       
     
    328260 * @retval EOK if successful.
    329261 * @retval EINVAL if no HID device is given.
    330  * @return Other value inherited from one of functions
    331  *         usb_pipe_start_session(), usb_pipe_end_session(),
    332  *         usb_control_request_set().
     262 * @return Other value inherited from function usb_control_request_set().
    333263 */
    334264int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
     
    351281         */
    352282       
    353         int rc, sess_rc;
    354        
    355         sess_rc = usb_pipe_start_session(ctrl_pipe);
    356         if (sess_rc != EOK) {
    357                 usb_log_warning("Failed to start a session: %s.\n",
    358                     str_error(sess_rc));
    359                 return sess_rc;
    360         }
     283        int rc;
    361284
    362285        usb_log_debug("Sending Get_Protocol request to the device ("
     
    370293            USB_HIDREQ_GET_PROTOCOL, 0, iface_no, buffer, 1, &actual_size);
    371294
    372         sess_rc = usb_pipe_end_session(ctrl_pipe);
    373 
    374         if (rc != EOK) {
    375                 usb_log_warning("Error sending output report to the keyboard: "
    376                     "%s.\n", str_error(rc));
    377                 return rc;
    378         }
    379 
    380         if (sess_rc != EOK) {
    381                 usb_log_warning("Error closing session: %s.\n",
    382                     str_error(sess_rc));
    383                 return sess_rc;
     295        if (rc != EOK) {
     296                usb_log_warning("Error sending output report to the keyboard: "
     297                    "%s.\n", str_error(rc));
     298                return rc;
    384299        }
    385300       
     
    427342         */
    428343       
    429         int rc, sess_rc;
    430        
    431         sess_rc = usb_pipe_start_session(ctrl_pipe);
    432         if (sess_rc != EOK) {
    433                 usb_log_warning("Failed to start a session: %s.\n",
    434                     str_error(sess_rc));
    435                 return sess_rc;
    436         }
     344        int rc;
    437345
    438346        usb_log_debug("Sending Get_Idle request to the device ("
     
    448356            &actual_size);
    449357
    450         sess_rc = usb_pipe_end_session(ctrl_pipe);
    451 
    452         if (rc != EOK) {
    453                 usb_log_warning("Error sending output report to the keyboard: "
    454                     "%s.\n", str_error(rc));
    455                 return rc;
    456         }
    457 
    458         if (sess_rc != EOK) {
    459                 usb_log_warning("Error closing session: %s.\n",
    460                     str_error(sess_rc));
    461                 return sess_rc;
     358        if (rc != EOK) {
     359                usb_log_warning("Error sending output report to the keyboard: "
     360                    "%s.\n", str_error(rc));
     361                return rc;
    462362        }
    463363       
  • uspace/lib/usb/src/host/batch.c

    ref354b6 re50cd7f  
    3939#include <usb/host/batch.h>
    4040
     41void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
     42void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
     43
    4144void usb_transfer_batch_init(
    4245    usb_transfer_batch_t *instance,
    43     usb_target_t target,
    44     usb_transfer_type_t transfer_type,
    45     usb_speed_t speed,
    46     size_t max_packet_size,
     46    endpoint_t *ep,
    4747    char *buffer,
    48     char *transport_buffer,
     48    char *data_buffer,
    4949    size_t buffer_size,
    5050    char *setup_buffer,
     
    5454    void *arg,
    5555    ddf_fun_t *fun,
    56                 endpoint_t *ep,
    57     void *private_data
     56    void *private_data,
     57    void (*private_data_dtor)(void *p_data)
    5858    )
    5959{
    6060        assert(instance);
    6161        link_initialize(&instance->link);
    62         instance->target = target;
    63         instance->transfer_type = transfer_type;
    64         instance->speed = speed;
    65         instance->direction = USB_DIRECTION_BOTH;
     62        instance->ep = ep;
    6663        instance->callback_in = func_in;
    6764        instance->callback_out = func_out;
    6865        instance->arg = arg;
    6966        instance->buffer = buffer;
    70         instance->transport_buffer = transport_buffer;
     67        instance->data_buffer = data_buffer;
    7168        instance->buffer_size = buffer_size;
    7269        instance->setup_buffer = setup_buffer;
    7370        instance->setup_size = setup_size;
    74         instance->max_packet_size = max_packet_size;
    7571        instance->fun = fun;
    7672        instance->private_data = private_data;
     73        instance->private_data_dtor = private_data_dtor;
    7774        instance->transfered_size = 0;
    7875        instance->next_step = NULL;
    7976        instance->error = EOK;
    80         instance->ep = ep;
     77        endpoint_use(instance->ep);
     78}
     79/*----------------------------------------------------------------------------*/
     80/** Helper function, calls callback and correctly destroys batch structure.
     81 *
     82 * @param[in] instance Batch structure to use.
     83 */
     84void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance)
     85{
     86        assert(instance);
     87        usb_transfer_batch_call_in(instance);
     88        usb_transfer_batch_dispose(instance);
     89}
     90/*----------------------------------------------------------------------------*/
     91/** Helper function calls callback and correctly destroys batch structure.
     92 *
     93 * @param[in] instance Batch structure to use.
     94 */
     95void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance)
     96{
     97        assert(instance);
     98        usb_transfer_batch_call_out(instance);
     99        usb_transfer_batch_dispose(instance);
    81100}
    82101/*----------------------------------------------------------------------------*/
     
    86105 *
    87106 */
    88 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error)
     107void usb_transfer_batch_finish(usb_transfer_batch_t *instance)
    89108{
    90109        assert(instance);
    91         instance->error = error;
     110        assert(instance->ep);
     111        endpoint_release(instance->ep);
    92112        instance->next_step(instance);
    93113}
     
    103123        assert(instance);
    104124        assert(instance->callback_in);
     125        assert(instance->ep);
    105126
    106127        /* We are data in, we need data */
    107         memcpy(instance->buffer, instance->transport_buffer,
    108             instance->buffer_size);
     128        memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
    109129
    110130        usb_log_debug("Batch %p done (T%d.%d, %s %s in, %zuB): %s (%d).\n",
    111             instance,
    112             instance->target.address, instance->target.endpoint,
    113             usb_str_speed(instance->speed),
    114             usb_str_transfer_type_short(instance->transfer_type),
    115             instance->transfered_size,
    116             str_error(instance->error), instance->error);
     131            instance, instance->ep->address, instance->ep->endpoint,
     132            usb_str_speed(instance->ep->speed),
     133            usb_str_transfer_type_short(instance->ep->transfer_type),
     134            instance->transfered_size, str_error(instance->error), instance->error);
    117135
    118136        instance->callback_in(instance->fun, instance->error,
     
    130148
    131149        usb_log_debug("Batch %p done (T%d.%d, %s %s out): %s (%d).\n",
    132             instance,
    133             instance->target.address, instance->target.endpoint,
    134             usb_str_speed(instance->speed),
    135             usb_str_transfer_type_short(instance->transfer_type),
     150            instance, instance->ep->address, instance->ep->endpoint,
     151            usb_str_speed(instance->ep->speed),
     152            usb_str_transfer_type_short(instance->ep->transfer_type),
    136153            str_error(instance->error), instance->error);
    137154
     
    139156            instance->error, instance->arg);
    140157}
     158/*----------------------------------------------------------------------------*/
     159/** Correctly dispose all used data structures.
     160 *
     161 * @param[in] instance Batch structure to use.
     162 */
     163void usb_transfer_batch_dispose(usb_transfer_batch_t *instance)
     164{
     165        assert(instance);
     166        usb_log_debug("Batch(%p) disposing.\n", instance);
     167        if (instance->private_data) {
     168                assert(instance->private_data_dtor);
     169                instance->private_data_dtor(instance->private_data);
     170        }
     171        free(instance);
     172}
    141173/**
    142174 * @}
  • uspace/lib/usb/src/host/device_keeper.c

    ref354b6 re50cd7f  
    4848{
    4949        assert(instance);
    50         fibril_mutex_initialize(&instance->guard);
    51         fibril_condvar_initialize(&instance->change);
    52         instance->last_address = 0;
    5350        unsigned i = 0;
    5451        for (; i < USB_ADDRESS_COUNT; ++i) {
    5552                instance->devices[i].occupied = false;
    56                 instance->devices[i].control_used = 0;
    5753                instance->devices[i].handle = 0;
    58                 list_initialize(&instance->devices[i].endpoints);
     54                instance->devices[i].speed = USB_SPEED_MAX;
    5955        }
    60 }
    61 /*----------------------------------------------------------------------------*/
    62 void usb_device_keeper_add_ep(
    63     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep)
    64 {
    65         assert(instance);
    66         fibril_mutex_lock(&instance->guard);
    67         assert(instance->devices[address].occupied);
    68         list_append(&ep->same_device_eps, &instance->devices[address].endpoints);
    69         fibril_mutex_unlock(&instance->guard);
    70 }
    71 /*----------------------------------------------------------------------------*/
    72 /** Attempt to obtain address 0, blocks.
    73  *
    74  * @param[in] instance Device keeper structure to use.
    75  * @param[in] speed Speed of the device requesting default address.
    76  */
    77 void usb_device_keeper_reserve_default_address(
    78     usb_device_keeper_t *instance, usb_speed_t speed)
    79 {
    80         assert(instance);
    81         fibril_mutex_lock(&instance->guard);
    82         while (instance->devices[USB_ADDRESS_DEFAULT].occupied) {
    83                 fibril_condvar_wait(&instance->change, &instance->guard);
    84         }
    85         instance->devices[USB_ADDRESS_DEFAULT].occupied = true;
    86         instance->devices[USB_ADDRESS_DEFAULT].speed = speed;
    87         fibril_mutex_unlock(&instance->guard);
    88 }
    89 /*----------------------------------------------------------------------------*/
    90 /** Attempt to obtain address 0, blocks.
    91  *
    92  * @param[in] instance Device keeper structure to use.
    93  * @param[in] speed Speed of the device requesting default address.
    94  */
    95 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance)
    96 {
    97         assert(instance);
    98         fibril_mutex_lock(&instance->guard);
    99         instance->devices[USB_ADDRESS_DEFAULT].occupied = false;
    100         fibril_mutex_unlock(&instance->guard);
    101         fibril_condvar_signal(&instance->change);
    102 }
    103 /*----------------------------------------------------------------------------*/
    104 /** Check setup packet data for signs of toggle reset.
    105  *
    106  * @param[in] instance Device keeper structure to use.
    107  * @param[in] target Device to receive setup packet.
    108  * @param[in] data Setup packet data.
    109  *
    110  * Really ugly one.
    111  */
    112 void usb_device_keeper_reset_if_need(
    113     usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data)
    114 {
    115         assert(instance);
    116         fibril_mutex_lock(&instance->guard);
    117         if (target.endpoint > 15 || target.endpoint < 0
    118             || target.address >= USB_ADDRESS_COUNT || target.address < 0
    119             || !instance->devices[target.address].occupied) {
    120                 fibril_mutex_unlock(&instance->guard);
    121                 usb_log_error("Invalid data when checking for toggle reset.\n");
    122                 return;
    123         }
    124 
    125         switch (data[1])
    126         {
    127         case 0x01: /*clear feature*/
    128                 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
    129                 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    130                         link_t *current =
    131                             instance->devices[target.address].endpoints.next;
    132                         while (current !=
    133                            &instance->devices[target.address].endpoints)
    134                         {
    135                         /* endpoint number is < 16, thus first byte is enough */
    136                                 endpoint_toggle_reset_filtered(
    137                                     current, data[4]);
    138                                 current = current->next;
    139                         }
    140                 }
    141         break;
    142 
    143         case 0x9: /* set configuration */
    144         case 0x11: /* set interface */
    145                 /* target must be device */
    146                 if ((data[0] & 0xf) == 0) {
    147                         link_t *current =
    148                             instance->devices[target.address].endpoints.next;
    149                         while (current !=
    150                            &instance->devices[target.address].endpoints)
    151                         {
    152                                 endpoint_toggle_reset(current);
    153                                 current = current->next;
    154                         }
    155                 }
    156         break;
    157         }
    158         fibril_mutex_unlock(&instance->guard);
     56        // TODO: is this hack enough?
     57        // (it is needed to allow smooth registration at default address)
     58        instance->devices[0].occupied = true;
     59        instance->last_address = 0;
     60        fibril_mutex_initialize(&instance->guard);
    15961}
    16062/*----------------------------------------------------------------------------*/
     
    18486        assert(new_address != USB_ADDRESS_DEFAULT);
    18587        assert(instance->devices[new_address].occupied == false);
     88
    18689        instance->devices[new_address].occupied = true;
    18790        instance->devices[new_address].speed = speed;
    18891        instance->last_address = new_address;
     92
    18993        fibril_mutex_unlock(&instance->guard);
    19094        return new_address;
     
    202106        assert(instance);
    203107        fibril_mutex_lock(&instance->guard);
     108
    204109        assert(address > 0);
    205110        assert(address <= USB11_ADDRESS_MAX);
    206111        assert(instance->devices[address].occupied);
     112
    207113        instance->devices[address].handle = handle;
    208114        fibril_mutex_unlock(&instance->guard);
     
    223129        fibril_mutex_lock(&instance->guard);
    224130        assert(instance->devices[address].occupied);
     131
    225132        instance->devices[address].occupied = false;
    226133        fibril_mutex_unlock(&instance->guard);
     
    241148        while (address <= USB11_ADDRESS_MAX) {
    242149                if (instance->devices[address].handle == handle) {
     150                        assert(instance->devices[address].occupied);
    243151                        fibril_mutex_unlock(&instance->guard);
    244152                        return address;
     
    262170        assert(address >= 0);
    263171        assert(address <= USB11_ADDRESS_MAX);
     172
    264173        return instance->devices[address].speed;
    265 }
    266 /*----------------------------------------------------------------------------*/
    267 void usb_device_keeper_use_control(
    268     usb_device_keeper_t *instance, usb_target_t target)
    269 {
    270         assert(instance);
    271         const uint16_t ep = 1 << target.endpoint;
    272         fibril_mutex_lock(&instance->guard);
    273         while (instance->devices[target.address].control_used & ep) {
    274                 fibril_condvar_wait(&instance->change, &instance->guard);
    275         }
    276         instance->devices[target.address].control_used |= ep;
    277         fibril_mutex_unlock(&instance->guard);
    278 }
    279 /*----------------------------------------------------------------------------*/
    280 void usb_device_keeper_release_control(
    281     usb_device_keeper_t *instance, usb_target_t target)
    282 {
    283         assert(instance);
    284         const uint16_t ep = 1 << target.endpoint;
    285         fibril_mutex_lock(&instance->guard);
    286         assert((instance->devices[target.address].control_used & ep) != 0);
    287         instance->devices[target.address].control_used &= ~ep;
    288         fibril_mutex_unlock(&instance->guard);
    289         fibril_condvar_signal(&instance->change);
    290174}
    291175/**
  • uspace/lib/usb/src/host/endpoint.c

    ref354b6 re50cd7f  
    3434 */
    3535
     36#include <assert.h>
    3637#include <errno.h>
    3738#include <usb/host/endpoint.h>
     
    4950        instance->max_packet_size = max_packet_size;
    5051        instance->toggle = 0;
    51         link_initialize(&instance->same_device_eps);
     52        instance->active = false;
     53        fibril_mutex_initialize(&instance->guard);
     54        fibril_condvar_initialize(&instance->avail);
     55        endpoint_clear_hc_data(instance);
    5256        return EOK;
    5357}
     
    5660{
    5761        assert(instance);
    58         list_remove(&instance->same_device_eps);
     62        assert(!instance->active);
    5963        free(instance);
     64}
     65/*----------------------------------------------------------------------------*/
     66void endpoint_set_hc_data(endpoint_t *instance,
     67    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
     68{
     69        assert(instance);
     70        instance->hc_data.data = data;
     71        instance->hc_data.toggle_get = toggle_get;
     72        instance->hc_data.toggle_set = toggle_set;
     73}
     74/*----------------------------------------------------------------------------*/
     75void endpoint_clear_hc_data(endpoint_t *instance)
     76{
     77        assert(instance);
     78        instance->hc_data.data = NULL;
     79        instance->hc_data.toggle_get = NULL;
     80        instance->hc_data.toggle_set = NULL;
     81}
     82/*----------------------------------------------------------------------------*/
     83void endpoint_use(endpoint_t *instance)
     84{
     85        assert(instance);
     86        fibril_mutex_lock(&instance->guard);
     87        while (instance->active)
     88                fibril_condvar_wait(&instance->avail, &instance->guard);
     89        instance->active = true;
     90        fibril_mutex_unlock(&instance->guard);
     91}
     92/*----------------------------------------------------------------------------*/
     93void endpoint_release(endpoint_t *instance)
     94{
     95        assert(instance);
     96        fibril_mutex_lock(&instance->guard);
     97        instance->active = false;
     98        fibril_mutex_unlock(&instance->guard);
     99        fibril_condvar_signal(&instance->avail);
    60100}
    61101/*----------------------------------------------------------------------------*/
     
    63103{
    64104        assert(instance);
     105        if (instance->hc_data.toggle_get)
     106                instance->toggle =
     107                    instance->hc_data.toggle_get(instance->hc_data.data);
    65108        return (int)instance->toggle;
    66109}
     
    70113        assert(instance);
    71114        assert(toggle == 0 || toggle == 1);
     115        if (instance->hc_data.toggle_set)
     116                instance->hc_data.toggle_set(instance->hc_data.data, toggle);
    72117        instance->toggle = toggle;
    73118}
    74119/*----------------------------------------------------------------------------*/
    75 void endpoint_toggle_reset(link_t *ep)
     120void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target)
    76121{
    77         endpoint_t *instance =
    78             list_get_instance(ep, endpoint_t, same_device_eps);
    79122        assert(instance);
    80         instance->toggle = 0;
    81 }
    82 /*----------------------------------------------------------------------------*/
    83 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn)
    84 {
    85         endpoint_t *instance =
    86             list_get_instance(ep, endpoint_t, same_device_eps);
    87         assert(instance);
    88         if (instance->endpoint == epn)
    89                 instance->toggle = 0;
     123        if (instance->address == target.address &&
     124            (instance->endpoint == target.endpoint || target.endpoint == 0))
     125                endpoint_toggle_set(instance, 0);
    90126}
    91127/**
  • uspace/lib/usb/src/host/usb_endpoint_manager.c

    ref354b6 re50cd7f  
    3131#include <errno.h>
    3232
     33#include <usb/debug.h>
    3334#include <usb/host/usb_endpoint_manager.h>
    3435
     
    8081        endpoint_destroy(node->ep);
    8182        free(node);
     83}
     84/*----------------------------------------------------------------------------*/
     85static void node_toggle_reset_filtered(link_t *item, void *arg)
     86{
     87        assert(item);
     88        node_t *node = hash_table_get_instance(item, node_t, link);
     89        usb_target_t *target = arg;
     90        endpoint_toggle_reset_filtered(node->ep, *target);
    8291}
    8392/*----------------------------------------------------------------------------*/
     
    202211
    203212        node_t *node = hash_table_get_instance(item, node_t, link);
     213        if (node->ep->active)
     214                return EBUSY;
     215
    204216        instance->free_bw += node->bw;
    205217        hash_table_remove(&instance->ep_table, key, MAX_KEYS);
     
    230242        return node->ep;
    231243}
     244/*----------------------------------------------------------------------------*/
     245/** Check setup packet data for signs of toggle reset.
     246 *
     247 * @param[in] instance Device keeper structure to use.
     248 * @param[in] target Device to receive setup packet.
     249 * @param[in] data Setup packet data.
     250 *
     251 * Really ugly one.
     252 */
     253void usb_endpoint_manager_reset_if_need(
     254    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data)
     255{
     256        assert(instance);
     257        if (target.endpoint > 15 || target.endpoint < 0
     258            || target.address >= USB11_ADDRESS_MAX || target.address < 0) {
     259                usb_log_error("Invalid data when checking for toggle reset.\n");
     260                return;
     261        }
     262
     263        switch (data[1])
     264        {
     265        case 0x01: /*clear feature*/
     266                /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
     267                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
     268                        /* endpoint number is < 16, thus first byte is enough */
     269                        usb_target_t reset_target =
     270                            { .address = target.address, data[4] };
     271                        fibril_mutex_lock(&instance->guard);
     272                        hash_table_apply(&instance->ep_table,
     273                            node_toggle_reset_filtered, &reset_target);
     274                        fibril_mutex_unlock(&instance->guard);
     275                }
     276        break;
     277
     278        case 0x9: /* set configuration */
     279        case 0x11: /* set interface */
     280                /* target must be device */
     281                if ((data[0] & 0xf) == 0) {
     282                        usb_target_t reset_target =
     283                            { .address = target.address, 0 };
     284                        fibril_mutex_lock(&instance->guard);
     285                        hash_table_apply(&instance->ep_table,
     286                            node_toggle_reset_filtered, &reset_target);
     287                        fibril_mutex_unlock(&instance->guard);
     288                }
     289        break;
     290        }
     291}
  • uspace/lib/usb/src/hub.c

    ref354b6 re50cd7f  
    4040#include <errno.h>
    4141#include <assert.h>
     42#include <usb/debug.h>
     43
     44/** How much time to wait between attempts to register endpoint 0:0.
     45 * The value is based on typical value for port reset + some overhead.
     46 */
     47#define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2))
    4248
    4349/** Check that HC connection is alright.
     
    5359        } while (false)
    5460
    55 
    56 /** Tell host controller to reserve default address.
    57  *
    58  * @param connection Opened connection to host controller.
    59  * @param speed Speed of the device that will respond on the default address.
    60  * @return Error code.
    61  */
    62 int usb_hc_reserve_default_address(usb_hc_connection_t *connection,
    63     usb_speed_t speed)
    64 {
    65         CHECK_CONNECTION(connection);
    66 
    67         return async_req_2_0(connection->hc_phone,
    68             DEV_IFACE_ID(USBHC_DEV_IFACE),
    69             IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);
    70 }
    71 
    72 /** Tell host controller to release default address.
    73  *
    74  * @param connection Opened connection to host controller.
    75  * @return Error code.
    76  */
    77 int usb_hc_release_default_address(usb_hc_connection_t *connection)
    78 {
    79         CHECK_CONNECTION(connection);
    80 
    81         return async_req_1_0(connection->hc_phone,
    82             DEV_IFACE_ID(USBHC_DEV_IFACE),
    83             IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
    84 }
    85 
    8661/** Ask host controller for free address assignment.
    8762 *
     
    178153 * error codes than those listed as return codes by this function itself).
    179154 *
     155 * The @p connection representing connection with host controller does not
     156 * need to be started.
     157 * This function duplicates the connection to allow simultaneous calls of
     158 * this function (i.e. from different fibrils).
     159 *
    180160 * @param[in] parent Parent device (i.e. the hub device).
    181  * @param[in] connection Opened connection to host controller.
     161 * @param[in] connection Connection to host controller.
    182162 * @param[in] dev_speed New device speed.
    183163 * @param[in] enable_port Function for enabling signaling through the port the
     
    206186    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
    207187{
    208         CHECK_CONNECTION(connection);
     188        assert(connection != NULL);
     189        // FIXME: this is awful, we are accessing directly the structure.
     190        usb_hc_connection_t hc_conn = {
     191                .hc_handle = connection->hc_handle,
     192                .hc_phone = -1
     193        };
     194
     195        int rc;
     196
     197        rc = usb_hc_connection_open(&hc_conn);
     198        if (rc != EOK) {
     199                return rc;
     200        }
     201
    209202
    210203        /*
    211204         * Request new address.
    212205         */
    213         usb_address_t dev_addr = usb_hc_request_address(connection, dev_speed);
     206        usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed);
    214207        if (dev_addr < 0) {
     208                usb_hc_connection_close(&hc_conn);
    215209                return EADDRNOTAVAIL;
    216210        }
    217211
    218         int rc;
    219 
    220         /*
    221          * Reserve the default address.
    222          */
    223         rc = usb_hc_reserve_default_address(connection, dev_speed);
    224         if (rc != EOK) {
    225                 rc = EBUSY;
    226                 goto leave_release_free_address;
    227         }
    228 
    229         /*
    230          * Enable the port (i.e. allow signaling through this port).
    231          */
    232         rc = enable_port(port_no, arg);
    233         if (rc != EOK) {
    234                 goto leave_release_default_address;
    235         }
    236 
    237         /*
    238          * Change the address from default to the free one.
    239          * We need to create a new control pipe for that.
     212        /*
     213         * We will not register control pipe on default address.
     214         * The registration might fail. That means that someone else already
     215         * registered that endpoint. We will simply wait and try again.
     216         * (Someone else already wants to add a new device.)
    240217         */
    241218        usb_device_connection_t dev_conn;
    242219        rc = usb_device_connection_initialize_on_default_address(&dev_conn,
    243             connection);
     220            &hc_conn);
    244221        if (rc != EOK) {
    245222                rc = ENOTCONN;
    246                 goto leave_release_default_address;
     223                goto leave_release_free_address;
    247224        }
    248225
     
    252229        if (rc != EOK) {
    253230                rc = ENOTCONN;
     231                goto leave_release_free_address;
     232        }
     233
     234        do {
     235                rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0,
     236                    &hc_conn);
     237                if (rc != EOK) {
     238                        /* Do not overheat the CPU ;-). */
     239                        async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
     240                }
     241        } while (rc != EOK);
     242
     243        /*
     244         * Endpoint is registered. We can enable the port and change
     245         * device address.
     246         */
     247        rc = enable_port(port_no, arg);
     248        if (rc != EOK) {
    254249                goto leave_release_default_address;
    255250        }
    256251
    257         /* Before sending any traffic, we need to register this
    258          * endpoint.
    259          */
    260         rc = usb_pipe_register(&ctrl_pipe, 0, connection);
    261         if (rc != EOK) {
    262                 rc = EREFUSED;
     252        rc = usb_pipe_probe_default_control(&ctrl_pipe);
     253        if (rc != EOK) {
     254                rc = ESTALL;
    263255                goto leave_release_default_address;
    264256        }
    265         rc = usb_pipe_probe_default_control(&ctrl_pipe);
    266         if (rc != EOK) {
    267                 rc = ENOTCONN;
     257
     258        rc = usb_request_set_address(&ctrl_pipe, dev_addr);
     259        if (rc != EOK) {
     260                rc = ESTALL;
    268261                goto leave_release_default_address;
    269262        }
    270263
    271         rc = usb_pipe_start_session(&ctrl_pipe);
    272         if (rc != EOK) {
    273                 rc = ENOTCONN;
    274                 goto leave_unregister_endpoint;
    275         }
    276 
    277         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
    278         if (rc != EOK) {
    279                 rc = ESTALL;
    280                 goto leave_stop_session;
    281         }
    282 
    283         usb_pipe_end_session(&ctrl_pipe);
    284 
    285         /*
    286          * Register the control endpoint for the new device.
    287          */
    288         rc = usb_pipe_register(&ctrl_pipe, 0, connection);
    289         if (rc != EOK) {
    290                 rc = EREFUSED;
    291                 goto leave_unregister_endpoint;
    292         }
    293 
    294         /*
    295          * Release the original endpoint.
    296          */
    297         unregister_control_endpoint_on_default_address(connection);
    298 
    299         /*
    300          * Once the address is changed, we can return the default address.
    301          */
    302         usb_hc_release_default_address(connection);
    303 
     264        /*
     265         * Address changed. We can release the original endpoint, thus
     266         * allowing other to access the default address.
     267         */
     268        unregister_control_endpoint_on_default_address(&hc_conn);
     269
     270        /*
     271         * Time to register the new endpoint.
     272         */
     273        rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
     274        if (rc != EOK) {
     275                goto leave_release_free_address;
     276        }
    304277
    305278        /*
     
    316289        }
    317290
    318 
    319 
    320291        /*
    321292         * And now inform the host controller about the handle.
     
    325296                .handle = child_handle
    326297        };
    327         rc = usb_hc_register_device(connection, &new_device);
     298        rc = usb_hc_register_device(&hc_conn, &new_device);
    328299        if (rc != EOK) {
    329300                rc = EDESTADDRREQ;
     
    349320         * Completely ignoring errors here.
    350321         */
    351 
    352 leave_stop_session:
    353         usb_pipe_end_session(&ctrl_pipe);
    354 
    355 leave_unregister_endpoint:
    356         usb_pipe_unregister(&ctrl_pipe, connection);
    357 
    358322leave_release_default_address:
    359         usb_hc_release_default_address(connection);
     323        usb_pipe_unregister(&ctrl_pipe, &hc_conn);
    360324
    361325leave_release_free_address:
    362         usb_hc_unregister_device(connection, dev_addr);
     326        usb_hc_unregister_device(&hc_conn, dev_addr);
     327
     328        usb_hc_connection_close(&hc_conn);
    363329
    364330        return rc;
  • uspace/lib/usb/src/pipes.c

    ref354b6 re50cd7f  
    4141#include <errno.h>
    4242#include <assert.h>
     43#include "pipepriv.h"
    4344
    4445#define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
     
    241242 * necessary.
    242243 *
     244 * @deprecated
     245 * Obsoleted with introduction of usb_pipe_start_long_transfer
     246 *
    243247 * @param pipe Endpoint pipe to start the session on.
    244248 * @return Error code.
     
    246250int usb_pipe_start_session(usb_pipe_t *pipe)
    247251{
    248         assert(pipe);
    249 
    250         if (usb_pipe_is_session_started(pipe)) {
    251                 return EBUSY;
    252         }
    253 
    254         int phone = devman_device_connect(pipe->wire->hc_handle, 0);
    255         if (phone < 0) {
    256                 return phone;
    257         }
    258 
    259         pipe->hc_phone = phone;
    260 
     252        usb_log_warning("usb_pipe_start_session() was deprecated.\n");
    261253        return EOK;
    262254}
     
    265257/** Ends a session on the endpoint pipe.
    266258 *
     259 * @deprecated
     260 * Obsoleted with introduction of usb_pipe_end_long_transfer
     261 *
    267262 * @see usb_pipe_start_session
    268263 *
     
    272267int usb_pipe_end_session(usb_pipe_t *pipe)
    273268{
    274         assert(pipe);
    275 
    276         if (!usb_pipe_is_session_started(pipe)) {
    277                 return ENOENT;
    278         }
    279 
    280         int rc = async_hangup(pipe->hc_phone);
    281         if (rc != EOK) {
    282                 return rc;
    283         }
    284 
    285         pipe->hc_phone = -1;
    286 
     269        usb_log_warning("usb_pipe_end_session() was deprecated.\n");
    287270        return EOK;
    288271}
     
    298281bool usb_pipe_is_session_started(usb_pipe_t *pipe)
    299282{
    300         return (pipe->hc_phone >= 0);
     283        pipe_acquire(pipe);
     284        bool started = pipe->refcount > 0;
     285        pipe_release(pipe);
     286        return started;
     287}
     288
     289/** Prepare pipe for a long transfer.
     290 *
     291 * By a long transfer is mean transfer consisting of several
     292 * requests to the HC.
     293 * Calling such function is optional and it has positive effect of
     294 * improved performance because IPC session is initiated only once.
     295 *
     296 * @param pipe Pipe over which the transfer will happen.
     297 * @return Error code.
     298 */
     299int usb_pipe_start_long_transfer(usb_pipe_t *pipe)
     300{
     301        return pipe_add_ref(pipe);
     302}
     303
     304/** Terminate a long transfer on a pipe.
     305 *
     306 * @see usb_pipe_start_long_transfer
     307 *
     308 * @param pipe Pipe where to end the long transfer.
     309 */
     310void usb_pipe_end_long_transfer(usb_pipe_t *pipe)
     311{
     312        pipe_drop_ref(pipe);
    301313}
    302314
  • uspace/lib/usb/src/pipesinit.c

    ref354b6 re50cd7f  
    356356        assert(connection);
    357357
     358        fibril_mutex_initialize(&pipe->guard);
    358359        pipe->wire = connection;
    359360        pipe->hc_phone = -1;
     361        fibril_mutex_initialize(&pipe->hc_phone_mutex);
    360362        pipe->endpoint_no = endpoint_no;
    361363        pipe->transfer_type = transfer_type;
    362364        pipe->max_packet_size = max_packet_size;
    363365        pipe->direction = direction;
     366        pipe->refcount = 0;
     367        pipe->auto_reset_halt = false;
    364368
    365369        return EOK;
     
    382386            0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
    383387            USB_DIRECTION_BOTH);
     388
     389        pipe->auto_reset_halt = true;
    384390
    385391        return rc;
     
    413419        int rc;
    414420
    415         TRY_LOOP(failed_attempts) {
    416                 rc = usb_pipe_start_session(pipe);
    417                 if (rc == EOK) {
    418                         break;
    419                 }
    420         }
     421        rc = usb_pipe_start_long_transfer(pipe);
    421422        if (rc != EOK) {
    422423                return rc;
     
    439440                }
    440441        }
    441         usb_pipe_end_session(pipe);
     442        usb_pipe_end_long_transfer(pipe);
    442443        if (rc != EOK) {
    443444                return rc;
     
    461462    usb_hc_connection_t *hc_connection)
    462463{
     464        return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1,
     465            interval, hc_connection);
     466}
     467
     468/** Register endpoint with a speed at the host controller.
     469 *
     470 * You will rarely need to use this function because it is needed only
     471 * if the registered endpoint is of address 0 and there is no other way
     472 * to tell speed of the device at address 0.
     473 *
     474 * @param pipe Pipe to be registered.
     475 * @param speed Speed of the device
     476 *      (invalid speed means use previously specified one).
     477 * @param interval Polling interval.
     478 * @param hc_connection Connection to the host controller (must be opened).
     479 * @return Error code.
     480 */
     481int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed,
     482    unsigned int interval,
     483    usb_hc_connection_t *hc_connection)
     484{
    463485        assert(pipe);
    464486        assert(hc_connection);
     
    468490        }
    469491
    470 #define _PACK(high, low) ((high) * 256 + (low))
    471 
    472         return async_req_5_0(hc_connection->hc_phone,
     492#define _PACK2(high, low) (((high) << 16) + (low))
     493#define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
     494
     495        return async_req_4_0(hc_connection->hc_phone,
    473496            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,
    474             _PACK(pipe->wire->address, pipe->endpoint_no),
    475             _PACK(pipe->transfer_type, pipe->direction),
    476             pipe->max_packet_size, interval);
    477 
    478 #undef _PACK
     497            _PACK2(pipe->wire->address, pipe->endpoint_no),
     498            _PACK3(speed, pipe->transfer_type, pipe->direction),
     499            _PACK2(pipe->max_packet_size, interval));
     500
     501#undef _PACK2
     502#undef _PACK3
    479503}
    480504
  • uspace/lib/usb/src/pipesio.c

    ref354b6 re50cd7f  
    4949#include <assert.h>
    5050#include <usbhc_iface.h>
     51#include <usb/request.h>
     52#include "pipepriv.h"
    5153
    5254/** Request an in transfer, no checking of input parameters.
     
    7880        }
    7981
     82        /* Ensure serialization over the phone. */
     83        pipe_start_transaction(pipe);
     84
    8085        /*
    8186         * Make call identifying target USB device and type of transfer.
    8287         */
    83         aid_t opening_request = async_send_4(pipe->hc_phone,
     88        aid_t opening_request = async_send_3(pipe->hc_phone,
    8489            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    8590            pipe->wire->address, pipe->endpoint_no,
    86             pipe->max_packet_size,
    8791            NULL);
    8892        if (opening_request == 0) {
     93                pipe_end_transaction(pipe);
    8994                return ENOMEM;
    9095        }
     
    96101        aid_t data_request = async_data_read(pipe->hc_phone, buffer, size,
    97102            &data_request_call);
     103
     104        /*
     105         * Since now on, someone else might access the backing phone
     106         * without breaking the transfer IPC protocol.
     107         */
     108        pipe_end_transaction(pipe);
    98109
    99110        if (data_request == 0) {
     
    146157
    147158        if (buffer == NULL) {
    148                         return EINVAL;
     159                return EINVAL;
    149160        }
    150161
    151162        if (size == 0) {
    152163                return EINVAL;
    153         }
    154 
    155         if (!usb_pipe_is_session_started(pipe)) {
    156                 return EBADF;
    157164        }
    158165
     
    165172        }
    166173
     174        int rc;
     175        rc = pipe_add_ref(pipe);
     176        if (rc != EOK) {
     177                return rc;
     178        }
     179
     180
    167181        size_t act_size = 0;
    168         int rc;
    169182
    170183        rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);
     184
     185        pipe_drop_ref(pipe);
     186
    171187        if (rc != EOK) {
    172188                return rc;
     
    210226        }
    211227
     228        /* Ensure serialization over the phone. */
     229        pipe_start_transaction(pipe);
     230
    212231        /*
    213232         * Make call identifying target USB device and type of transfer.
    214233         */
    215         aid_t opening_request = async_send_4(pipe->hc_phone,
     234        aid_t opening_request = async_send_3(pipe->hc_phone,
    216235            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    217236            pipe->wire->address, pipe->endpoint_no,
    218             pipe->max_packet_size,
    219237            NULL);
    220238        if (opening_request == 0) {
     239                pipe_end_transaction(pipe);
    221240                return ENOMEM;
    222241        }
     
    226245         */
    227246        int rc = async_data_write_start(pipe->hc_phone, buffer, size);
     247
     248        /*
     249         * Since now on, someone else might access the backing phone
     250         * without breaking the transfer IPC protocol.
     251         */
     252        pipe_end_transaction(pipe);
     253
    228254        if (rc != EOK) {
    229255                async_wait_for(opening_request, NULL);
     
    260286        }
    261287
    262         if (!usb_pipe_is_session_started(pipe)) {
    263                 return EBADF;
    264         }
    265 
    266288        if (pipe->direction != USB_DIRECTION_OUT) {
    267289                return EBADF;
     
    272294        }
    273295
    274         int rc = usb_pipe_write_no_check(pipe, buffer, size);
     296        int rc;
     297
     298        rc = pipe_add_ref(pipe);
     299        if (rc != EOK) {
     300                return rc;
     301        }
     302
     303        rc = usb_pipe_write_no_check(pipe, buffer, size);
     304
     305        pipe_drop_ref(pipe);
    275306
    276307        return rc;
     308}
     309
     310/** Try to clear endpoint halt of default control pipe.
     311 *
     312 * @param pipe Pipe for control endpoint zero.
     313 */
     314static void clear_self_endpoint_halt(usb_pipe_t *pipe)
     315{
     316        assert(pipe != NULL);
     317
     318        if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
     319                return;
     320        }
     321
     322
     323        /* Prevent indefinite recursion. */
     324        pipe->auto_reset_halt = false;
     325        usb_request_clear_endpoint_halt(pipe, 0);
     326        pipe->auto_reset_halt = true;
    277327}
    278328
     
    293343    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
    294344{
     345        /* Ensure serialization over the phone. */
     346        pipe_start_transaction(pipe);
     347
    295348        /*
    296349         * Make call identifying target USB device and control transfer type.
    297350         */
    298         aid_t opening_request = async_send_4(pipe->hc_phone,
     351        aid_t opening_request = async_send_3(pipe->hc_phone,
    299352            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
    300353            pipe->wire->address, pipe->endpoint_no,
    301             pipe->max_packet_size,
    302354            NULL);
    303355        if (opening_request == 0) {
     
    311363            setup_buffer, setup_buffer_size);
    312364        if (rc != EOK) {
     365                pipe_end_transaction(pipe);
    313366                async_wait_for(opening_request, NULL);
    314367                return rc;
     
    322375            data_buffer, data_buffer_size,
    323376            &data_request_call);
     377
     378        /*
     379         * Since now on, someone else might access the backing phone
     380         * without breaking the transfer IPC protocol.
     381         */
     382        pipe_end_transaction(pipe);
     383
     384
    324385        if (data_request == 0) {
    325386                async_wait_for(opening_request, NULL);
     
    379440        }
    380441
    381         if (!usb_pipe_is_session_started(pipe)) {
    382                 return EBADF;
    383         }
    384 
    385442        if ((pipe->direction != USB_DIRECTION_BOTH)
    386443            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    388445        }
    389446
     447        int rc;
     448
     449        rc = pipe_add_ref(pipe);
     450        if (rc != EOK) {
     451                return rc;
     452        }
     453
    390454        size_t act_size = 0;
    391         int rc = usb_pipe_control_read_no_check(pipe,
     455        rc = usb_pipe_control_read_no_check(pipe,
    392456            setup_buffer, setup_buffer_size,
    393457            data_buffer, data_buffer_size, &act_size);
     458
     459        if (rc == ESTALL) {
     460                clear_self_endpoint_halt(pipe);
     461        }
     462
     463        pipe_drop_ref(pipe);
    394464
    395465        if (rc != EOK) {
     
    418488    void *data_buffer, size_t data_buffer_size)
    419489{
     490        /* Ensure serialization over the phone. */
     491        pipe_start_transaction(pipe);
     492
    420493        /*
    421494         * Make call identifying target USB device and control transfer type.
    422495         */
    423         aid_t opening_request = async_send_5(pipe->hc_phone,
     496        aid_t opening_request = async_send_4(pipe->hc_phone,
    424497            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
    425498            pipe->wire->address, pipe->endpoint_no,
    426499            data_buffer_size,
    427             pipe->max_packet_size,
    428500            NULL);
    429501        if (opening_request == 0) {
     502                pipe_end_transaction(pipe);
    430503                return ENOMEM;
    431504        }
     
    437510            setup_buffer, setup_buffer_size);
    438511        if (rc != EOK) {
     512                pipe_end_transaction(pipe);
    439513                async_wait_for(opening_request, NULL);
    440514                return rc;
     
    447521                rc = async_data_write_start(pipe->hc_phone,
    448522                    data_buffer, data_buffer_size);
     523
     524                /* All data sent, pipe can be released. */
     525                pipe_end_transaction(pipe);
     526
    449527                if (rc != EOK) {
    450528                        async_wait_for(opening_request, NULL);
    451529                        return rc;
    452530                }
     531        } else {
     532                /* No data to send, we can release the pipe for others. */
     533                pipe_end_transaction(pipe);
    453534        }
    454535
     
    491572        }
    492573
    493         if (!usb_pipe_is_session_started(pipe)) {
    494                 return EBADF;
    495         }
    496 
    497574        if ((pipe->direction != USB_DIRECTION_BOTH)
    498575            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    500577        }
    501578
    502         int rc = usb_pipe_control_write_no_check(pipe,
     579        int rc;
     580
     581        rc = pipe_add_ref(pipe);
     582        if (rc != EOK) {
     583                return rc;
     584        }
     585
     586        rc = usb_pipe_control_write_no_check(pipe,
    503587            setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
     588
     589        if (rc == ESTALL) {
     590                clear_self_endpoint_halt(pipe);
     591        }
     592
     593        pipe_drop_ref(pipe);
    504594
    505595        return rc;
  • uspace/lib/usb/src/recognise.c

    ref354b6 re50cd7f  
    404404        child->driver_data = dev_data;
    405405
    406         rc = usb_pipe_start_session(&ctrl_pipe);
    407         if (rc != EOK) {
    408                 goto failure;
    409         }
    410 
    411406        rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
    412         if (rc != EOK) {
    413                 goto failure;
    414         }
    415 
    416         rc = usb_pipe_end_session(&ctrl_pipe);
    417407        if (rc != EOK) {
    418408                goto failure;
  • uspace/lib/usb/src/request.c

    ref354b6 re50cd7f  
    871871}
    872872
     873/** Clear halt bit of an endpoint pipe (after pipe stall).
     874 *
     875 * @param pipe Control pipe.
     876 * @param ep_index Endpoint index (in native endianness).
     877 * @return Error code.
     878 */
     879int usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index)
     880{
     881        return usb_request_clear_feature(pipe,
     882            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT,
     883            uint16_host2usb(USB_FEATURE_SELECTOR_ENDPOINT_HALT),
     884            uint16_host2usb(ep_index));
     885}
     886
    873887/**
    874888 * @}
Note: See TracChangeset for help on using the changeset viewer.