Changes in / [fb48a0e:c48f6ab] in mainline


Ignore:
Location:
uspace
Files:
2 deleted
23 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ehci/Makefile

    rfb48a0e rc48f6ab  
    4242
    4343SOURCES = \
    44         hc_iface.c \
    4544        main.c \
    4645        pci.c
  • uspace/drv/bus/usb/ehci/main.c

    rfb48a0e rc48f6ab  
    4242#include <usb/ddfiface.h>
    4343#include <usb/debug.h>
     44#include <usb/host/hcd.h>
    4445
    4546#include "pci.h"
    46 #include "ehci.h"
     47
     48#define NAME "ehci"
    4749
    4850static int ehci_dev_add(ddf_dev_t *device);
     
    5759};
    5860static ddf_dev_ops_t hc_ops = {
    59         .interfaces[USBHC_DEV_IFACE] = &ehci_hc_iface,
     61        .interfaces[USBHC_DEV_IFACE] = &hcd_iface,
    6062};
    6163
     
    9597                return ENOMEM;
    9698        }
     99        hcd_t *ehci_hc = ddf_fun_data_alloc(hc_fun, sizeof(hcd_t));
     100        if (ehci_hc == NULL) {
     101                usb_log_error("Failed to alloc generic HC driver.\n");
     102                return ENOMEM;
     103        }
     104        /* High Speed, no bandwidth */
     105        hcd_init(ehci_hc, USB_SPEED_HIGH, 0, NULL);
    97106        hc_fun->ops = &hc_ops;
    98107
  • uspace/drv/bus/usb/usbmid/explore.c

    rfb48a0e rc48f6ab  
    5454 * @return Interface @p interface_no is already present in the list.
    5555 */
    56 static bool interface_in_list(list_t *list, int interface_no)
     56static bool interface_in_list(const list_t *list, int interface_no)
    5757{
    5858        list_foreach(*list, l) {
  • uspace/drv/bus/usb/usbmid/usbmid.c

    rfb48a0e rc48f6ab  
    4545
    4646/** Callback for DDF USB interface. */
    47 static int usb_iface_get_interface_impl(ddf_fun_t *fun, devman_handle_t handle,
    48     int *iface_no)
     47static int usb_iface_get_interface_impl(ddf_fun_t *fun, int *iface_no)
    4948{
    5049        assert(fun);
     
    6463        .get_hc_handle = usb_iface_get_hc_handle_device_impl,
    6564        .get_my_address = usb_iface_get_my_address_forward_impl,
    66         .get_interface = usb_iface_get_interface_impl,
     65        .get_my_interface = usb_iface_get_interface_impl,
    6766};
    6867
  • uspace/drv/bus/usb/vhc/connhost.c

    rfb48a0e rc48f6ab  
    508508        .request_address = request_address,
    509509        .bind_address = bind_address,
    510         .find_by_address = find_by_address,
     510        .get_handle = find_by_address,
    511511        .release_address = release_address,
    512512
  • uspace/lib/drv/generic/remote_usb.c

    rfb48a0e rc48f6ab  
    11/*
    22 * Copyright (c) 2010 Vojtech Horky
     3 * Copyright (c) 2011 Jan Vesely
    34 * All rights reserved.
    45 *
     
    3940#include "ddf/driver.h"
    4041
     42typedef enum {
     43        IPC_M_USB_GET_MY_ADDRESS,
     44        IPC_M_USB_GET_MY_INTERFACE,
     45        IPC_M_USB_GET_HOST_CONTROLLER_HANDLE,
     46} usb_iface_funcs_t;
     47
     48/** Tell USB address assigned to device.
     49 * @param exch Vaid IPC exchange
     50 * @param address Pointer to address storage place.
     51 * @return Error code.
     52 *
     53 * Exch param is an open communication to device implementing usb_iface.
     54 */
     55int usb_get_my_address(async_exch_t *exch, usb_address_t *address)
     56{
     57        if (!exch)
     58                return EINVAL;
     59        sysarg_t addr;
     60        const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     61            IPC_M_USB_GET_MY_ADDRESS, &addr);
     62
     63        if (ret == EOK && address != NULL)
     64                *address = (usb_address_t) addr;
     65        return ret;
     66}
     67/*----------------------------------------------------------------------------*/
     68/** Tell interface number given device can use.
     69 * @param[in] exch IPC communication exchange
     70 * @param[in] handle Id of the device
     71 * @param[out] usb_iface Assigned USB interface
     72 * @return Error code.
     73 */
     74int usb_get_my_interface(async_exch_t *exch, int *usb_iface)
     75{
     76        if (!exch)
     77                return EINVAL;
     78        sysarg_t iface_no;
     79        const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     80            IPC_M_USB_GET_MY_INTERFACE, &iface_no);
     81        if (ret == EOK && usb_iface)
     82                *usb_iface = (int)iface_no;
     83        return ret;
     84}
     85/*----------------------------------------------------------------------------*/
     86/** Tell devman handle of device host controller.
     87 * @param[in] exch IPC communication exchange
     88 * @param[out] hc_handle devman handle of the HC used by the target device.
     89 * @return Error code.
     90 */
     91int usb_get_hc_handle(async_exch_t *exch, devman_handle_t *hc_handle)
     92{
     93        if (!exch)
     94                return EINVAL;
     95        devman_handle_t h;
     96        const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     97            IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
     98        if (ret == EOK && hc_handle)
     99                *hc_handle = (devman_handle_t)h;
     100        return ret;
     101}
     102
    41103
    42104static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    43 static void remote_usb_get_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     105static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    44106static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    45 //static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *);
    46107
    47108/** Remote USB interface operations. */
    48109static remote_iface_func_ptr_t remote_usb_iface_ops [] = {
    49110        [IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address,
    50         [IPC_M_USB_GET_INTERFACE] = remote_usb_get_interface,
     111        [IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface,
    51112        [IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle,
    52113};
     
    60121};
    61122
    62 
     123/*----------------------------------------------------------------------------*/
    63124void remote_usb_get_my_address(ddf_fun_t *fun, void *iface,
    64125    ipc_callid_t callid, ipc_call_t *call)
    65126{
    66         usb_iface_t *usb_iface = (usb_iface_t *) iface;
     127        const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    67128
    68129        if (usb_iface->get_my_address == NULL) {
     
    72133
    73134        usb_address_t address;
    74         int rc = usb_iface->get_my_address(fun, &address);
    75         if (rc != EOK) {
    76                 async_answer_0(callid, rc);
     135        const int ret = usb_iface->get_my_address(fun, &address);
     136        if (ret != EOK) {
     137                async_answer_0(callid, ret);
    77138        } else {
    78139                async_answer_1(callid, EOK, address);
    79140        }
    80141}
    81 
    82 void remote_usb_get_interface(ddf_fun_t *fun, void *iface,
     142/*----------------------------------------------------------------------------*/
     143void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface,
    83144    ipc_callid_t callid, ipc_call_t *call)
    84145{
    85         usb_iface_t *usb_iface = (usb_iface_t *) iface;
     146        const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    86147
    87         if (usb_iface->get_interface == NULL) {
     148        if (usb_iface->get_my_interface == NULL) {
    88149                async_answer_0(callid, ENOTSUP);
    89150                return;
    90151        }
    91152
    92         devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
    93 
    94153        int iface_no;
    95         int rc = usb_iface->get_interface(fun, handle, &iface_no);
    96         if (rc != EOK) {
    97                 async_answer_0(callid, rc);
     154        const int ret = usb_iface->get_my_interface(fun, &iface_no);
     155        if (ret != EOK) {
     156                async_answer_0(callid, ret);
    98157        } else {
    99158                async_answer_1(callid, EOK, iface_no);
    100159        }
    101160}
    102 
     161/*----------------------------------------------------------------------------*/
    103162void remote_usb_get_hc_handle(ddf_fun_t *fun, void *iface,
    104163    ipc_callid_t callid, ipc_call_t *call)
    105164{
    106         usb_iface_t *usb_iface = (usb_iface_t *) iface;
     165        const usb_iface_t *usb_iface = (usb_iface_t *) iface;
    107166
    108167        if (usb_iface->get_hc_handle == NULL) {
     
    112171
    113172        devman_handle_t handle;
    114         int rc = usb_iface->get_hc_handle(fun, &handle);
    115         if (rc != EOK) {
    116                 async_answer_0(callid, rc);
     173        const int ret = usb_iface->get_hc_handle(fun, &handle);
     174        if (ret != EOK) {
     175                async_answer_0(callid, ret);
    117176        }
    118177
    119178        async_answer_1(callid, EOK, (sysarg_t) handle);
    120179}
    121 
    122 
    123 
    124180/**
    125181 * @}
  • uspace/lib/drv/generic/remote_usbhc.c

    rfb48a0e rc48f6ab  
    11/*
    22 * Copyright (c) 2010-2011 Vojtech Horky
     3 * Copyright (c) 2011 Jan Vesely
    34 * All rights reserved.
    45 *
     
    4243#define USB_MAX_PAYLOAD_SIZE 1020
    4344
     45/** IPC methods for communication with HC through DDF interface.
     46 *
     47 * Notes for async methods:
     48 *
     49 * Methods for sending data to device (OUT transactions)
     50 * - e.g. IPC_M_USBHC_INTERRUPT_OUT -
     51 * always use the same semantics:
     52 * - first, IPC call with given method is made
     53 *   - argument #1 is target address
     54 *   - argument #2 is target endpoint
     55 *   - argument #3 is max packet size of the endpoint
     56 * - this call is immediately followed by IPC data write (from caller)
     57 * - the initial call (and the whole transaction) is answer after the
     58 *   transaction is scheduled by the HC and acknowledged by the device
     59 *   or immediately after error is detected
     60 * - the answer carries only the error code
     61 *
     62 * Methods for retrieving data from device (IN transactions)
     63 * - e.g. IPC_M_USBHC_INTERRUPT_IN -
     64 * also use the same semantics:
     65 * - first, IPC call with given method is made
     66 *   - argument #1 is target address
     67 *   - argument #2 is target endpoint
     68 * - this call is immediately followed by IPC data read (async version)
     69 * - the call is not answered until the device returns some data (or until
     70 *   error occurs)
     71 *
     72 * Some special methods (NO-DATA transactions) do not send any data. These
     73 * might behave as both OUT or IN transactions because communication parts
     74 * where actual buffers are exchanged are omitted.
     75 **
     76 * For all these methods, wrap functions exists. Important rule: functions
     77 * for IN transactions have (as parameters) buffers where retrieved data
     78 * will be stored. These buffers must be already allocated and shall not be
     79 * touch until the transaction is completed
     80 * (e.g. not before calling usb_wait_for() with appropriate handle).
     81 * OUT transactions buffers can be freed immediately after call is dispatched
     82 * (i.e. after return from wrapping function).
     83 *
     84 */
     85typedef enum {
     86        /** Asks for address assignment by host controller.
     87         * Answer:
     88         * - ELIMIT - host controller run out of address
     89         * - EOK - address assigned
     90         * Answer arguments:
     91         * - assigned address
     92         *
     93         * The address must be released by via IPC_M_USBHC_RELEASE_ADDRESS.
     94         */
     95        IPC_M_USBHC_REQUEST_ADDRESS,
     96
     97        /** Bind USB address with devman handle.
     98         * Parameters:
     99         * - USB address
     100         * - devman handle
     101         * Answer:
     102         * - EOK - address binded
     103         * - ENOENT - address is not in use
     104         */
     105        IPC_M_USBHC_BIND_ADDRESS,
     106
     107        /** Get handle binded with given USB address.
     108         * Parameters
     109         * - USB address
     110         * Answer:
     111         * - EOK - address binded, first parameter is the devman handle
     112         * - ENOENT - address is not in use at the moment
     113         */
     114        IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,
     115
     116        /** Release address in use.
     117         * Arguments:
     118         * - address to be released
     119         * Answer:
     120         * - ENOENT - address not in use
     121         * - EPERM - trying to release default USB address
     122         */
     123        IPC_M_USBHC_RELEASE_ADDRESS,
     124
     125        /** Register endpoint attributes at host controller.
     126         * This is used to reserve portion of USB bandwidth.
     127         * When speed is invalid, speed of the device is used.
     128         * Parameters:
     129         * - USB address + endpoint number
     130         *   - packed as ADDR << 16 + EP
     131         * - speed + transfer type + direction
     132         *   - packed as ( SPEED << 8 + TYPE ) << 8 + DIR
     133         * - maximum packet size + interval (in milliseconds)
     134         *   - packed as MPS << 16 + INT
     135         * Answer:
     136         * - EOK - reservation successful
     137         * - ELIMIT - not enough bandwidth to satisfy the request
     138         */
     139        IPC_M_USBHC_REGISTER_ENDPOINT,
     140
     141        /** Revert endpoint registration.
     142         * Parameters:
     143         * - USB address
     144         * - endpoint number
     145         * - data direction
     146         * Answer:
     147         * - EOK - endpoint unregistered
     148         * - ENOENT - unknown endpoint
     149         */
     150        IPC_M_USBHC_UNREGISTER_ENDPOINT,
     151
     152        /** Get data from device.
     153         * See explanation at usb_iface_funcs_t (IN transaction).
     154         */
     155        IPC_M_USBHC_READ,
     156
     157        /** Send data to device.
     158         * See explanation at usb_iface_funcs_t (OUT transaction).
     159         */
     160        IPC_M_USBHC_WRITE,
     161} usbhc_iface_funcs_t;
     162
     163int usbhc_request_address(async_exch_t *exch, usb_address_t *address,
     164    bool strict, usb_speed_t speed)
     165{
     166        if (!exch || !address)
     167                return EINVAL;
     168        sysarg_t new_address;
     169        const int ret = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     170            IPC_M_USBHC_REQUEST_ADDRESS, *address, strict, speed, &new_address);
     171        if (ret == EOK)
     172                *address = (usb_address_t)new_address;
     173        return ret;
     174}
     175/*----------------------------------------------------------------------------*/
     176int usbhc_bind_address(async_exch_t *exch, usb_address_t address,
     177    devman_handle_t handle)
     178{
     179        if (!exch)
     180                return EINVAL;
     181        return async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     182            IPC_M_USBHC_BIND_ADDRESS, address, handle);
     183}
     184/*----------------------------------------------------------------------------*/
     185int usbhc_get_handle(async_exch_t *exch, usb_address_t address,
     186    devman_handle_t *handle)
     187{
     188        if (!exch)
     189                return EINVAL;
     190        sysarg_t h;
     191        const int ret = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     192            IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, address, &h);
     193        if (ret == EOK && handle)
     194                *handle = (devman_handle_t)h;
     195        return ret;
     196}
     197/*----------------------------------------------------------------------------*/
     198int usbhc_release_address(async_exch_t *exch, usb_address_t address)
     199{
     200        if (!exch)
     201                return EINVAL;
     202        return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     203            IPC_M_USBHC_RELEASE_ADDRESS, address);
     204}
     205/*----------------------------------------------------------------------------*/
     206int usbhc_register_endpoint(async_exch_t *exch, usb_address_t address,
     207    usb_endpoint_t endpoint, usb_transfer_type_t type,
     208    usb_direction_t direction, size_t mps, unsigned interval)
     209{
     210        if (!exch)
     211                return EINVAL;
     212        const usb_target_t target =
     213            {{ .address = address, .endpoint = endpoint }};
     214#define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff))
     215
     216        return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     217            IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,
     218            _PACK2(type, direction), _PACK2(mps, interval));
     219
     220#undef _PACK2
     221}
     222/*----------------------------------------------------------------------------*/
     223int usbhc_unregister_endpoint(async_exch_t *exch, usb_address_t address,
     224    usb_endpoint_t endpoint, usb_direction_t direction)
     225{
     226        if (!exch)
     227                return EINVAL;
     228        return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     229            IPC_M_USBHC_UNREGISTER_ENDPOINT, address, endpoint, direction);
     230}
     231/*----------------------------------------------------------------------------*/
     232int usbhc_read(async_exch_t *exch, usb_address_t address,
     233    usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size,
     234    size_t *rec_size)
     235{
     236        if (size == 0 && setup == 0)
     237                return EOK;
     238
     239        if (!exch)
     240                return EINVAL;
     241        const usb_target_t target =
     242            {{ .address = address, .endpoint = endpoint }};
     243
     244        /* Make call identifying target USB device and type of transfer. */
     245        aid_t opening_request = async_send_4(exch,
     246            DEV_IFACE_ID(USBHC_DEV_IFACE),
     247            IPC_M_USBHC_READ, target.packed,
     248            (setup & UINT32_MAX), (setup >> 32), NULL);
     249
     250        if (opening_request == 0) {
     251                return ENOMEM;
     252        }
     253
     254        /* Retrieve the data. */
     255        ipc_call_t data_request_call;
     256        aid_t data_request =
     257            async_data_read(exch, data, size, &data_request_call);
     258
     259        if (data_request == 0) {
     260                // FIXME: How to let the other side know that we want to abort?
     261                async_wait_for(opening_request, NULL);
     262                return ENOMEM;
     263        }
     264
     265        /* Wait for the answer. */
     266        sysarg_t data_request_rc;
     267        sysarg_t opening_request_rc;
     268        async_wait_for(data_request, &data_request_rc);
     269        async_wait_for(opening_request, &opening_request_rc);
     270
     271        if (data_request_rc != EOK) {
     272                /* Prefer the return code of the opening request. */
     273                if (opening_request_rc != EOK) {
     274                        return (int) opening_request_rc;
     275                } else {
     276                        return (int) data_request_rc;
     277                }
     278        }
     279        if (opening_request_rc != EOK) {
     280                return (int) opening_request_rc;
     281        }
     282
     283        *rec_size = IPC_GET_ARG2(data_request_call);
     284        return EOK;
     285}
     286/*----------------------------------------------------------------------------*/
     287int usbhc_write(async_exch_t *exch, usb_address_t address,
     288    usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size)
     289{
     290        if (size == 0 && setup == 0)
     291                return EOK;
     292
     293        if (!exch)
     294                return EINVAL;
     295        const usb_target_t target =
     296            {{ .address = address, .endpoint = endpoint }};
     297
     298        aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     299            IPC_M_USBHC_WRITE, target.packed, size,
     300            (setup & UINT32_MAX), (setup >> 32), NULL);
     301
     302        if (opening_request == 0) {
     303                return ENOMEM;
     304        }
     305
     306        /* Send the data if any. */
     307        if (size > 0) {
     308                const int ret = async_data_write_start(exch, data, size);
     309                if (ret != EOK) {
     310                        async_wait_for(opening_request, NULL);
     311                        return ret;
     312                }
     313        }
     314
     315        /* Wait for the answer. */
     316        sysarg_t opening_request_rc;
     317        async_wait_for(opening_request, &opening_request_rc);
     318
     319        return (int) opening_request_rc;
     320}
     321/*----------------------------------------------------------------------------*/
     322
    44323static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    45324static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    46 static void remote_usbhc_find_by_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     325static void remote_usbhc_get_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    47326static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    48327static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     
    57336        [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,
    58337        [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address,
    59         [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_find_by_address,
     338        [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_get_handle,
    60339
    61340        [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
     
    78357        ipc_callid_t data_caller;
    79358        void *buffer;
    80         size_t size;
    81359} async_transaction_t;
    82360
     
    103381        trans->data_caller = 0;
    104382        trans->buffer = NULL;
    105         trans->size = 0;
    106383
    107384        return trans;
    108385}
    109 
     386/*----------------------------------------------------------------------------*/
    110387void remote_usbhc_request_address(ddf_fun_t *fun, void *iface,
    111388    ipc_callid_t callid, ipc_call_t *call)
    112389{
    113         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     390        const usbhc_iface_t *usb_iface = iface;
    114391
    115392        if (!usb_iface->request_address) {
     
    129406        }
    130407}
    131 
     408/*----------------------------------------------------------------------------*/
    132409void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface,
    133410    ipc_callid_t callid, ipc_call_t *call)
    134411{
    135         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     412        const usbhc_iface_t *usb_iface = iface;
    136413
    137414        if (!usb_iface->bind_address) {
     
    140417        }
    141418
    142         usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
    143         devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call);
    144 
    145         int rc = usb_iface->bind_address(fun, address, handle);
    146 
    147         async_answer_0(callid, rc);
    148 }
    149 
    150 void remote_usbhc_find_by_address(ddf_fun_t *fun, void *iface,
     419        const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
     420        const devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call);
     421
     422        const int ret = usb_iface->bind_address(fun, address, handle);
     423        async_answer_0(callid, ret);
     424}
     425/*----------------------------------------------------------------------------*/
     426void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface,
    151427    ipc_callid_t callid, ipc_call_t *call)
    152428{
    153         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    154 
    155         if (!usb_iface->find_by_address) {
    156                 async_answer_0(callid, ENOTSUP);
    157                 return;
    158         }
    159 
    160         usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
     429        const usbhc_iface_t *usb_iface = iface;
     430
     431        if (!usb_iface->get_handle) {
     432                async_answer_0(callid, ENOTSUP);
     433                return;
     434        }
     435
     436        const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
    161437        devman_handle_t handle;
    162         int rc = usb_iface->find_by_address(fun, address, &handle);
    163 
    164         if (rc == EOK) {
    165                 async_answer_1(callid, EOK, handle);
     438        const int ret = usb_iface->get_handle(fun, address, &handle);
     439
     440        if (ret == EOK) {
     441                async_answer_1(callid, ret, handle);
    166442        } else {
    167                 async_answer_0(callid, rc);
    168         }
    169 }
    170 
     443                async_answer_0(callid, ret);
     444        }
     445}
     446/*----------------------------------------------------------------------------*/
    171447void remote_usbhc_release_address(ddf_fun_t *fun, void *iface,
    172448    ipc_callid_t callid, ipc_call_t *call)
    173449{
    174         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
     450        const usbhc_iface_t *usb_iface = iface;
    175451
    176452        if (!usb_iface->release_address) {
     
    179455        }
    180456
    181         usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
    182 
    183         int rc = usb_iface->release_address(fun, address);
    184 
    185         async_answer_0(callid, rc);
    186 }
    187 
    188 
     457        const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
     458
     459        const int ret = usb_iface->release_address(fun, address);
     460        async_answer_0(callid, ret);
     461}
     462/*----------------------------------------------------------------------------*/
    189463static void callback_out(ddf_fun_t *fun,
    190464    int outcome, void *arg)
    191465{
    192         async_transaction_t *trans = (async_transaction_t *)arg;
     466        async_transaction_t *trans = arg;
    193467
    194468        async_answer_0(trans->caller, outcome);
     
    196470        async_transaction_destroy(trans);
    197471}
    198 
     472/*----------------------------------------------------------------------------*/
    199473static void callback_in(ddf_fun_t *fun,
    200474    int outcome, size_t actual_size, void *arg)
     
    211485        }
    212486
    213         trans->size = actual_size;
    214 
    215487        if (trans->data_caller) {
    216488                async_data_read_finalize(trans->data_caller,
     
    222494        async_transaction_destroy(trans);
    223495}
    224 
     496/*----------------------------------------------------------------------------*/
    225497void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
    226498    ipc_callid_t callid, ipc_call_t *call)
     
    300572        }
    301573
    302         if (!async_data_read_receive(&trans->data_caller, &trans->size)) {
     574        size_t size = 0;
     575        if (!async_data_read_receive(&trans->data_caller, &size)) {
    303576                async_answer_0(callid, EPARTY);
    304577                return;
    305578        }
    306579
    307         trans->buffer = malloc(trans->size);
     580        trans->buffer = malloc(size);
    308581        if (trans->buffer == NULL) {
    309582                async_answer_0(trans->data_caller, ENOMEM);
     
    313586
    314587        const int rc = hc_iface->read(
    315             fun, target, setup, trans->buffer, trans->size, callback_in, trans);
     588            fun, target, setup, trans->buffer, size, callback_in, trans);
    316589
    317590        if (rc != EOK) {
     
    321594        }
    322595}
    323 
     596/*----------------------------------------------------------------------------*/
    324597void remote_usbhc_write(
    325598    ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
     
    348621        }
    349622
     623        size_t size = 0;
    350624        if (data_buffer_len > 0) {
    351                 int rc = async_data_write_accept(&trans->buffer, false,
     625                const int rc = async_data_write_accept(&trans->buffer, false,
    352626                    1, USB_MAX_PAYLOAD_SIZE,
    353                     0, &trans->size);
     627                    0, &size);
    354628
    355629                if (rc != EOK) {
     
    360634        }
    361635
    362         int rc = hc_iface->write(
    363             fun, target, setup, trans->buffer, trans->size, callback_out, trans);
     636        const int rc = hc_iface->write(
     637            fun, target, setup, trans->buffer, size, callback_out, trans);
    364638
    365639        if (rc != EOK) {
     
    368642        }
    369643}
    370 
    371 
    372644/**
    373645 * @}
  • uspace/lib/drv/include/usb_iface.h

    rfb48a0e rc48f6ab  
    3939
    4040#include "ddf/driver.h"
     41#include <async.h>
    4142#include <usb/usb.h>
    42 typedef enum {
    43         /** Tell USB address assigned to device.
    44          * Parameters:
    45          * - devman handle id
    46          * Answer:
    47          * - EINVAL - unknown handle or handle not managed by this driver
    48          * - ENOTSUP - operation not supported (shall not happen)
    49          * - arbitrary error code if returned by remote implementation
    50          * - EOK - handle found, first parameter contains the USB address
    51          *
    52          * The handle must be the one used for binding USB address with
    53          * it (IPC_M_USBHC_BIND_ADDRESS), otherwise the host controller
    54          * (that this request would eventually reach) would not be able
    55          * to find it.
    56          * The problem is that this handle is actually assigned to the
    57          * function inside driver of the parent device (usually hub driver).
    58          * To bypass this problem, the initial caller specify handle as
    59          * zero and the first parent assigns the actual value.
    60          * See usb_iface_get_address_hub_child_impl() implementation
    61          * that could be assigned to device ops of a child device of in a
    62          * hub driver.
    63          * For example, the USB multi interface device driver (MID)
    64          * passes this initial zero without any modification because the
    65          * handle must be resolved by its parent.
    66          */
    67         IPC_M_USB_GET_MY_ADDRESS,
    6843
    69         /** Tell interface number given device can use.
    70          * Parameters
    71          * - devman handle id of the device
    72          * Answer:
    73          * - ENOTSUP - operation not supported (can also mean any interface)
    74          * - EOK - operation okay, first parameter contains interface number
    75          */
    76         IPC_M_USB_GET_INTERFACE,
    77 
    78         /** Tell devman handle of device host controller.
    79          * Parameters:
    80          * - none
    81          * Answer:
    82          * - EOK - request processed without errors
    83          * - ENOTSUP - this indicates invalid USB driver
    84          * Parameters of the answer:
    85          * - devman handle of HC caller is physically connected to
    86          */
    87         IPC_M_USB_GET_HOST_CONTROLLER_HANDLE
    88 } usb_iface_funcs_t;
     44int usb_get_my_address(async_exch_t *, usb_address_t *);
     45int usb_get_my_interface(async_exch_t *, int *);
     46int usb_get_hc_handle(async_exch_t *, devman_handle_t *);
    8947
    9048/** USB device communication interface. */
    9149typedef struct {
    9250        int (*get_my_address)(ddf_fun_t *, usb_address_t *);
    93         int (*get_interface)(ddf_fun_t *, devman_handle_t, int *);
     51        int (*get_my_interface)(ddf_fun_t *, int *);
    9452        int (*get_hc_handle)(ddf_fun_t *, devman_handle_t *);
    9553} usb_iface_t;
    96 
    9754
    9855#endif
  • uspace/lib/drv/include/usbhc_iface.h

    rfb48a0e rc48f6ab  
    4242#include <bool.h>
    4343
    44 
    45 /** IPC methods for communication with HC through DDF interface.
    46  *
    47  * Notes for async methods:
    48  *
    49  * Methods for sending data to device (OUT transactions)
    50  * - e.g. IPC_M_USBHC_INTERRUPT_OUT -
    51  * always use the same semantics:
    52  * - first, IPC call with given method is made
    53  *   - argument #1 is target address
    54  *   - argument #2 is target endpoint
    55  *   - argument #3 is max packet size of the endpoint
    56  * - this call is immediately followed by IPC data write (from caller)
    57  * - the initial call (and the whole transaction) is answer after the
    58  *   transaction is scheduled by the HC and acknowledged by the device
    59  *   or immediately after error is detected
    60  * - the answer carries only the error code
    61  *
    62  * Methods for retrieving data from device (IN transactions)
    63  * - e.g. IPC_M_USBHC_INTERRUPT_IN -
    64  * also use the same semantics:
    65  * - first, IPC call with given method is made
    66  *   - argument #1 is target address
    67  *   - argument #2 is target endpoint
    68  * - this call is immediately followed by IPC data read (async version)
    69  * - the call is not answered until the device returns some data (or until
    70  *   error occurs)
    71  *
    72  * Some special methods (NO-DATA transactions) do not send any data. These
    73  * might behave as both OUT or IN transactions because communication parts
    74  * where actual buffers are exchanged are omitted.
    75  **
    76  * For all these methods, wrap functions exists. Important rule: functions
    77  * for IN transactions have (as parameters) buffers where retrieved data
    78  * will be stored. These buffers must be already allocated and shall not be
    79  * touch until the transaction is completed
    80  * (e.g. not before calling usb_wait_for() with appropriate handle).
    81  * OUT transactions buffers can be freed immediately after call is dispatched
    82  * (i.e. after return from wrapping function).
    83  *
    84  */
    85 typedef enum {
    86         /** Asks for address assignment by host controller.
    87          * Answer:
    88          * - ELIMIT - host controller run out of address
    89          * - EOK - address assigned
    90          * Answer arguments:
    91          * - assigned address
    92          *
    93          * The address must be released by via IPC_M_USBHC_RELEASE_ADDRESS.
    94          */
    95         IPC_M_USBHC_REQUEST_ADDRESS,
    96 
    97         /** Bind USB address with devman handle.
    98          * Parameters:
    99          * - USB address
    100          * - devman handle
    101          * Answer:
    102          * - EOK - address binded
    103          * - ENOENT - address is not in use
    104          */
    105         IPC_M_USBHC_BIND_ADDRESS,
    106 
    107         /** Get handle binded with given USB address.
    108          * Parameters
    109          * - USB address
    110          * Answer:
    111          * - EOK - address binded, first parameter is the devman handle
    112          * - ENOENT - address is not in use at the moment
    113          */
    114         IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,
    115 
    116         /** Release address in use.
    117          * Arguments:
    118          * - address to be released
    119          * Answer:
    120          * - ENOENT - address not in use
    121          * - EPERM - trying to release default USB address
    122          */
    123         IPC_M_USBHC_RELEASE_ADDRESS,
    124 
    125         /** Register endpoint attributes at host controller.
    126          * This is used to reserve portion of USB bandwidth.
    127          * When speed is invalid, speed of the device is used.
    128          * Parameters:
    129          * - USB address + endpoint number
    130          *   - packed as ADDR << 16 + EP
    131          * - speed + transfer type + direction
    132          *   - packed as ( SPEED << 8 + TYPE ) << 8 + DIR
    133          * - maximum packet size + interval (in milliseconds)
    134          *   - packed as MPS << 16 + INT
    135          * Answer:
    136          * - EOK - reservation successful
    137          * - ELIMIT - not enough bandwidth to satisfy the request
    138          */
    139         IPC_M_USBHC_REGISTER_ENDPOINT,
    140 
    141         /** Revert endpoint registration.
    142          * Parameters:
    143          * - USB address
    144          * - endpoint number
    145          * - data direction
    146          * Answer:
    147          * - EOK - endpoint unregistered
    148          * - ENOENT - unknown endpoint
    149          */
    150         IPC_M_USBHC_UNREGISTER_ENDPOINT,
    151 
    152         /** Get data from device.
    153          * See explanation at usb_iface_funcs_t (IN transaction).
    154          */
    155         IPC_M_USBHC_READ,
    156 
    157         /** Send data to device.
    158          * See explanation at usb_iface_funcs_t (OUT transaction).
    159          */
    160         IPC_M_USBHC_WRITE,
    161 } usbhc_iface_funcs_t;
     44int usbhc_request_address(async_exch_t *, usb_address_t *, bool, usb_speed_t);
     45int usbhc_bind_address(async_exch_t *, usb_address_t, devman_handle_t);
     46int usbhc_get_handle(async_exch_t *, usb_address_t, devman_handle_t *);
     47int usbhc_release_address(async_exch_t *, usb_address_t);
     48int usbhc_register_endpoint(async_exch_t *, usb_address_t,  usb_endpoint_t,
     49    usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
     50int usbhc_unregister_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t,
     51    usb_direction_t);
     52int usbhc_read(async_exch_t *, usb_address_t, usb_endpoint_t,
     53    uint64_t, void *, size_t, size_t *);
     54int usbhc_write(async_exch_t *, usb_address_t, usb_endpoint_t,
     55    uint64_t, const void *, size_t);
    16256
    16357/** Callback for outgoing transfer. */
     
    17266        int (*request_address)(ddf_fun_t *, usb_address_t *, bool, usb_speed_t);
    17367        int (*bind_address)(ddf_fun_t *, usb_address_t, devman_handle_t);
    174         int (*find_by_address)(ddf_fun_t *, usb_address_t, devman_handle_t *);
     68        int (*get_handle)(ddf_fun_t *, usb_address_t,
     69            devman_handle_t *);
    17570        int (*release_address)(ddf_fun_t *, usb_address_t);
    17671
  • uspace/lib/usb/src/ddfiface.c

    rfb48a0e rc48f6ab  
    3636#include <devman.h>
    3737#include <async.h>
     38#include <usb_iface.h>
    3839#include <usb/ddfiface.h>
    3940#include <usb/hc.h>
     
    104105
    105106        async_exch_t *exch = async_exchange_begin(parent_sess);
     107        if (!exch) {
     108                async_hangup(parent_sess);
     109                return ENOMEM;
     110        }
    106111
    107         sysarg_t addr;
    108         int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    109             IPC_M_USB_GET_MY_ADDRESS, &addr);
     112        const int ret = usb_get_my_address(exch, address);
    110113
    111114        async_exchange_end(exch);
    112115        async_hangup(parent_sess);
    113116
    114         if (rc != EOK)
    115                 return rc;
    116 
    117         if (address != NULL)
    118                 *address = (usb_address_t) addr;
    119 
    120         return EOK;
     117        return ret;
    121118}
    122119
  • uspace/lib/usb/src/hc.c

    rfb48a0e rc48f6ab  
    153153        if (!usb_hc_connection_is_opened(connection))
    154154                return ENOENT;
    155        
     155
    156156        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
    157        
    158         sysarg_t tmp;
    159         int rc = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    160             IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,
    161             address, &tmp);
    162        
     157        if (!exch)
     158                return ENOMEM;
     159        const int ret = usbhc_get_handle(exch, address, handle);
    163160        async_exchange_end(exch);
    164        
    165         if ((rc == EOK) && (handle != NULL))
    166                 *handle = tmp;
    167        
    168         return rc;
     161        return ret;
    169162}
    170163
     
    181174        if (!parent_sess)
    182175                return ENOMEM;
    183        
     176
    184177        async_exch_t *exch = async_exchange_begin(parent_sess);
    185        
    186         sysarg_t address;
    187         int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    188             IPC_M_USB_GET_MY_ADDRESS, &address);
    189        
     178        if (!exch) {
     179                async_hangup(parent_sess);
     180                return ENOMEM;
     181        }
     182        usb_address_t address;
     183        const int ret = usb_get_my_address(exch, &address);
     184
    190185        async_exchange_end(exch);
    191186        async_hangup(parent_sess);
    192        
    193         if (rc != EOK)
    194                 return rc;
    195        
    196         return (usb_address_t) address;
     187
     188        if (ret != EOK)
     189                return ret;
     190
     191        return address;
    197192}
    198193
     
    231226        if (!parent_sess)
    232227                return ENOMEM;
    233        
     228
    234229        async_exch_t *exch = async_exchange_begin(parent_sess);
    235        
    236         devman_handle_t h;
    237         int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    238             IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
    239        
     230        if (!exch) {
     231                async_hangup(parent_sess);
     232                return ENOMEM;
     233        }
     234        const int ret = usb_get_hc_handle(exch, hc_handle);
     235
    240236        async_exchange_end(exch);
    241237        async_hangup(parent_sess);
    242        
    243         if (rc != EOK)
    244                 return rc;
    245        
    246         if (hc_handle != NULL)
    247                 *hc_handle = h;
    248        
    249         return EOK;
     238
     239        return ret;
    250240}
    251241
  • uspace/lib/usbdev/include/usb/dev/pipes.h

    rfb48a0e rc48f6ab  
    179179
    180180int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *);
    181 int usb_pipe_write(usb_pipe_t *, void *, size_t);
     181int usb_pipe_write(usb_pipe_t *, const void *, size_t);
    182182
    183183int usb_pipe_control_read(usb_pipe_t *, const void *, size_t,
  • uspace/lib/usbdev/include/usb/dev/request.h

    rfb48a0e rc48f6ab  
    8282         */
    8383        uint8_t request_type;
     84#define SETUP_REQUEST_TYPE_DEVICE_TO_HOST (1 << 7)
     85
    8486        /** Request identification. */
    8587        uint8_t request;
  • uspace/lib/usbdev/src/altiface.c

    rfb48a0e rc48f6ab  
    6565        size_t alternate_count = 0;
    6666
    67         const uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
    68             &dp_data, config_descr);
     67        const void *iface_ptr =
     68            usb_dp_get_nested_descriptor(&dp_parser, &dp_data, config_descr);
    6969        while (iface_ptr != NULL) {
    70                 usb_standard_interface_descriptor_t *iface
    71                     = (usb_standard_interface_descriptor_t *) iface_ptr;
    72                 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) {
    73                         if (iface->interface_number == interface_no) {
    74                                 alternate_count++;
    75                         }
     70                const usb_standard_interface_descriptor_t *iface = iface_ptr;
     71                if (iface->descriptor_type == USB_DESCTYPE_INTERFACE
     72                    && iface->interface_number == interface_no) {
     73                        ++alternate_count;
    7674                }
    7775                iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
     
    8280}
    8381
    84 /** Create alternate interface representation structure.
     82/** Initialize alternate interface representation structure.
    8583 *
     84 * @param[in] alternates Pointer to allocated structure.
    8685 * @param[in] config_descr Configuration descriptor.
    8786 * @param[in] config_descr_size Size of configuration descriptor.
    8887 * @param[in] interface_number Interface number.
    89  * @param[out] alternates_ptr Where to store pointer to allocated structure.
    9088 * @return Error code.
    9189 */
     
    10199        alternates->current = 0;
    102100
     101        /* No interfaces. */
    103102        if (interface_number < 0) {
    104103                return EOK;
     
    107106        alternates->alternative_count
    108107            = usb_interface_count_alternates(config_descr, config_descr_size,
    109             interface_number);
     108                interface_number);
    110109
    111110        if (alternates->alternative_count == 0) {
     
    128127        };
    129128
    130         usb_alternate_interface_descriptors_t *cur_alt_iface
     129        usb_alternate_interface_descriptors_t *iterator
    131130            = &alternates->alternatives[0];
    132131
    133         const uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
    134             &dp_data, dp_data.data);
    135         while (iface_ptr != NULL) {
    136                 usb_standard_interface_descriptor_t *iface
    137                     = (usb_standard_interface_descriptor_t *) iface_ptr;
     132        const usb_alternate_interface_descriptors_t *end
     133            = &alternates->alternatives[alternates->alternative_count];
     134
     135        const void *iface_ptr =
     136            usb_dp_get_nested_descriptor(&dp_parser, &dp_data, dp_data.data);
     137
     138        while (iface_ptr != NULL && iterator < end) {
     139                const usb_standard_interface_descriptor_t *iface = iface_ptr;
     140
    138141                if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE)
    139142                    || (iface->interface_number != interface_number)) {
     143                        /* This is not a valid alternate interface descriptor
     144                         * for interface with number == interface_number. */
    140145                        iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
    141146                            &dp_data, dp_data.data, iface_ptr);
     
    143148                }
    144149
    145                 cur_alt_iface->interface = iface;
    146                 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);
     150                iterator->interface = iface;
     151                iterator->nested_descriptors = iface_ptr + sizeof(*iface);
    147152
    148153                /* Find next interface to count size of nested descriptors. */
    149154                iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
    150155                    dp_data.data, iface_ptr);
    151                 if (iface_ptr == NULL) {
    152                         const uint8_t *next = dp_data.data + dp_data.size;
    153                         cur_alt_iface->nested_descriptors_size
    154                             = next - cur_alt_iface->nested_descriptors;
    155                 } else {
    156                         cur_alt_iface->nested_descriptors_size
    157                             = iface_ptr - cur_alt_iface->nested_descriptors;
    158                 }
    159156
    160                 cur_alt_iface++;
     157                const uint8_t *next = (iface_ptr == NULL) ?
     158                    dp_data.data + dp_data.size : iface_ptr;
     159
     160                iterator->nested_descriptors_size
     161                    = next - iterator->nested_descriptors;
     162
     163                ++iterator;
    161164        }
    162165
  • uspace/lib/usbdev/src/devpoll.c

    rfb48a0e rc48f6ab  
    4646/** Data needed for polling. */
    4747typedef 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 *);
     48        usb_device_auto_polling_t auto_polling;
    5549
    5650        usb_device_t *dev;
     
    6963static int polling_fibril(void *arg)
    7064{
    71         polling_data_t *polling_data = (polling_data_t *) arg;
    72         assert(polling_data);
     65        assert(arg);
     66        const polling_data_t *data = arg;
     67        /* Helper to reduce typing. */
     68        const usb_device_auto_polling_t *params = &data->auto_polling;
    7369
    7470        usb_pipe_t *pipe
    75             = &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];
     71            = &data->dev->pipes[data->pipe_index].pipe;
     72
     73        if (params->debug > 0) {
     74                const usb_endpoint_mapping_t *mapping
     75                    = &data->dev->pipes[data->pipe_index];
    8076                usb_log_debug("Poll%p: started polling of `%s' - " \
    8177                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
    82                     polling_data,
    83                     polling_data->dev->ddf_dev->name,
     78                    data, data->dev->ddf_dev->name,
    8479                    (int) mapping->interface->interface_number,
    8580                    usb_str_class(mapping->interface->interface_class),
    8681                    (int) mapping->interface->interface_subclass,
    8782                    (int) mapping->interface->interface_protocol,
    88                     polling_data->request_size, pipe->max_packet_size);
    89         }
    90 
     83                    data->request_size, pipe->max_packet_size);
     84        }
     85
     86        usb_pipe_start_long_transfer(pipe);
    9187        size_t failed_attempts = 0;
    92         while (failed_attempts <= polling_data->max_failures) {
    93                 int rc;
    94 
     88        while (failed_attempts <= params->max_failures) {
    9589                size_t actual_size;
    96                 rc = usb_pipe_read(pipe, polling_data->buffer,
    97                     polling_data->request_size, &actual_size);
    98 
    99                 if (polling_data->debug > 1) {
     90                const int rc = usb_pipe_read(pipe, data->buffer,
     91                    data->request_size, &actual_size);
     92
     93                if (params->debug > 1) {
    10094                        if (rc == EOK) {
    10195                                usb_log_debug(
    10296                                    "Poll%p: received: '%s' (%zuB).\n",
    103                                     polling_data,
    104                                     usb_debug_str_buffer(polling_data->buffer,
     97                                    data,
     98                                    usb_debug_str_buffer(data->buffer,
    10599                                        actual_size, 16),
    106100                                    actual_size);
     
    108102                                usb_log_debug(
    109103                                    "Poll%p: polling failed: %s.\n",
    110                                     polling_data, str_error(rc));
     104                                    data, str_error(rc));
    111105                        }
    112106                }
    113107
    114108                /* If the pipe stalled, we can try to reset the stall. */
    115                 if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
     109                if ((rc == ESTALL) && (params->auto_clear_halt)) {
    116110                        /*
    117111                         * We ignore error here as this is usually a futile
     
    119113                         */
    120114                        usb_request_clear_endpoint_halt(
    121                             &polling_data->dev->ctrl_pipe,
    122                             pipe->endpoint_no);
     115                            &data->dev->ctrl_pipe, pipe->endpoint_no);
    123116                }
    124117
    125118                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                                 }
     119                        ++failed_attempts;
     120                        const bool cont = (params->on_error == NULL) ? true :
     121                            params->on_error(data->dev, rc, data->custom_arg);
     122                        if (!cont) {
     123                                failed_attempts = params->max_failures;
    134124                        }
    135                         failed_attempts++;
    136125                        continue;
    137126                }
    138127
    139128                /* We have the data, execute the callback now. */
    140                 bool carry_on = polling_data->on_data(polling_data->dev,
    141                     polling_data->buffer, actual_size,
    142                     polling_data->custom_arg);
     129                assert(params->on_data);
     130                const bool carry_on = params->on_data(
     131                    data->dev, data->buffer, actual_size, data->custom_arg);
    143132
    144133                if (!carry_on) {
     134                        /* This is user requested abort, erases failures. */
    145135                        failed_attempts = 0;
    146136                        break;
     
    151141
    152142                /* 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,
    158                     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");
     143                async_usleep(params->delay);
     144        }
     145
     146        usb_pipe_end_long_transfer(pipe);
     147
     148        const bool failed = failed_attempts > 0;
     149
     150        if (params->on_polling_end != NULL) {
     151                params->on_polling_end(data->dev, failed, data->custom_arg);
     152        }
     153
     154        if (params->debug > 0) {
     155                if (failed) {
     156                        usb_log_error("Polling of device `%s' terminated: "
     157                            "recurring failures.\n", data->dev->ddf_dev->name);
    167158                } else {
    168                         usb_log_debug(
    169                             "Polling of device `%s' terminated by user.\n",
    170                             polling_data->dev->ddf_dev->name
    171                         );
     159                        usb_log_debug("Polling of device `%s' terminated: "
     160                            "driver request.\n", data->dev->ddf_dev->name);
    172161                }
    173162        }
    174163
    175164        /* Free the allocated memory. */
    176         free(polling_data->buffer);
    177         free(polling_data);
     165        free(data->buffer);
     166        free(data);
    178167
    179168        return EOK;
     
    202191    usb_polling_terminted_callback_t terminated_callback, void *arg)
    203192{
    204         if ((dev == NULL) || (callback == NULL)) {
    205                 return EBADMEM;
    206         }
    207         if (request_size == 0) {
    208                 return EINVAL;
    209         }
    210         if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)
    211             || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
    212                 return EINVAL;
    213         }
    214 
    215193        const usb_device_auto_polling_t auto_polling = {
    216194                .debug = 1,
     
    248226    size_t request_size, void *arg)
    249227{
    250         if (dev == NULL) {
     228        if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) {
    251229                return EBADMEM;
    252230        }
    253         if (pipe_index >= dev->pipes_count) {
     231
     232        if (pipe_index >= dev->pipes_count || request_size == 0) {
    254233                return EINVAL;
    255234        }
     
    257236            || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
    258237                return EINVAL;
    259         }
    260         if ((polling == NULL) || (polling->on_data == NULL)) {
    261                 return EBADMEM;
    262238        }
    263239
     
    278254        polling_data->custom_arg = arg;
    279255
    280         polling_data->debug = polling->debug;
    281         polling_data->max_failures = polling->max_failures;
    282         if (polling->delay >= 0) {
    283                 polling_data->delay = (useconds_t) polling->delay;
    284         } else {
    285                 polling_data->delay = (useconds_t) dev->pipes[pipe_index]
    286                     .descriptor->poll_interval;
    287         }
    288         polling_data->auto_clear_halt = polling->auto_clear_halt;
    289 
    290         polling_data->on_data = polling->on_data;
    291         polling_data->on_polling_end = polling->on_polling_end;
    292         polling_data->on_error = polling->on_error;
     256        /* Copy provided settings. */
     257        polling_data->auto_polling = *polling;
     258
     259        /* Negative value means use descriptor provided value. */
     260        if (polling->delay < 0) {
     261                polling_data->auto_polling.delay =
     262                    (int) dev->pipes[pipe_index].descriptor->poll_interval;
     263        }
    293264
    294265        fid_t fibril = fibril_create(polling_fibril, polling_data);
  • uspace/lib/usbdev/src/hub.c

    rfb48a0e rc48f6ab  
    7676{
    7777        CHECK_CONNECTION(connection);
    78        
     78
    7979        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
    80        
    81         sysarg_t address;
    82         int rc = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    83             IPC_M_USBHC_REQUEST_ADDRESS, preferred, strict, speed, &address);
    84        
     80        if (!exch)
     81                return (usb_address_t)ENOMEM;
     82
     83        usb_address_t address = preferred;
     84        const int ret = usbhc_request_address(exch, &address, strict, speed);
     85
    8586        async_exchange_end(exch);
    86        
    87         if (rc != EOK)
    88                 return (usb_address_t) rc;
    89        
    90         return (usb_address_t) address;
     87        return ret == EOK ? address : ret;
    9188}
    9289
     
    9794 * @return Error code.
    9895 */
    99 int usb_hc_register_device(usb_hc_connection_t * connection,
     96int usb_hc_register_device(usb_hc_connection_t *connection,
    10097    const usb_hub_attached_device_t *attached_device)
    10198{
    10299        CHECK_CONNECTION(connection);
    103        
    104         if (attached_device == NULL)
    105                 return EBADMEM;
    106        
     100        if (attached_device == NULL || attached_device->fun == NULL)
     101                return EINVAL;
     102
    107103        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
    108         int rc = async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    109             IPC_M_USBHC_BIND_ADDRESS,
     104        if (!exch)
     105                return ENOMEM;
     106        const int ret = usbhc_bind_address(exch,
    110107            attached_device->address, attached_device->fun->handle);
    111108        async_exchange_end(exch);
    112        
    113         return rc;
     109
     110        return ret;
    114111}
    115112
     
    124121{
    125122        CHECK_CONNECTION(connection);
    126        
     123
    127124        async_exch_t *exch = async_exchange_begin(connection->hc_sess);
    128         int rc = async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    129             IPC_M_USBHC_RELEASE_ADDRESS, address);
     125        if (!exch)
     126                return ENOMEM;
     127        const int ret = usbhc_release_address(exch, address);
    130128        async_exchange_end(exch);
    131        
    132         return rc;
     129
     130        return ret;
    133131}
    134132
     
    221219 *      request or requests for descriptors when creating match ids).
    222220 */
    223 int usb_hc_new_device_wrapper(ddf_dev_t *parent, usb_hc_connection_t *connection,
    224     usb_speed_t dev_speed,
     221int usb_hc_new_device_wrapper(ddf_dev_t *parent,
     222    usb_hc_connection_t *connection, usb_speed_t dev_speed,
    225223    int (*enable_port)(void *arg), void *arg, usb_address_t *assigned_address,
    226224    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
     
    229227                return EINVAL;
    230228
    231         // FIXME: this is awful, we are accessing directly the structure.
    232229        // TODO: Why not use provided connection?
    233         usb_hc_connection_t hc_conn = {
    234                 .hc_handle = connection->hc_handle,
    235                 .hc_sess = NULL
    236         };
     230        usb_hc_connection_t hc_conn;
     231        usb_hc_connection_initialize(&hc_conn, connection->hc_handle);
    237232
    238233        int rc;
  • uspace/lib/usbdev/src/pipepriv.c

    rfb48a0e rc48f6ab  
    8787       
    8888        if (pipe->refcount == 0) {
     89                assert(pipe->hc_sess == NULL);
    8990                /* Need to open the phone by ourselves. */
    9091                async_sess_t *sess =
  • uspace/lib/usbdev/src/pipes.c

    rfb48a0e rc48f6ab  
    5454static usb_address_t get_my_address(async_sess_t *sess, const ddf_dev_t *dev)
    5555{
     56        assert(sess);
    5657        async_exch_t *exch = async_exchange_begin(sess);
    57        
    58         sysarg_t address;
    59         int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    60             IPC_M_USB_GET_MY_ADDRESS, &address);
    61        
     58        if (!exch)
     59                return ENOMEM;
     60
     61        usb_address_t address;
     62        const int ret = usb_get_my_address(exch, &address);
     63
    6264        async_exchange_end(exch);
    63        
    64         if (rc != EOK)
    65                 return rc;
    66        
    67         return (usb_address_t) address;
     65
     66        return (ret == EOK) ? address : ret;
    6867}
    6968
     
    7170 *
    7271 * @param device Device in question.
    73  * @return Interface number (negative code means any).
     72 * @return Error code (ENOTSUP means any).
    7473 */
    7574int usb_device_get_assigned_interface(const ddf_dev_t *device)
     
    8079            IPC_FLAG_BLOCKING);
    8180        if (!parent_sess)
    82                 return -1;
    83        
     81                return ENOMEM;
     82
    8483        async_exch_t *exch = async_exchange_begin(parent_sess);
    85        
    86         sysarg_t iface_no;
    87         int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    88             IPC_M_USB_GET_INTERFACE, device->handle, &iface_no);
    89        
    90         async_exchange_end(exch);
    91         async_hangup(parent_sess);
    92        
    93         if (rc != EOK)
    94                 return -1;
    95        
    96         return (int) iface_no;
     84        if (!exch) {
     85                async_hangup(parent_sess);
     86                return ENOMEM;
     87        }
     88
     89        int iface_no;
     90        const int ret = usb_get_my_interface(exch, &iface_no);
     91
     92        return ret == EOK ? iface_no : ret;
    9793}
    9894
  • uspace/lib/usbdev/src/pipesinit.c

    rfb48a0e rc48f6ab  
    5454
    5555/** Nesting pairs of standard descriptors. */
    56 static usb_dp_descriptor_nesting_t descriptor_nesting[] = {
     56static const usb_dp_descriptor_nesting_t descriptor_nesting[] = {
    5757        NESTING(CONFIGURATION, INTERFACE),
    5858        NESTING(INTERFACE, ENDPOINT),
     
    405405        }
    406406
    407 #define TRY_LOOP(attempt_var) \
    408         for (attempt_var = 0; attempt_var < 3; attempt_var++)
    409 
    410         size_t failed_attempts;
    411         int rc;
    412407
    413408        usb_pipe_start_long_transfer(pipe);
     
    415410        uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];
    416411        size_t transferred_size;
    417         TRY_LOOP(failed_attempts) {
     412        int rc;
     413        for (size_t attempt_var = 0; attempt_var < 3; ++attempt_var) {
    418414                rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD,
    419415                    USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE,
     
    450446{
    451447        assert(pipe);
     448        assert(pipe->wire);
    452449        assert(hc_connection);
    453450
    454451        if (!usb_hc_connection_is_opened(hc_connection))
    455452                return EBADF;
    456 
    457         const usb_target_t target =
    458             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    459 #define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff))
    460 
    461453        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
    462         int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    463             IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,
    464             _PACK2(pipe->transfer_type, pipe->direction),
    465             _PACK2(pipe->max_packet_size, interval));
     454        if (!exch)
     455                return ENOMEM;
     456        const int ret = usbhc_register_endpoint(exch,
     457            pipe->wire->address, pipe->endpoint_no, pipe->transfer_type,
     458            pipe->direction, pipe->max_packet_size, interval);
     459
    466460        async_exchange_end(exch);
    467 
    468 #undef _PACK2
    469         return rc;
     461        return ret;
    470462}
    471463
     
    482474        assert(pipe->wire);
    483475        assert(hc_connection);
    484        
     476
    485477        if (!usb_hc_connection_is_opened(hc_connection))
    486478                return EBADF;
    487        
     479
    488480        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
    489         int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    490             IPC_M_USBHC_UNREGISTER_ENDPOINT,
     481        if (!exch)
     482                return ENOMEM;
     483        const int ret = usbhc_unregister_endpoint(exch,
    491484            pipe->wire->address, pipe->endpoint_no, pipe->direction);
    492485        async_exchange_end(exch);
    493        
    494         return rc;
     486
     487        return ret;
    495488}
    496489
  • uspace/lib/usbdev/src/pipesio.c

    rfb48a0e rc48f6ab  
    6262 * @return Error code.
    6363 */
    64 static int usb_pipe_read_no_checks(usb_pipe_t *pipe,
     64static int usb_pipe_read_no_check(usb_pipe_t *pipe, uint64_t setup,
    6565    void *buffer, size_t size, size_t *size_transfered)
    6666{
    67         /* Only interrupt and bulk transfers are supported */
     67        /* Isochronous transfer are not supported (yet) */
    6868        if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    69             pipe->transfer_type != USB_TRANSFER_BULK)
     69            pipe->transfer_type != USB_TRANSFER_BULK &&
     70            pipe->transfer_type != USB_TRANSFER_CONTROL)
    7071            return ENOTSUP;
    7172
    72         const usb_target_t target =
    73             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    74        
     73        int ret = pipe_add_ref(pipe, false);
     74        if (ret != EOK) {
     75                return ret;
     76        }
     77
    7578        /* Ensure serialization over the phone. */
    7679        pipe_start_transaction(pipe);
    7780        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    78        
    79         /*
    80          * Make call identifying target USB device and type of transfer.
    81          */
    82         aid_t opening_request = async_send_2(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    83             IPC_M_USBHC_READ, target.packed, NULL);
    84        
    85         if (opening_request == 0) {
    86                 async_exchange_end(exch);
     81        if (!exch) {
    8782                pipe_end_transaction(pipe);
     83                pipe_drop_ref(pipe);
    8884                return ENOMEM;
    8985        }
    90        
    91         /*
    92          * Retrieve the data.
    93          */
    94         ipc_call_t data_request_call;
    95         aid_t data_request = async_data_read(exch, buffer, size,
    96             &data_request_call);
    97        
    98         /*
    99          * Since now on, someone else might access the backing phone
    100          * without breaking the transfer IPC protocol.
    101          */
     86
     87        ret = usbhc_read(exch, pipe->wire->address, pipe->endpoint_no,
     88            setup, buffer, size, size_transfered);
    10289        async_exchange_end(exch);
    10390        pipe_end_transaction(pipe);
    104        
    105         if (data_request == 0) {
    106                 /*
    107                  * FIXME:
    108                  * How to let the other side know that we want to abort?
    109                  */
    110                 async_wait_for(opening_request, NULL);
    111                 return ENOMEM;
    112         }
    113        
    114         /*
    115          * Wait for the answer.
    116          */
    117         sysarg_t data_request_rc;
    118         sysarg_t opening_request_rc;
    119         async_wait_for(data_request, &data_request_rc);
    120         async_wait_for(opening_request, &opening_request_rc);
    121        
    122         if (data_request_rc != EOK) {
    123                 /* Prefer the return code of the opening request. */
    124                 if (opening_request_rc != EOK) {
    125                         return (int) opening_request_rc;
    126                 } else {
    127                         return (int) data_request_rc;
    128                 }
    129         }
    130         if (opening_request_rc != EOK) {
    131                 return (int) opening_request_rc;
    132         }
    133        
    134         *size_transfered = IPC_GET_ARG2(data_request_call);
    135        
    136         return EOK;
    137 }
    138 
    139 
    140 /** Request a read (in) transfer on an endpoint pipe.
    141  *
    142  * @param[in] pipe Pipe used for the transfer.
    143  * @param[out] buffer Buffer where to store the data.
    144  * @param[in] size Size of the buffer (in bytes).
    145  * @param[out] size_transfered Number of bytes that were actually transfered.
    146  * @return Error code.
    147  */
    148 int usb_pipe_read(usb_pipe_t *pipe,
    149     void *buffer, size_t size, size_t *size_transfered)
    150 {
    151         assert(pipe);
    152 
    153         if (buffer == NULL) {
    154                 return EINVAL;
    155         }
    156 
    157         if (size == 0) {
    158                 return EINVAL;
    159         }
    160 
    161         if (pipe->direction != USB_DIRECTION_IN) {
    162                 return EBADF;
    163         }
    164 
    165         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    166                 return EBADF;
    167         }
    168 
    169         int rc;
    170         rc = pipe_add_ref(pipe, false);
    171         if (rc != EOK) {
    172                 return rc;
    173         }
    174 
    175 
    176         size_t act_size = 0;
    177 
    178         rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);
    179 
    18091        pipe_drop_ref(pipe);
    181 
    182         if (rc != EOK) {
    183                 return rc;
    184         }
    185 
    186         if (size_transfered != NULL) {
    187                 *size_transfered = act_size;
    188         }
    189 
    190         return EOK;
    191 }
    192 
    193 
    194 
     92        return ret;
     93}
    19594
    19695/** Request an out transfer, no checking of input parameters.
     
    201100 * @return Error code.
    202101 */
    203 static int usb_pipe_write_no_check(usb_pipe_t *pipe,
    204     void *buffer, size_t size)
     102static int usb_pipe_write_no_check(usb_pipe_t *pipe, uint64_t setup,
     103    const void *buffer, size_t size)
    205104{
    206105        /* Only interrupt and bulk transfers are supported */
    207106        if (pipe->transfer_type != USB_TRANSFER_INTERRUPT &&
    208             pipe->transfer_type != USB_TRANSFER_BULK)
     107            pipe->transfer_type != USB_TRANSFER_BULK &&
     108            pipe->transfer_type != USB_TRANSFER_CONTROL)
    209109            return ENOTSUP;
    210110
    211         const usb_target_t target =
    212             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
     111        int ret = pipe_add_ref(pipe, false);
     112        if (ret != EOK) {
     113                return ret;
     114        }
    213115
    214116        /* Ensure serialization over the phone. */
    215117        pipe_start_transaction(pipe);
    216118        async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    217        
    218         /*
    219          * Make call identifying target USB device and type of transfer.
    220          */
    221         aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    222             IPC_M_USBHC_WRITE, target.packed, size, NULL);
    223        
    224         if (opening_request == 0) {
    225                 async_exchange_end(exch);
     119        if (!exch) {
    226120                pipe_end_transaction(pipe);
     121                pipe_drop_ref(pipe);
    227122                return ENOMEM;
    228123        }
    229        
    230         /*
    231          * Send the data.
    232          */
    233         int rc = async_data_write_start(exch, buffer, size);
    234        
    235         /*
    236          * Since now on, someone else might access the backing phone
    237          * without breaking the transfer IPC protocol.
    238          */
     124        ret = usbhc_write(exch, pipe->wire->address, pipe->endpoint_no,
     125            setup, buffer, size);
    239126        async_exchange_end(exch);
    240127        pipe_end_transaction(pipe);
    241        
    242         if (rc != EOK) {
    243                 async_wait_for(opening_request, NULL);
    244                 return rc;
    245         }
    246        
    247         /*
    248          * Wait for the answer.
    249          */
    250         sysarg_t opening_request_rc;
    251         async_wait_for(opening_request, &opening_request_rc);
    252        
    253         return (int) opening_request_rc;
    254 }
    255 
    256 /** Request a write (out) transfer on an endpoint pipe.
    257  *
    258  * @param[in] pipe Pipe used for the transfer.
    259  * @param[in] buffer Buffer with data to transfer.
    260  * @param[in] size Size of the buffer (in bytes).
    261  * @return Error code.
    262  */
    263 int usb_pipe_write(usb_pipe_t *pipe,
    264     void *buffer, size_t size)
    265 {
    266         assert(pipe);
    267 
    268         if (buffer == NULL) {
    269                 return EINVAL;
    270         }
    271 
    272         if (size == 0) {
    273                 return EINVAL;
    274         }
    275 
    276         if (pipe->direction != USB_DIRECTION_OUT) {
    277                 return EBADF;
    278         }
    279 
    280         if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
    281                 return EBADF;
    282         }
    283 
    284         int rc;
    285 
    286         rc = pipe_add_ref(pipe, false);
    287         if (rc != EOK) {
    288                 return rc;
    289         }
    290 
    291         rc = usb_pipe_write_no_check(pipe, buffer, size);
    292 
    293128        pipe_drop_ref(pipe);
    294 
    295         return rc;
     129        return ret;
    296130}
    297131
     
    309143
    310144
    311         /* Prevent indefinite recursion. */
     145        /* Prevent infinite recursion. */
    312146        pipe->auto_reset_halt = false;
    313147        usb_request_clear_endpoint_halt(pipe, 0);
     
    315149}
    316150
    317 
    318 /** Request a control read transfer, no checking of input parameters.
     151/** Request a control read transfer on an endpoint pipe.
     152 *
     153 * This function encapsulates all three stages of a control transfer.
    319154 *
    320155 * @param[in] pipe Pipe used for the transfer.
     
    327162 * @return Error code.
    328163 */
    329 static int usb_pipe_control_read_no_check(usb_pipe_t *pipe,
    330     const void *setup_buffer, size_t setup_buffer_size,
    331     void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
    332 {
    333         /* Ensure serialization over the phone. */
    334         pipe_start_transaction(pipe);
    335 
    336         const usb_target_t target =
    337             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    338 
    339         assert(setup_buffer_size == 8);
    340         uint64_t setup_packet;
    341         memcpy(&setup_packet, setup_buffer, 8);
    342         /*
    343          * Make call identifying target USB device and control transfer type.
    344          */
    345         async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    346         aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    347             IPC_M_USBHC_READ, target.packed,
    348             (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);
    349 
    350         if (opening_request == 0) {
    351                 async_exchange_end(exch);
    352                 return ENOMEM;
    353         }
    354 
    355         /*
    356          * Retrieve the data.
    357          */
    358         ipc_call_t data_request_call;
    359         aid_t data_request = async_data_read(exch, data_buffer,
    360             data_buffer_size, &data_request_call);
    361        
    362         /*
    363          * Since now on, someone else might access the backing phone
    364          * without breaking the transfer IPC protocol.
    365          */
    366         async_exchange_end(exch);
    367         pipe_end_transaction(pipe);
    368        
    369         if (data_request == 0) {
    370                 async_wait_for(opening_request, NULL);
    371                 return ENOMEM;
    372         }
    373 
    374         /*
    375          * Wait for the answer.
    376          */
    377         sysarg_t data_request_rc;
    378         sysarg_t opening_request_rc;
    379         async_wait_for(data_request, &data_request_rc);
    380         async_wait_for(opening_request, &opening_request_rc);
    381 
    382         if (data_request_rc != EOK) {
    383                 /* Prefer the return code of the opening request. */
    384                 if (opening_request_rc != EOK) {
    385                         return (int) opening_request_rc;
    386                 } else {
    387                         return (int) data_request_rc;
    388                 }
    389         }
    390         if (opening_request_rc != EOK) {
    391                 return (int) opening_request_rc;
    392         }
    393 
    394         *data_transfered_size = IPC_GET_ARG2(data_request_call);
    395 
    396         return EOK;
    397 }
    398 
    399 /** Request a control read transfer on an endpoint pipe.
    400  *
    401  * This function encapsulates all three stages of a control transfer.
    402  *
    403  * @param[in] pipe Pipe used for the transfer.
    404  * @param[in] setup_buffer Buffer with the setup packet.
    405  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    406  * @param[out] data_buffer Buffer for incoming data.
    407  * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
    408  * @param[out] data_transfered_size Number of bytes that were actually
    409  *                                  transfered during the DATA stage.
    410  * @return Error code.
    411  */
    412164int usb_pipe_control_read(usb_pipe_t *pipe,
    413165    const void *setup_buffer, size_t setup_buffer_size,
     
    416168        assert(pipe);
    417169
    418         if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
     170        if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    419171                return EINVAL;
    420172        }
     
    429181        }
    430182
    431         int rc;
    432 
    433         rc = pipe_add_ref(pipe, false);
    434         if (rc != EOK) {
    435                 return rc;
    436         }
     183        uint64_t setup_packet;
     184        memcpy(&setup_packet, setup_buffer, 8);
    437185
    438186        size_t act_size = 0;
    439         rc = usb_pipe_control_read_no_check(pipe,
    440             setup_buffer, setup_buffer_size,
     187        const int rc = usb_pipe_read_no_check(pipe, setup_packet,
    441188            data_buffer, data_buffer_size, &act_size);
    442189
     
    445192        }
    446193
    447         pipe_drop_ref(pipe);
    448 
    449         if (rc != EOK) {
    450                 return rc;
    451         }
    452 
    453         if (data_transfered_size != NULL) {
     194        if (rc == EOK && data_transfered_size != NULL) {
    454195                *data_transfered_size = act_size;
    455196        }
    456197
    457         return EOK;
    458 }
    459 
    460 
    461 /** Request a control write transfer, no checking of input parameters.
     198        return rc;
     199}
     200
     201/** Request a control write transfer on an endpoint pipe.
     202 *
     203 * This function encapsulates all three stages of a control transfer.
    462204 *
    463205 * @param[in] pipe Pipe used for the transfer.
     
    468210 * @return Error code.
    469211 */
    470 static int usb_pipe_control_write_no_check(usb_pipe_t *pipe,
    471     const void *setup_buffer, size_t setup_buffer_size,
    472     const void *data_buffer, size_t data_buffer_size)
    473 {
    474         /* Ensure serialization over the phone. */
    475         pipe_start_transaction(pipe);
    476 
    477         const usb_target_t target =
    478             {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    479         assert(setup_buffer_size == 8);
    480         uint64_t setup_packet;
    481         memcpy(&setup_packet, setup_buffer, 8);
    482 
    483         /*
    484          * Make call identifying target USB device and control transfer type.
    485          */
    486         async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
    487         aid_t opening_request = async_send_5(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    488             IPC_M_USBHC_WRITE, target.packed, data_buffer_size,
    489             (setup_packet & UINT32_MAX), (setup_packet >> 32), NULL);
    490        
    491         if (opening_request == 0) {
    492                 async_exchange_end(exch);
    493                 pipe_end_transaction(pipe);
    494                 return ENOMEM;
    495         }
    496 
    497         /*
    498          * Send the data (if any).
    499          */
    500         if (data_buffer_size > 0) {
    501                 int rc = async_data_write_start(exch, data_buffer, data_buffer_size);
    502                
    503                 /* All data sent, pipe can be released. */
    504                 async_exchange_end(exch);
    505                 pipe_end_transaction(pipe);
    506        
    507                 if (rc != EOK) {
    508                         async_wait_for(opening_request, NULL);
    509                         return rc;
    510                 }
    511         } else {
    512                 /* No data to send, we can release the pipe for others. */
    513                 async_exchange_end(exch);
    514                 pipe_end_transaction(pipe);
    515         }
    516        
    517         /*
    518          * Wait for the answer.
    519          */
    520         sysarg_t opening_request_rc;
    521         async_wait_for(opening_request, &opening_request_rc);
    522 
    523         return (int) opening_request_rc;
    524 }
    525 
    526 /** Request a control write transfer on an endpoint pipe.
    527  *
    528  * This function encapsulates all three stages of a control transfer.
    529  *
    530  * @param[in] pipe Pipe used for the transfer.
    531  * @param[in] setup_buffer Buffer with the setup packet.
    532  * @param[in] setup_buffer_size Size of the setup packet (in bytes).
    533  * @param[in] data_buffer Buffer with data to be sent.
    534  * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
    535  * @return Error code.
    536  */
    537212int usb_pipe_control_write(usb_pipe_t *pipe,
    538213    const void *setup_buffer, size_t setup_buffer_size,
     
    541216        assert(pipe);
    542217
    543         if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
     218        if ((setup_buffer == NULL) || (setup_buffer_size != 8)) {
    544219                return EINVAL;
    545220        }
     
    558233        }
    559234
    560         int rc;
    561 
    562         rc = pipe_add_ref(pipe, false);
    563         if (rc != EOK) {
    564                 return rc;
    565         }
    566 
    567         rc = usb_pipe_control_write_no_check(pipe,
    568             setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
     235        uint64_t setup_packet;
     236        memcpy(&setup_packet, setup_buffer, 8);
     237
     238        const int rc = usb_pipe_write_no_check(pipe, setup_packet,
     239            data_buffer, data_buffer_size);
    569240
    570241        if (rc == ESTALL) {
     
    572243        }
    573244
    574         pipe_drop_ref(pipe);
    575 
    576245        return rc;
    577246}
    578247
     248/** Request a read (in) transfer on an endpoint pipe.
     249 *
     250 * @param[in] pipe Pipe used for the transfer.
     251 * @param[out] buffer Buffer where to store the data.
     252 * @param[in] size Size of the buffer (in bytes).
     253 * @param[out] size_transfered Number of bytes that were actually transfered.
     254 * @return Error code.
     255 */
     256int usb_pipe_read(usb_pipe_t *pipe,
     257    void *buffer, size_t size, size_t *size_transfered)
     258{
     259        assert(pipe);
     260
     261        if (buffer == NULL) {
     262                return EINVAL;
     263        }
     264
     265        if (size == 0) {
     266                return EINVAL;
     267        }
     268
     269        if (pipe->direction != USB_DIRECTION_IN) {
     270                return EBADF;
     271        }
     272
     273        if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
     274                return EBADF;
     275        }
     276
     277        size_t act_size = 0;
     278        const int rc = usb_pipe_read_no_check(pipe, 0, buffer, size, &act_size);
     279
     280
     281        if (rc == EOK && size_transfered != NULL) {
     282                *size_transfered = act_size;
     283        }
     284
     285        return rc;
     286}
     287
     288/** Request a write (out) transfer on an endpoint pipe.
     289 *
     290 * @param[in] pipe Pipe used for the transfer.
     291 * @param[in] buffer Buffer with data to transfer.
     292 * @param[in] size Size of the buffer (in bytes).
     293 * @return Error code.
     294 */
     295int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size)
     296{
     297        assert(pipe);
     298
     299        if (buffer == NULL || size == 0) {
     300                return EINVAL;
     301        }
     302
     303        if (pipe->direction != USB_DIRECTION_OUT) {
     304                return EBADF;
     305        }
     306
     307        if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
     308                return EBADF;
     309        }
     310
     311        return usb_pipe_write_no_check(pipe, 0, buffer, size);
     312}
    579313
    580314/**
  • uspace/lib/usbdev/src/request.c

    rfb48a0e rc48f6ab  
    143143         */
    144144
    145         usb_device_request_setup_packet_t setup_packet;
    146         setup_packet.request_type = 128 | (request_type << 5) | recipient;
    147         setup_packet.request = request;
    148         setup_packet.value = value;
    149         setup_packet.index = index;
    150         setup_packet.length = (uint16_t) data_size;
    151 
    152         int rc = usb_pipe_control_read(pipe,
    153             &setup_packet, sizeof(setup_packet),
     145        const usb_device_request_setup_packet_t setup_packet = {
     146                .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST
     147                    | (request_type << 5) | recipient,
     148                .request = request,
     149                .value = value,
     150                .index = index,
     151                .length = (uint16_t) data_size,
     152        };
     153
     154        return usb_pipe_control_read(pipe, &setup_packet, sizeof(setup_packet),
    154155            data, data_size, actual_data_size);
    155 
    156         return rc;
    157156}
    158157
     
    276275        }
    277276
    278         uint16_t wValue = descriptor_index | (descriptor_type << 8);
     277        const uint16_t wValue = descriptor_index | (descriptor_type << 8);
    279278
    280279        return usb_control_request_get(pipe,
  • uspace/lib/usbhost/include/usb/host/hcd.h

    rfb48a0e rc48f6ab  
    6363/*----------------------------------------------------------------------------*/
    6464/** Initialize hcd_t structure.
    65  * Initializes device and endpoint managers. Sets data nd hook pointer to NULL.
     65 * Initializes device and endpoint managers. Sets data and hook pointer to NULL.
    6666 * @param hcd hcd_t structure to initialize, non-null.
    6767 * @param bandwidth Available bandwidth, passed to endpoint manager.
  • uspace/lib/usbhost/src/iface.c

    rfb48a0e rc48f6ab  
    252252        .request_address = request_address,
    253253        .bind_address = bind_address,
    254         .find_by_address = find_by_address,
     254        .get_handle = find_by_address,
    255255        .release_address = release_address,
    256256
Note: See TracChangeset for help on using the changeset viewer.