Changeset a43f1d18 in mainline


Ignore:
Timestamp:
2011-04-09T18:26:22Z (13 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2ad98fd
Parents:
f35b294 (diff), 97e7e8a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merge with usb/development

Location:
uspace
Files:
6 added
35 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/usbinfo/dev.c

    rf35b294 ra43f1d18  
    5050
    5151        int rc;
     52        bool transfer_started = false;
    5253
    5354        rc = usb_device_connection_initialize(&dev->wire, hc_handle, dev_addr);
     
    7677        }
    7778
    78         rc = usb_pipe_start_session(&dev->ctrl_pipe);
     79        rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
    7980        if (rc != EOK) {
    8081                fprintf(stderr,
    81                     NAME ": failed to start session on control pipe: %s.\n",
     82                    NAME ": failed to start transfer on control pipe: %s.\n",
    8283                    str_error(rc));
    8384                goto leave;
    8485        }
     86        transfer_started = true;
    8587
    8688        rc = usb_request_get_device_descriptor(&dev->ctrl_pipe,
     
    107109
    108110leave:
    109         if (usb_pipe_is_session_started(&dev->ctrl_pipe)) {
    110                 usb_pipe_end_session(&dev->ctrl_pipe);
     111        if (transfer_started) {
     112                usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    111113        }
    112114
     
    118120void destroy_device(usbinfo_device_t *dev)
    119121{
    120         usb_pipe_end_session(&dev->ctrl_pipe);
     122        usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    121123        free(dev);
    122124}
  • uspace/doc/doxygroups.h

    rf35b294 ra43f1d18  
    269269
    270270        /**
     271         * @defgroup drvusbohci OHCI driver
     272         * @ingroup usb
     273         * @brief Driver for OHCI host controller.
     274         */
     275
     276        /**
    271277         * @defgroup drvusbehci EHCI driver
    272278         * @ingroup usb
     
    275281
    276282        /**
    277          * @defgroup drvusbfallback USB fallback driver.
     283         * @defgroup drvusbfallback USB fallback driver
    278284         * @ingroup usb
    279285         * @brief Fallback driver for any USB device.
  • uspace/drv/ehci-hcd/hc_iface.c

    rf35b294 ra43f1d18  
    123123 * @param[in] fun Device function the action was invoked on.
    124124 * @param[in] address USB address of the device.
     125 * @param[in] speed Endpoint speed (invalid means to use device one).
    125126 * @param[in] endpoint Endpoint number.
    126127 * @param[in] transfer_type USB transfer type.
     
    131132 */
    132133static int register_endpoint(ddf_fun_t *fun,
    133     usb_address_t address, usb_endpoint_t endpoint,
     134    usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
    134135    usb_transfer_type_t transfer_type, usb_direction_t direction,
    135136    size_t max_packet_size, unsigned int interval)
     
    165166 * @param[in] fun Device function the action was invoked on.
    166167 * @param[in] target Target pipe (address and endpoint number) specification.
    167  * @param[in] max_packet_size Max packet size for the transfer.
    168168 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    169169 *      by the caller).
     
    174174 */
    175175static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
    176     size_t max_packet_size, void *data, size_t size,
     176    void *data, size_t size,
    177177    usbhc_iface_transfer_out_callback_t callback, void *arg)
    178178{
     
    191191 * @param[in] fun Device function the action was invoked on.
    192192 * @param[in] target Target pipe (address and endpoint number) specification.
    193  * @param[in] max_packet_size Max packet size for the transfer.
    194193 * @param[in] data Buffer where to store the data (in USB endianess,
    195194 *      allocated and deallocated by the caller).
     
    200199 */
    201200static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
    202     size_t max_packet_size, void *data, size_t size,
     201    void *data, size_t size,
    203202    usbhc_iface_transfer_in_callback_t callback, void *arg)
    204203{
     
    217216 * @param[in] fun Device function the action was invoked on.
    218217 * @param[in] target Target pipe (address and endpoint number) specification.
    219  * @param[in] max_packet_size Max packet size for the transfer.
    220218 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    221219 *      by the caller).
     
    226224 */
    227225static int bulk_out(ddf_fun_t *fun, usb_target_t target,
    228     size_t max_packet_size, void *data, size_t size,
     226    void *data, size_t size,
    229227    usbhc_iface_transfer_out_callback_t callback, void *arg)
    230228{
     
    243241 * @param[in] fun Device function the action was invoked on.
    244242 * @param[in] target Target pipe (address and endpoint number) specification.
    245  * @param[in] max_packet_size Max packet size for the transfer.
    246243 * @param[in] data Buffer where to store the data (in USB endianess,
    247244 *      allocated and deallocated by the caller).
     
    252249 */
    253250static int bulk_in(ddf_fun_t *fun, usb_target_t target,
    254     size_t max_packet_size, void *data, size_t size,
     251    void *data, size_t size,
    255252    usbhc_iface_transfer_in_callback_t callback, void *arg)
    256253{
     
    269266 * @param[in] fun Device function the action was invoked on.
    270267 * @param[in] target Target pipe (address and endpoint number) specification.
    271  * @param[in] max_packet_size Max packet size for the transfer.
    272268 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    273269 *      and deallocated by the caller).
     
    281277 */
    282278static int control_write(ddf_fun_t *fun, usb_target_t target,
    283     size_t max_packet_size,
    284279    void *setup_packet, size_t setup_packet_size,
    285280    void *data_buffer, size_t data_buffer_size,
     
    300295 * @param[in] fun Device function the action was invoked on.
    301296 * @param[in] target Target pipe (address and endpoint number) specification.
    302  * @param[in] max_packet_size Max packet size for the transfer.
    303297 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    304298 *      and deallocated by the caller).
     
    312306 */
    313307static int control_read(ddf_fun_t *fun, usb_target_t target,
    314     size_t max_packet_size,
    315308    void *setup_packet, size_t setup_packet_size,
    316309    void *data_buffer, size_t data_buffer_size,
  • uspace/drv/ohci/Makefile

    rf35b294 ra43f1d18  
    3333
    3434SOURCES = \
     35        batch.c \
     36        hc.c \
    3537        iface.c \
    36         batch.c \
    3738        main.c \
    38         hc.c \
    3939        ohci.c \
     40        pci.c \
    4041        root_hub.c \
    41         pci.c
     42        transfer_list.c \
     43        hw_struct/endpoint_descriptor.c \
     44        hw_struct/transfer_descriptor.c
     45
    4246
    4347include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/ohci/batch.c

    rf35b294 ra43f1d18  
    4040#include "batch.h"
    4141#include "utils/malloc32.h"
    42 
     42#include "hw_struct/endpoint_descriptor.h"
     43#include "hw_struct/transfer_descriptor.h"
     44
     45typedef struct ohci_batch {
     46        ed_t *ed;
     47        td_t *tds;
     48        size_t td_count;
     49} ohci_batch_t;
     50
     51static void batch_control(usb_transfer_batch_t *instance,
     52    usb_direction_t data_dir, usb_direction_t status_dir);
    4353static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    4454static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    4555
    4656#define DEFAULT_ERROR_COUNT 3
    47 usb_transfer_batch_t * batch_get(
    48     ddf_fun_t *fun,
    49                 usb_target_t target,
    50     usb_transfer_type_t transfer_type,
    51                 size_t max_packet_size,
    52     usb_speed_t speed,
    53                 char *buffer,
    54                 size_t buffer_size,
    55                 char *setup_buffer,
    56                 size_t setup_size,
     57usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
     58    char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
    5759    usbhc_iface_transfer_in_callback_t func_in,
    58     usbhc_iface_transfer_out_callback_t func_out,
    59                 void *arg,
    60                 usb_device_keeper_t *manager
    61                 )
     60    usbhc_iface_transfer_out_callback_t func_out, void *arg)
    6261{
    6362#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
     
    7372        CHECK_NULL_DISPOSE_RETURN(instance,
    7473            "Failed to allocate batch instance.\n");
    75         usb_transfer_batch_init(instance, target, transfer_type, speed,
    76             max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
    77             func_in, func_out, arg, fun, NULL, NULL);
     74        usb_target_t target =
     75            { .address = ep->address, .endpoint = ep->endpoint };
     76        usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed,
     77            ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
     78            func_in, func_out, arg, fun, ep, NULL);
     79
     80        ohci_batch_t *data = malloc(sizeof(ohci_batch_t));
     81        CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
     82        bzero(data, sizeof(ohci_batch_t));
     83        instance->private_data = data;
     84
     85        /* we needs + 1 transfer descriptor as the last one won't be executed */
     86        data->td_count = 1 +
     87            ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
     88        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     89                data->td_count += 2;
     90        }
     91
     92        data->tds = malloc32(sizeof(td_t) * data->td_count);
     93        CHECK_NULL_DISPOSE_RETURN(data->tds,
     94            "Failed to allocate transfer descriptors.\n");
     95        bzero(data->tds, sizeof(td_t) * data->td_count);
     96
     97        data->ed = malloc32(sizeof(ed_t));
     98        CHECK_NULL_DISPOSE_RETURN(data->ed,
     99            "Failed to allocate endpoint descriptor.\n");
    78100
    79101        if (buffer_size > 0) {
     
    90112        }
    91113
    92 
    93114        return instance;
    94115}
     
    97118{
    98119        assert(instance);
     120        ohci_batch_t *data = instance->private_data;
     121        assert(data);
     122        free32(data->ed);
     123        free32(data->tds);
     124        free32(instance->setup_buffer);
    99125        free32(instance->transport_buffer);
    100         free32(instance->setup_buffer);
     126        free(data);
    101127        free(instance);
     128}
     129/*----------------------------------------------------------------------------*/
     130bool batch_is_complete(usb_transfer_batch_t *instance)
     131{
     132        assert(instance);
     133        ohci_batch_t *data = instance->private_data;
     134        assert(data);
     135        size_t tds = data->td_count - 1;
     136        usb_log_debug2("Batch(%p) checking %d td(s) for completion.\n",
     137            instance, tds);
     138        size_t i = 0;
     139        for (; i < tds; ++i) {
     140                if (!td_is_finished(&data->tds[i]))
     141                        return false;
     142                instance->error = td_error(&data->tds[i]);
     143                /* FIXME: calculate real transfered size */
     144                instance->transfered_size = instance->buffer_size;
     145                if (instance->error != EOK) {
     146                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
     147                            instance, i, data->tds[i].status);
     148                        return true;
     149//                      endpoint_toggle_set(instance->ep,
     150                }
     151        }
     152        return true;
    102153}
    103154/*----------------------------------------------------------------------------*/
     
    109160            instance->buffer_size);
    110161        instance->next_step = batch_call_out_and_dispose;
    111         /* TODO: implement */
     162        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    112163        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    113164}
     
    117168        assert(instance);
    118169        instance->next_step = batch_call_in_and_dispose;
    119         /* TODO: implement */
     170        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    120171        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    121172}
     
    124175{
    125176        assert(instance);
    126         instance->direction = USB_DIRECTION_IN;
     177        assert(instance->direction == USB_DIRECTION_IN);
    127178        instance->next_step = batch_call_in_and_dispose;
    128179        /* TODO: implement */
     
    133184{
    134185        assert(instance);
    135         instance->direction = USB_DIRECTION_OUT;
     186        assert(instance->direction == USB_DIRECTION_OUT);
    136187        /* We are data out, we are supposed to provide data */
    137188        memcpy(instance->transport_buffer, instance->buffer,
     
    160211}
    161212/*----------------------------------------------------------------------------*/
     213ed_t * batch_ed(usb_transfer_batch_t *instance)
     214{
     215        assert(instance);
     216        ohci_batch_t *data = instance->private_data;
     217        assert(data);
     218        return data->ed;
     219}
     220/*----------------------------------------------------------------------------*/
     221void batch_control(usb_transfer_batch_t *instance,
     222    usb_direction_t data_dir, usb_direction_t status_dir)
     223{
     224        assert(instance);
     225        ohci_batch_t *data = instance->private_data;
     226        assert(data);
     227        ed_init(data->ed, instance->ep);
     228        ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
     229        usb_log_debug("Created ED: %x:%x:%x:%x.\n", data->ed->status,
     230            data->ed->td_tail, data->ed->td_head, data->ed->next);
     231        int toggle = 0;
     232        /* setup stage */
     233        td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     234                instance->setup_size, toggle);
     235        td_set_next(&data->tds[0], &data->tds[1]);
     236        usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0].status,
     237            data->tds[0].cbp, data->tds[0].next, data->tds[0].be);
     238
     239        /* data stage */
     240        size_t td_current = 1;
     241        size_t remain_size = instance->buffer_size;
     242        char *transfer_buffer = instance->transport_buffer;
     243        while (remain_size > 0) {
     244                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     245                    OHCI_TD_MAX_TRANSFER : remain_size;
     246                toggle = 1 - toggle;
     247
     248                td_init(&data->tds[td_current], data_dir, transfer_buffer,
     249                    transfer_size, toggle);
     250                td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
     251                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     252                    data->tds[td_current].status, data->tds[td_current].cbp,
     253                    data->tds[td_current].next, data->tds[td_current].be);
     254
     255                transfer_buffer += transfer_size;
     256                remain_size -= transfer_size;
     257                assert(td_current < data->td_count - 2);
     258                ++td_current;
     259        }
     260
     261        /* status stage */
     262        assert(td_current == data->td_count - 2);
     263        td_init(&data->tds[td_current], status_dir, NULL, 0, 1);
     264        usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
     265            data->tds[td_current].status, data->tds[td_current].cbp,
     266            data->tds[td_current].next, data->tds[td_current].be);
     267}
     268/*----------------------------------------------------------------------------*/
    162269/** Helper function calls callback and correctly disposes of batch structure.
    163270 *
  • uspace/drv/ohci/batch.h

    rf35b294 ra43f1d18  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbohci
     28/** @addtogroup drvusbuhcihc
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief OHCI driver USB transaction structure
     32 * @brief UHCI driver USB transaction structure
    3333 */
    34 #ifndef DRV_OHCI_BATCH_H
    35 #define DRV_OHCI_BATCH_H
    36 
     34#ifndef DRV_UHCI_BATCH_H
     35#define DRV_UHCI_BATCH_H
    3736
    3837#include <usbhc_iface.h>
    3938#include <usb/usb.h>
    4039#include <usb/host/device_keeper.h>
     40#include <usb/host/endpoint.h>
    4141#include <usb/host/batch.h>
    4242
     43#include "hw_struct/endpoint_descriptor.h"
     44
    4345usb_transfer_batch_t * batch_get(
    44     ddf_fun_t *fun,
    45                 usb_target_t target,
    46     usb_transfer_type_t transfer_type,
    47                 size_t max_packet_size,
    48     usb_speed_t speed,
    49                 char *buffer,
    50                 size_t size,
    51                 char *setup_buffer,
    52                 size_t setup_size,
     46    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
     47    char *setup_buffer, size_t setup_size,
    5348    usbhc_iface_transfer_in_callback_t func_in,
    5449    usbhc_iface_transfer_out_callback_t func_out,
    55                 void *arg,
    56                 usb_device_keeper_t *manager
    57                 );
     50    void *arg);
    5851
    5952void batch_dispose(usb_transfer_batch_t *instance);
     53
     54bool batch_is_complete(usb_transfer_batch_t *instance);
    6055
    6156void batch_control_write(usb_transfer_batch_t *instance);
     
    7065
    7166void batch_bulk_out(usb_transfer_batch_t *instance);
     67
     68ed_t * batch_ed(usb_transfer_batch_t *instance);
    7269#endif
    7370/**
  • uspace/drv/ohci/hc.c

    rf35b294 ra43f1d18  
    4747static void hc_gain_control(hc_t *instance);
    4848static void hc_init_hw(hc_t *instance);
     49static int hc_init_transfer_lists(hc_t *instance);
     50static int hc_init_memory(hc_t *instance);
    4951/*----------------------------------------------------------------------------*/
    5052int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
     
    5961            &instance->manager, hub_address, hub_fun->handle);
    6062
     63        endpoint_t *ep = malloc(sizeof(endpoint_t));
     64        assert(ep);
     65        int ret = endpoint_init(ep, hub_address, 0, USB_DIRECTION_BOTH,
     66            USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64);
     67        assert(ret == EOK);
     68        ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, 0);
     69        assert(ret == EOK);
     70
    6171        char *match_str = NULL;
    62         int ret = asprintf(&match_str, "usb&class=hub");
    63         ret = (match_str == NULL) ? ret : EOK;
     72        ret = asprintf(&match_str, "usb&class=hub");
     73//      ret = (match_str == NULL) ? ret : EOK;
    6474        if (ret < 0) {
    65                 usb_log_error("Failed to create root hub match-id string.\n");
     75                usb_log_error(
     76                    "Failed(%d) to create root hub match-id string.\n", ret);
    6677                return ret;
    6778        }
     
    107118        rh_init(&instance->rh, dev, instance->registers);
    108119
     120        hc_init_memory(instance);
    109121        hc_init_hw(instance);
    110122
     
    117129        assert(instance);
    118130        assert(batch);
     131
     132        /* check for root hub communication */
    119133        if (batch->target.address == instance->rh.address) {
    120134                return rh_request(&instance->rh, batch);
    121135        }
    122         /* TODO: implement */
    123         return ENOTSUP;
     136
     137        transfer_list_add_batch(
     138            instance->transfers[batch->transfer_type], batch);
     139
     140        switch (batch->transfer_type) {
     141        case USB_TRANSFER_CONTROL:
     142                instance->registers->command_status |= CS_CLF;
     143                break;
     144        case USB_TRANSFER_BULK:
     145                instance->registers->command_status |= CS_BLF;
     146                break;
     147        default:
     148                break;
     149        }
     150        return EOK;
    124151}
    125152/*----------------------------------------------------------------------------*/
     
    134161        usb_log_info("OHCI interrupt: %x.\n", status);
    135162
    136         /* TODO: Check for further interrupt causes */
    137         /* TODO: implement */
     163        LIST_INITIALIZE(done);
     164        transfer_list_remove_finished(&instance->transfers_interrupt, &done);
     165        transfer_list_remove_finished(&instance->transfers_isochronous, &done);
     166        transfer_list_remove_finished(&instance->transfers_control, &done);
     167        transfer_list_remove_finished(&instance->transfers_bulk, &done);
     168
     169        while (!list_empty(&done)) {
     170                link_t *item = done.next;
     171                list_remove(item);
     172                usb_transfer_batch_t *batch =
     173                    list_get_instance(item, usb_transfer_batch_t, link);
     174                usb_transfer_batch_finish(batch);
     175        }
    138176}
    139177/*----------------------------------------------------------------------------*/
     
    197235        assert(instance);
    198236        const uint32_t fm_interval = instance->registers->fm_interval;
     237
     238        /* reset hc */
    199239        instance->registers->command_status = CS_HCR;
    200240        async_usleep(10);
     241
     242        /* restore fm_interval */
    201243        instance->registers->fm_interval = fm_interval;
    202244        assert((instance->registers->command_status & CS_HCR) == 0);
     245
    203246        /* hc is now in suspend state */
    204         /* TODO: init HCCA block */
    205         /* TODO: init queues */
    206         /* TODO: enable queues */
     247
     248        /* enable queues */
     249        instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
    207250        /* TODO: enable interrupts */
    208         /* TODO: set periodic start to 90% */
     251        /* set periodic start to 90% */
     252        instance->registers->periodic_start = (fm_interval / 10) * 9;
    209253
    210254        instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
    211255        usb_log_info("OHCI HC up and running.\n");
     256}
     257/*----------------------------------------------------------------------------*/
     258int hc_init_transfer_lists(hc_t *instance)
     259{
     260        assert(instance);
     261
     262#define SETUP_TRANSFER_LIST(type, name) \
     263do { \
     264        int ret = transfer_list_init(&instance->type, name); \
     265        if (ret != EOK) { \
     266                usb_log_error("Failed(%d) to setup %s transfer list.\n", \
     267                    ret, name); \
     268                transfer_list_fini(&instance->transfers_isochronous); \
     269                transfer_list_fini(&instance->transfers_interrupt); \
     270                transfer_list_fini(&instance->transfers_control); \
     271                transfer_list_fini(&instance->transfers_bulk); \
     272        } \
     273} while (0)
     274
     275        SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS");
     276        SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT");
     277        SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
     278        SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
     279
     280        transfer_list_set_next(&instance->transfers_interrupt,
     281            &instance->transfers_isochronous);
     282
     283        /* Assign pointers to be used during scheduling */
     284        instance->transfers[USB_TRANSFER_INTERRUPT] =
     285          &instance->transfers_interrupt;
     286        instance->transfers[USB_TRANSFER_ISOCHRONOUS] =
     287          &instance->transfers_interrupt;
     288        instance->transfers[USB_TRANSFER_CONTROL] =
     289          &instance->transfers_control;
     290        instance->transfers[USB_TRANSFER_BULK] =
     291          &instance->transfers_bulk;
     292
     293        return EOK;
     294#undef CHECK_RET_CLEAR_RETURN
     295}
     296/*----------------------------------------------------------------------------*/
     297int hc_init_memory(hc_t *instance)
     298{
     299        assert(instance);
     300        /* init queues */
     301        hc_init_transfer_lists(instance);
     302
     303        /* init HCCA */
     304        instance->hcca = malloc32(sizeof(hcca_t));
     305        if (instance->hcca == NULL)
     306                return ENOMEM;
     307        bzero(instance->hcca, sizeof(hcca_t));
     308        instance->registers->hcca = addr_to_phys(instance->hcca);
     309
     310        /* use queues */
     311        instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
     312        instance->registers->control_head =
     313            instance->transfers_control.list_head_pa;
     314
     315        unsigned i = 0;
     316        for (; i < 32; ++i) {
     317                instance->hcca->int_ep[i] =
     318                    instance->transfers_interrupt.list_head_pa;
     319        }
     320
     321        return EOK;
    212322}
    213323/**
  • uspace/drv/ohci/hc.h

    rf35b294 ra43f1d18  
    4848#include "ohci_regs.h"
    4949#include "root_hub.h"
     50#include "transfer_list.h"
    5051#include "hw_struct/hcca.h"
    5152
     
    5455        usb_address_t rh_address;
    5556        rh_t rh;
     57
     58        hcca_t *hcca;
     59
     60        transfer_list_t transfers_isochronous;
     61        transfer_list_t transfers_interrupt;
     62        transfer_list_t transfers_control;
     63        transfer_list_t transfers_bulk;
     64
     65        transfer_list_t *transfers[4];
     66
    5667        ddf_fun_t *ddf_instance;
    5768        usb_device_keeper_t manager;
  • uspace/drv/ohci/hw_struct/completion_codes.h

    rf35b294 ra43f1d18  
    3535#define DRV_OHCI_HW_STRUCT_COMPLETION_CODES_H
    3636
     37#include <errno.h>
     38
    3739#define CC_NOERROR (0x0)
    3840#define CC_CRC (0x1)
     
    5052#define CC_NOACCESS2 (0xf)
    5153
     54inline static int cc_to_rc(int cc)
     55{
     56        switch (cc) {
     57        case CC_NOERROR:
     58                return EOK;
     59
     60        case CC_CRC:
     61                return EBADCHECKSUM;
     62
     63        case CC_PIDUNEXPECTED:
     64        case CC_PIDFAIL:
     65        case CC_BITSTUFF:
     66                return EIO;
     67
     68        case CC_TOGGLE:
     69        case CC_STALL:
     70                return ESTALL;
     71
     72        case CC_NORESPONSE:
     73                return ETIMEOUT;
     74
     75        case CC_DATAOVERRRUN:
     76        case CC_DATAUNDERRRUN:
     77        case CC_BUFFEROVERRRUN:
     78        case CC_BUFFERUNDERRUN:
     79                return EOVERFLOW;
     80
     81        case CC_NOACCESS1:
     82        case CC_NOACCESS2:
     83        default:
     84                return ENOTSUP;
     85        }
     86}
     87
    5288#endif
    5389/**
  • uspace/drv/ohci/hw_struct/endpoint_descriptor.h

    rf35b294 ra43f1d18  
    3535#define DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H
    3636
     37#include <assert.h>
    3738#include <stdint.h>
     39
     40#include <usb/host/endpoint.h>
     41
     42#include "utils/malloc32.h"
     43#include "transfer_descriptor.h"
    3844
    3945#include "completion_codes.h"
     
    4450#define ED_STATUS_FA_SHIFT (0)
    4551#define ED_STATUS_EN_MASK (0xf)    /* USB endpoint address */
    46 #define ED_STATUS_EN_SHIFT (6)
     52#define ED_STATUS_EN_SHIFT (7)
    4753#define ED_STATUS_D_MASK (0x3)     /* direction */
    48 #define ED_STATUS_D_SHIFT (10)
     54#define ED_STATUS_D_SHIFT (11)
    4955#define ED_STATUS_D_IN (0x1)
    5056#define ED_STATUS_D_OUT (0x2)
     57#define ED_STATUS_D_TRANSFER (0x3)
    5158
    52 #define ED_STATUS_S_FLAG (1 << 13) /* speed flag */
     59#define ED_STATUS_S_FLAG (1 << 13) /* speed flag: 1 = low */
    5360#define ED_STATUS_K_FLAG (1 << 14) /* skip flag (no not execute this ED) */
    5461#define ED_STATUS_F_FLAG (1 << 15) /* format: 1 = isochronous*/
     
    7178#define ED_NEXT_PTR_SHIFT (0)
    7279} __attribute__((packed)) ed_t;
     80
     81void ed_init(ed_t *instance, endpoint_t *ep);
     82
     83static inline void ed_add_tds(ed_t *instance, td_t *head, td_t *tail)
     84{
     85        assert(instance);
     86        instance->td_head = addr_to_phys(head) & ED_TDHEAD_PTR_MASK;
     87        instance->td_tail = addr_to_phys(tail) & ED_TDTAIL_PTR_MASK;
     88}
     89
     90static inline void ed_append_ed(ed_t *instance, ed_t *next)
     91{
     92        assert(instance);
     93        assert(next);
     94        uint32_t pa = addr_to_phys(next);
     95        assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa);
     96        instance->next = pa;
     97}
     98
    7399#endif
    74100/**
  • uspace/drv/ohci/hw_struct/transfer_descriptor.h

    rf35b294 ra43f1d18  
    3535#define DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
    3636
     37#include <bool.h>
    3738#include <stdint.h>
     39#include "utils/malloc32.h"
    3840
    3941#include "completion_codes.h"
     42
     43/* OHCI TDs can handle up to 8KB buffers */
     44#define OHCI_TD_MAX_TRANSFER (8 * 1024)
    4045
    4146typedef struct td {
     
    5257#define TD_STATUS_T_MASK (0x3)  /* data toggle 1x = use ED toggle carry */
    5358#define TD_STATUS_T_SHIFT (24)
     59#define TD_STATUS_T_0 (0x2)
     60#define TD_STATUS_T_1 (0x3)
    5461#define TD_STATUS_EC_MASK (0x3) /* error count */
    5562#define TD_STATUS_EC_SHIFT (26)
     
    6471        volatile uint32_t be; /* buffer end, address of the last byte */
    6572} __attribute__((packed)) td_t;
     73
     74void td_init(
     75    td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle);
     76
     77inline static void td_set_next(td_t *instance, td_t *next)
     78{
     79        assert(instance);
     80        instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK;
     81}
     82
     83inline static bool td_is_finished(td_t *instance)
     84{
     85        assert(instance);
     86        int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
     87        /* something went wrong, error code is set */
     88        if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2 && cc != CC_NOERROR) {
     89                return true;
     90        }
     91        /* everything done */
     92        if (cc == CC_NOERROR && instance->cbp == 0) {
     93                return true;
     94        }
     95        return false;
     96}
     97
     98static inline int td_error(td_t *instance)
     99{
     100        assert(instance);
     101        int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
     102        return cc_to_rc(cc);
     103}
    66104#endif
    67105/**
  • uspace/drv/ohci/iface.c

    rf35b294 ra43f1d18  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky
     2 * Copyright (c) 2011 Vojtech Horky, Jan Vesely
    33 * All rights reserved.
    44 *
     
    3030 */
    3131/** @file
    32  * USB-HC interface implementation.
     32 * @brief OHCI driver hc interface implementation
    3333 */
    3434#include <ddf/driver.h>
     
    3636
    3737#include <usb/debug.h>
     38#include <usb/host/endpoint.h>
    3839
    3940#include "iface.h"
    4041#include "hc.h"
    4142
    42 #define UNSUPPORTED(methodname) \
    43         usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \
    44             methodname, __FILE__, __LINE__)
    45 
    46 /** Reserve default address.
    47  *
    48  * This function may block the caller.
    49  *
    50  * @param[in] fun Device function the action was invoked on.
    51  * @param[in] speed Speed of the device for which the default address is
    52  *      reserved.
     43static inline int setup_batch(
     44    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
     45    void *data, size_t size, void * setup_data, size_t setup_size,
     46    usbhc_iface_transfer_in_callback_t in,
     47    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
     48    hc_t **hc, usb_transfer_batch_t **batch)
     49{
     50        assert(hc);
     51        assert(batch);
     52        assert(fun);
     53        *hc = fun_to_hc(fun);
     54        assert(*hc);
     55
     56        size_t res_bw;
     57        endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
     58            target.address, target.endpoint, direction, &res_bw);
     59        if (ep == NULL) {
     60                usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
     61                    target.address, target.endpoint, name);
     62                return ENOENT;
     63        }
     64
     65        const size_t bw = bandwidth_count_usb11(
     66            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     67        if (res_bw < bw) {
     68                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
     69                    "but only %zu is reserved.\n",
     70                    name, target.address, target.endpoint, bw, res_bw);
     71                return ENOSPC;
     72        }
     73        usb_log_debug("%s %d:%d %zu(%zu).\n",
     74            name, target.address, target.endpoint, size, ep->max_packet_size);
     75
     76        assert(ep->speed ==
     77            usb_device_keeper_get_speed(&(*hc)->manager, target.address));
     78//      assert(ep->max_packet_size == max_packet_size);
     79//      assert(ep->transfer_type == USB_TRANSFER_CONTROL);
     80
     81        *batch =
     82            batch_get(fun, ep, data, size, setup_data, setup_size,
     83                in, out, arg);
     84        if (!batch)
     85                return ENOMEM;
     86        return EOK;
     87}
     88
     89
     90/** Reserve default address interface function
     91 *
     92 * @param[in] fun DDF function that was called.
     93 * @param[in] speed Speed to associate with the new default address.
    5394 * @return Error code.
    5495 */
     
    61102        usb_device_keeper_reserve_default_address(&hc->manager, speed);
    62103        return EOK;
    63 }
    64 /*----------------------------------------------------------------------------*/
    65 /** Release default address.
    66  *
    67  * @param[in] fun Device function the action was invoked on.
     104#if 0
     105        endpoint_t *ep = malloc(sizeof(endpoint_t));
     106        if (ep == NULL)
     107                return ENOMEM;
     108        const size_t max_packet_size = speed == USB_SPEED_LOW ? 8 : 64;
     109        endpoint_init(ep, USB_TRANSFER_CONTROL, speed, max_packet_size);
     110        int ret;
     111try_retgister:
     112        ret = usb_endpoint_manager_register_ep(&hc->ep_manager,
     113            USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH, ep, endpoint_destroy, 0);
     114        if (ret == EEXISTS) {
     115                async_usleep(1000);
     116                goto try_retgister;
     117        }
     118        if (ret != EOK) {
     119                endpoint_destroy(ep);
     120        }
     121        return ret;
     122#endif
     123}
     124/*----------------------------------------------------------------------------*/
     125/** Release default address interface function
     126 *
     127 * @param[in] fun DDF function that was called.
    68128 * @return Error code.
    69129 */
     
    74134        assert(hc);
    75135        usb_log_debug("Default address release.\n");
     136//      return usb_endpoint_manager_unregister_ep(&hc->ep_manager,
     137//          USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH);
    76138        usb_device_keeper_release_default_address(&hc->manager);
    77139        return EOK;
    78140}
    79141/*----------------------------------------------------------------------------*/
    80 /** Found free USB address.
    81  *
    82  * @param[in] fun Device function the action was invoked on.
    83  * @param[in] speed Speed of the device that will get this address.
    84  * @param[out] address Non-null pointer where to store the free address.
     142/** Request address interface function
     143 *
     144 * @param[in] fun DDF function that was called.
     145 * @param[in] speed Speed to associate with the new default address.
     146 * @param[out] address Place to write a new address.
    85147 * @return Error code.
    86148 */
     
    101163}
    102164/*----------------------------------------------------------------------------*/
    103 /** Bind USB address with device devman handle.
    104  *
    105  * @param[in] fun Device function the action was invoked on.
    106  * @param[in] address USB address of the device.
    107  * @param[in] handle Devman handle of the device.
     165/** Bind address interface function
     166 *
     167 * @param[in] fun DDF function that was called.
     168 * @param[in] address Address of the device
     169 * @param[in] handle Devman handle of the device driver.
    108170 * @return Error code.
    109171 */
    110172static int bind_address(
    111     ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
     173  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
    112174{
    113175        assert(fun);
     
    119181}
    120182/*----------------------------------------------------------------------------*/
    121 /** Release previously requested address.
    122  *
    123  * @param[in] fun Device function the action was invoked on.
     183/** Release address interface function
     184 *
     185 * @param[in] fun DDF function that was called.
    124186 * @param[in] address USB address to be released.
    125187 * @return Error code.
     
    139201 * @param[in] fun Device function the action was invoked on.
    140202 * @param[in] address USB address of the device.
     203 * @param[in] ep_speed Endpoint speed (invalid means to use device one).
    141204 * @param[in] endpoint Endpoint number.
    142205 * @param[in] transfer_type USB transfer type.
     
    146209 * @return Error code.
    147210 */
    148 static int register_endpoint(
    149     ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
     211static int register_endpoint(ddf_fun_t *fun,
     212    usb_address_t address, usb_speed_t ep_speed, usb_endpoint_t endpoint,
    150213    usb_transfer_type_t transfer_type, usb_direction_t direction,
    151214    size_t max_packet_size, unsigned int interval)
    152215{
    153         assert(fun);
    154216        hc_t *hc = fun_to_hc(fun);
    155217        assert(hc);
    156218        if (address == hc->rh.address)
    157219                return EOK;
    158         const usb_speed_t speed =
    159                 usb_device_keeper_get_speed(&hc->manager, address);
    160         const size_t size = max_packet_size;
     220        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
     221        if (speed >= USB_SPEED_MAX) {
     222                speed = ep_speed;
     223        }
     224        const size_t size =
     225            (transfer_type == USB_TRANSFER_INTERRUPT
     226            || transfer_type == USB_TRANSFER_ISOCHRONOUS) ?
     227            max_packet_size : 0;
     228        int ret;
     229
     230        endpoint_t *ep = malloc(sizeof(endpoint_t));
     231        if (ep == NULL)
     232                return ENOMEM;
     233        ret = endpoint_init(ep, address, endpoint, direction,
     234            transfer_type, speed, max_packet_size);
     235        if (ret != EOK) {
     236                free(ep);
     237                return ret;
     238        }
     239
    161240        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    162241            address, endpoint, usb_str_transfer_type(transfer_type),
    163242            usb_str_speed(speed), direction, size, max_packet_size, interval);
    164         // TODO use real endpoint here!
    165         return usb_endpoint_manager_register_ep(&hc->ep_manager,NULL, 0);
    166 }
    167 /*----------------------------------------------------------------------------*/
    168 /** Unregister endpoint (free some bandwidth reservation).
    169  *
    170  * @param[in] fun Device function the action was invoked on.
    171  * @param[in] address USB address of the device.
    172  * @param[in] endpoint Endpoint number.
    173  * @param[in] direction Endpoint data direction.
    174  * @return Error code.
    175  */
     243
     244        ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
     245        if (ret != EOK) {
     246                endpoint_destroy(ep);
     247        } else {
     248                usb_device_keeper_add_ep(&hc->manager, address, ep);
     249        }
     250        return ret;
     251}
     252/*----------------------------------------------------------------------------*/
    176253static int unregister_endpoint(
    177254    ddf_fun_t *fun, usb_address_t address,
    178255    usb_endpoint_t endpoint, usb_direction_t direction)
    179256{
    180         assert(fun);
    181257        hc_t *hc = fun_to_hc(fun);
    182258        assert(hc);
    183259        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    184260            address, endpoint, direction);
     261        endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
     262            address, endpoint, direction, NULL);
     263        if (ep != NULL) {
     264                usb_device_keeper_del_ep(&hc->manager, address, ep);
     265        }
    185266        return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    186267            endpoint, direction);
     
    196277 * @param[in] fun Device function the action was invoked on.
    197278 * @param[in] target Target pipe (address and endpoint number) specification.
    198  * @param[in] max_packet_size Max packet size for the transfer.
    199279 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    200280 *      by the caller).
     
    205285 */
    206286static int interrupt_out(
    207     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     287    ddf_fun_t *fun, usb_target_t target, void *data,
    208288    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    209289{
    210         assert(fun);
    211         hc_t *hc = fun_to_hc(fun);
    212         assert(hc);
    213         usb_speed_t speed =
    214             usb_device_keeper_get_speed(&hc->manager, target.address);
    215 
    216         usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n",
    217             target.address, target.endpoint, size, max_packet_size);
    218 
    219         usb_transfer_batch_t *batch =
    220             batch_get(fun, target, USB_TRANSFER_INTERRUPT, max_packet_size,
    221                 speed, data, size, NULL, 0, NULL, callback, arg, &hc->manager);
    222         if (!batch)
    223                 return ENOMEM;
     290        usb_transfer_batch_t *batch = NULL;
     291        hc_t *hc = NULL;
     292        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     293            NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
     294        if (ret != EOK)
     295                return ret;
    224296        batch_interrupt_out(batch);
    225         const int ret = hc_schedule(hc, batch);
     297        ret = hc_schedule(hc, batch);
    226298        if (ret != EOK) {
    227299                batch_dispose(batch);
     
    239311 * @param[in] fun Device function the action was invoked on.
    240312 * @param[in] target Target pipe (address and endpoint number) specification.
    241  * @param[in] max_packet_size Max packet size for the transfer.
    242313 * @param[in] data Buffer where to store the data (in USB endianess,
    243314 *      allocated and deallocated by the caller).
     
    248319 */
    249320static int interrupt_in(
    250     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     321    ddf_fun_t *fun, usb_target_t target, void *data,
    251322    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    252323{
    253         assert(fun);
    254         hc_t *hc = fun_to_hc(fun);
    255         assert(hc);
    256         usb_speed_t speed =
    257             usb_device_keeper_get_speed(&hc->manager, target.address);
    258         usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n",
    259             target.address, target.endpoint, size, max_packet_size);
    260 
    261         usb_transfer_batch_t *batch =
    262             batch_get(fun, target, USB_TRANSFER_INTERRUPT, max_packet_size,
    263                 speed, data, size, NULL, 0, callback, NULL, arg, &hc->manager);
    264         if (!batch)
    265                 return ENOMEM;
     324        usb_transfer_batch_t *batch = NULL;
     325        hc_t *hc = NULL;
     326        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     327            NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
     328        if (ret != EOK)
     329                return ret;
    266330        batch_interrupt_in(batch);
    267         const int ret = hc_schedule(hc, batch);
     331        ret = hc_schedule(hc, batch);
    268332        if (ret != EOK) {
    269333                batch_dispose(batch);
     
    281345 * @param[in] fun Device function the action was invoked on.
    282346 * @param[in] target Target pipe (address and endpoint number) specification.
    283  * @param[in] max_packet_size Max packet size for the transfer.
    284347 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    285348 *      by the caller).
     
    290353 */
    291354static int bulk_out(
    292     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     355    ddf_fun_t *fun, usb_target_t target, void *data,
    293356    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    294357{
    295         assert(fun);
    296         hc_t *hc = fun_to_hc(fun);
    297         assert(hc);
    298         usb_speed_t speed =
    299             usb_device_keeper_get_speed(&hc->manager, target.address);
    300 
    301         usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
    302             target.address, target.endpoint, size, max_packet_size);
    303 
    304         usb_transfer_batch_t *batch =
    305             batch_get(fun, target, USB_TRANSFER_BULK, max_packet_size, speed,
    306                 data, size, NULL, 0, NULL, callback, arg, &hc->manager);
    307         if (!batch)
    308                 return ENOMEM;
     358        usb_transfer_batch_t *batch = NULL;
     359        hc_t *hc = NULL;
     360        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     361            NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
     362        if (ret != EOK)
     363                return ret;
    309364        batch_bulk_out(batch);
    310         const int ret = hc_schedule(hc, batch);
     365        ret = hc_schedule(hc, batch);
    311366        if (ret != EOK) {
    312367                batch_dispose(batch);
     
    324379 * @param[in] fun Device function the action was invoked on.
    325380 * @param[in] target Target pipe (address and endpoint number) specification.
    326  * @param[in] max_packet_size Max packet size for the transfer.
    327381 * @param[in] data Buffer where to store the data (in USB endianess,
    328382 *      allocated and deallocated by the caller).
     
    333387 */
    334388static int bulk_in(
    335     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     389    ddf_fun_t *fun, usb_target_t target, void *data,
    336390    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    337391{
    338         assert(fun);
    339         hc_t *hc = fun_to_hc(fun);
    340         assert(hc);
    341         usb_speed_t speed =
    342             usb_device_keeper_get_speed(&hc->manager, target.address);
    343         usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
    344             target.address, target.endpoint, size, max_packet_size);
    345 
    346         usb_transfer_batch_t *batch =
    347             batch_get(fun, target, USB_TRANSFER_BULK, max_packet_size, speed,
    348                 data, size, NULL, 0, callback, NULL, arg, &hc->manager);
    349         if (!batch)
    350                 return ENOMEM;
     392        usb_transfer_batch_t *batch = NULL;
     393        hc_t *hc = NULL;
     394        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     395            NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
     396        if (ret != EOK)
     397                return ret;
    351398        batch_bulk_in(batch);
    352         const int ret = hc_schedule(hc, batch);
     399        ret = hc_schedule(hc, batch);
    353400        if (ret != EOK) {
    354401                batch_dispose(batch);
     
    366413 * @param[in] fun Device function the action was invoked on.
    367414 * @param[in] target Target pipe (address and endpoint number) specification.
    368  * @param[in] max_packet_size Max packet size for the transfer.
    369415 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    370416 *      and deallocated by the caller).
     
    378424 */
    379425static int control_write(
    380     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     426    ddf_fun_t *fun, usb_target_t target,
    381427    void *setup_data, size_t setup_size, void *data, size_t size,
    382428    usbhc_iface_transfer_out_callback_t callback, void *arg)
    383429{
    384         assert(fun);
    385         hc_t *hc = fun_to_hc(fun);
    386         assert(hc);
    387         usb_speed_t speed =
    388             usb_device_keeper_get_speed(&hc->manager, target.address);
    389         usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n",
    390             speed, target.address, target.endpoint, size, max_packet_size);
    391 
    392         if (setup_size != 8)
    393                 return EINVAL;
    394 
    395         usb_transfer_batch_t *batch =
    396             batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size,
    397                 speed, data, size, setup_data, setup_size, NULL, callback, arg,
    398                 &hc->manager);
    399         if (!batch)
    400                 return ENOMEM;
     430        usb_transfer_batch_t *batch = NULL;
     431        hc_t *hc = NULL;
     432        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     433            setup_data, setup_size, NULL, callback, arg, "Control WRITE",
     434            &hc, &batch);
     435        if (ret != EOK)
     436                return ret;
    401437        usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
    402438        batch_control_write(batch);
    403         const int ret = hc_schedule(hc, batch);
     439        ret = hc_schedule(hc, batch);
    404440        if (ret != EOK) {
    405441                batch_dispose(batch);
     
    417453 * @param[in] fun Device function the action was invoked on.
    418454 * @param[in] target Target pipe (address and endpoint number) specification.
    419  * @param[in] max_packet_size Max packet size for the transfer.
    420455 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    421456 *      and deallocated by the caller).
     
    429464 */
    430465static int control_read(
    431     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     466    ddf_fun_t *fun, usb_target_t target,
    432467    void *setup_data, size_t setup_size, void *data, size_t size,
    433468    usbhc_iface_transfer_in_callback_t callback, void *arg)
    434469{
    435         assert(fun);
    436         hc_t *hc = fun_to_hc(fun);
    437         assert(hc);
    438         usb_speed_t speed =
    439             usb_device_keeper_get_speed(&hc->manager, target.address);
    440 
    441         usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n",
    442             speed, target.address, target.endpoint, size, max_packet_size);
    443         usb_transfer_batch_t *batch =
    444             batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size,
    445                 speed, data, size, setup_data, setup_size, callback, NULL, arg,
    446                 &hc->manager);
    447         if (!batch)
    448                 return ENOMEM;
     470        usb_transfer_batch_t *batch = NULL;
     471        hc_t *hc = NULL;
     472        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     473            setup_data, setup_size, callback, NULL, arg, "Control READ",
     474            &hc, &batch);
     475        if (ret != EOK)
     476                return ret;
    449477        batch_control_read(batch);
    450         const int ret = hc_schedule(hc, batch);
     478        ret = hc_schedule(hc, batch);
    451479        if (ret != EOK) {
    452480                batch_dispose(batch);
     
    455483}
    456484/*----------------------------------------------------------------------------*/
    457 /** Host controller interface implementation for OHCI. */
    458485usbhc_iface_t hc_iface = {
    459486        .reserve_default_address = reserve_default_address,
     
    475502        .control_read = control_read,
    476503};
    477 
    478504/**
    479505 * @}
  • uspace/drv/ohci/ohci_regs.h

    rf35b294 ra43f1d18  
    4141        const volatile uint32_t revision;
    4242        volatile uint32_t control;
    43 #define C_CSBR_MASK (0x3)
     43#define C_CSBR_MASK (0x3) /* Control-bulk service ratio */
     44#define C_CSBR_1_1  (0x0)
     45#define C_CSBR_1_2  (0x1)
     46#define C_CSBR_1_3  (0x2)
     47#define C_CSBR_1_4  (0x3)
    4448#define C_CSBR_SHIFT (0)
    45 #define C_PLE (1 << 2)
    46 #define C_IE (1 << 3)
    47 #define C_CLE (1 << 4)
    48 #define C_BLE (1 << 5)
    49 
    50 #define C_HCFS_MASK (0x3)
    51 #define C_HCFS_SHIFT (6)
    52 #define C_HCFS_RESET (0x0)
     49
     50#define C_PLE (1 << 2)   /* Periodic list enable */
     51#define C_IE  (1 << 3)   /* Isochronous enable */
     52#define C_CLE (1 << 4)   /* Control list enable */
     53#define C_BLE (1 << 5)   /* Bulk list enable */
     54
     55#define C_HCFS_MASK        (0x3) /* Host controller functional state */
     56#define C_HCFS_RESET       (0x0)
    5357#define C_HCFS_OPERATIONAL (0x1)
    54 #define C_HCFS_RESUME (0x2)
    55 #define C_HCFS_SUSPEND (0x3)
    56 
    57 #define C_IR (1 << 8)
    58 #define C_RWC (1 << 9)
    59 #define C_RWE (1 << 10)
     58#define C_HCFS_RESUME      (0x2)
     59#define C_HCFS_SUSPEND     (0x3)
     60#define C_HCFS_SHIFT       (6)
     61
     62#define C_IR  (1 << 8)   /* Interrupt routing, make sure it's 0 */
     63#define C_RWC (1 << 9)   /* Remote wakeup connected, host specific */
     64#define C_RWE (1 << 10)  /* Remote wakeup enable */
    6065
    6166        volatile uint32_t command_status;
    62 #define CS_HCR (1 << 0)
    63 #define CS_CLF (1 << 1)
    64 #define CS_BLF (1 << 2)
    65 #define CS_OCR (1 << 3)
    66 #define CS_SOC_MASK (0x3)
     67#define CS_HCR (1 << 0)   /* Host controller reset */
     68#define CS_CLF (1 << 1)   /* Control list filled */
     69#define CS_BLF (1 << 2)   /* Bulk list filled */
     70#define CS_OCR (1 << 3)   /* Ownership change request */
     71#define CS_SOC_MASK (0x3) /* Scheduling overrun count */
    6772#define CS_SOC_SHIFT (16)
    6873
    6974        volatile uint32_t interrupt_status;
    70 #define IS_SO (1 << 0)
    71 #define IS_WDH (1 << 1)
    72 #define IS_SF (1 << 2)
    73 #define IS_RD (1 << 3)
    74 #define IS_UE (1 << 4)
    75 #define IS_FNO (1 << 5)
    76 #define IS_RHSC (1 << 6)
    77 #define IS_OC (1 << 30)
    78 
     75#define IS_SO   (1 << 0)  /* Scheduling overrun */
     76#define IS_WDH  (1 << 1)  /* Write-back done head */
     77#define IS_SF   (1 << 2)  /* Start of frame */
     78#define IS_RD   (1 << 3)  /* Resume detected */
     79#define IS_UE   (1 << 4)  /* Unrecoverable error */
     80#define IS_FNO  (1 << 5)  /* Frame number overflow */
     81#define IS_RHSC (1 << 6)  /* Root hub status change */
     82#define IS_OC   (1 << 30) /* Ownership change */
     83
     84        /** Interupt enable/disable, reads give the same value, writing causes
     85         * enable/disable */
    7986        volatile uint32_t interupt_enable;
    80 #define IE_SO   (1 << 0)
    81 #define IE_WDH  (1 << 1)
    82 #define IE_SF   (1 << 2)
    83 #define IE_RD   (1 << 3)
    84 #define IE_UE   (1 << 4)
    85 #define IE_FNO  (1 << 5)
    86 #define IE_RHSC (1 << 6)
    87 #define IE_OC   (1 << 30)
    88 #define IE_MIE  (1 << 31)
    89 
    9087        volatile uint32_t interrupt_disable;
     88#define I_SO   (1 << 0)   /* Scheduling overrun */
     89#define I_WDH  (1 << 1)   /* Done head write-back */
     90#define I_SF   (1 << 2)   /* Start of frame */
     91#define I_RD   (1 << 3)   /* Resume detect */
     92#define I_UE   (1 << 4)   /* Unrecoverable error */
     93#define I_FNO  (1 << 5)   /* Frame number overflow */
     94#define I_RHSC (1 << 6)   /* Root hub status change */
     95#define I_OC   (1 << 30)  /* Ownership change */
     96#define I_MI   (1 << 31)  /* Master interrupt (all/any interrupts) */
     97
     98        /** HCCA pointer (see hw_struct hcca.h) */
    9199        volatile uint32_t hcca;
    92         volatile uint32_t period_corrent;
     100#define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */
     101
     102        /** Currently executed period endpoint */
     103        const volatile uint32_t period_current;
     104
     105        /** The first control endpoint */
    93106        volatile uint32_t control_head;
     107
     108        /** Currently executed control endpoint */
    94109        volatile uint32_t control_current;
     110
     111        /** The first bulk endpoint */
    95112        volatile uint32_t bulk_head;
     113
     114        /** Currently executed bulk endpoint */
    96115        volatile uint32_t bulk_current;
    97         volatile uint32_t done_head;
     116
     117        /** Done TD list, this value is periodically written to HCCA */
     118        const volatile uint32_t done_head;
     119
     120        /** Frame time and max packet size for all transfers */
    98121        volatile uint32_t fm_interval;
    99         volatile uint32_t fm_remaining;
    100         volatile uint32_t fm_number;
     122#define FMI_FI_MASK (0x1fff) /* Frame interval in bit times (should be 11999)*/
     123#define FMI_FI_SHIFT (0)
     124#define FMI_FSMPS_MASK (0x7fff) /* Full speed max packet size */
     125#define FMI_FSMPS_SHIFT (16)
     126#define FMI_TOGGLE_FLAG (1 << 31)
     127
     128        /** Bit times remaining in current frame */
     129        const volatile uint32_t fm_remaining;
     130#define FMR_FR_MASK FMI_FI_MASK
     131#define FMR_FR_SHIFT FMI_FI_SHIFT
     132#define FMR_TOGGLE_FLAG FMI_TOGGLE_FLAG
     133
     134        /** Frame number */
     135        const volatile uint32_t fm_number;
     136#define FMN_NUMBER_MASK (0xffff)
     137
     138        /** Remaining bit time in frame to start periodic transfers */
    101139        volatile uint32_t periodic_start;
     140#define PS_PS_MASK (0x1fff) /* bit time when periodic get priority (0x3e67) */
     141
     142        /** Threshold for starting LS transaction */
    102143        volatile uint32_t ls_threshold;
     144#define LST_LST_MASK (0x7fff)
     145
     146        /** The first root hub control register */
    103147        volatile uint32_t rh_desc_a;
     148#define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */
     149#define RHDA_NDS_SHIFT (0)
     150#define RHDA_PSM_FLAG  (1 << 8)  /* Power switching mode: 0-global, 1-per port*/
     151#define RHDA_NPS_FLAG  (1 << 9)  /* No power switch: 1-power on, 0-use PSM*/
     152#define RHDA_DT_FLAG   (1 << 10) /* 1-Compound device, must be 0 */
     153#define RHDA_OCPM_FLAG (1 << 11) /* Over-current mode: 0-global, 1-per port */
     154#define RHDA_NOCP      (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
     155#define RHDA_POTPGT_MASK (0xff)  /* Power on to power good time */
     156#define RHDA_POTPGT_SHIFT (24)
     157
     158        /** The other root hub control register */
    104159        volatile uint32_t rh_desc_b;
     160#define RHDB_DR_MASK (0xffff) /* Device removable mask */
     161#define RHDB_DR_SHIFT (0)
     162#define RHDB_PCC_MASK (0xffff) /* Power control mask */
     163#define RHDB_PCC_SHIFT (16)
     164
     165/* Port device removable status */
     166#define RHDB_DR_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
     167/* Port power control status: 1-per port power control, 0-global power switch */
     168#define RHDB_PPC_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
     169
     170        /** Root hub status register */
    105171        volatile uint32_t rh_status;
     172#define RHS_LPS_FLAG  (1 <<  0)/* read: 0,
     173                                * write: 0-no effect,
     174                                *        1-turn off port power for ports
     175                                *        specified in PPCM(RHDB), or all ports,
     176                                *        if power is set globally */
     177#define RHS_CLEAR_PORT_POWER RHS_LPS_FLAG /* synonym for the above */
     178#define RHS_OCI_FLAG  (1 <<  1)/* Over-current indicator, if per-port: 0 */
     179#define RHS_DRWE_FLAG (1 << 15)/* read: 0-connect status change does not wake HC
     180                                *       1-connect status change wakes HC
     181                                * write: 1-set DRWE, 0-no effect */
     182#define RHS_SET_DRWE RHS_DRWE_FLAG
     183#define RHS_LPSC_FLAG (1 << 16)/* read: 0,
     184                                * write: 0-no effect
     185                                *        1-turn on port power for ports
     186                                *        specified in PPCM(RHDB), or all ports,
     187                                *        if power is set globally */
     188#define RHS_SET_PORT_POWER RHS_LPSC_FLAG /* synonym for the above */
     189#define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change   */
     190#define RHS_CLEAR_DRWE (1 << 31)
     191
     192        /** Root hub per port status */
    106193        volatile uint32_t rh_port_status[];
     194#define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
     195                                * w: 1-clear port enable, 0-nothing */
     196#define RHPS_CLEAR_PORT_ENABLE RHPS_CCS_FLAG
     197#define RHPS_PES_FLAG (1 << 1) /* r: port enable status
     198                                * w: 1-set port enable, 0-nothing */
     199#define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG
     200#define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status
     201                                * w: 1-set port suspend, 0-nothing */
     202#define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG
     203#define RHPS_POCI_FLAG (1 << 3) /* r: port over-current (if reports are per-port
     204                                 * w: 1-clear port suspend (start resume
     205                                 *      if suspened)
     206                                 *    0-nothing */
     207#define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG
     208#define RHPS_PRS_FLAG (1 << 4) /* r: port reset status
     209                                * w: 1-set port reset, 0-nothing */
     210#define RHPS_SET_PORT_RESET RHPS_PRS_FLAG
     211#define RHPS_PPS_FLAG (1 << 8) /* r: port power status
     212                                * w: 1-set port power, 0-nothing */
     213#define RHPS_SET_PORT_POWER RHPS_PPS_FLAG
     214#define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached
     215                                 * w: 1-clear port power, 0-nothing */
     216#define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG
     217#define RHPS_CSC_FLAG  (1 << 16) /* connect status change Write-Clean */
     218#define RHPS_PESC_FLAG (1 << 17) /* port enable status change WC */
     219#define RHPS_PSSC_FLAG (1 << 18) /* port suspend status change WC */
     220#define RHPS_OCIC_FLAG (1 << 19) /* port over-current change WC */
     221#define RHPS_PRSC_FLAG (1 << 20) /* port reset status change WC */
     222#define RHPS_CHANGE_WC_MASK 0x1f0000
    107223} __attribute__((packed)) ohci_regs_t;
    108224#endif
  • uspace/drv/ohci/utils/malloc32.h

    rf35b294 ra43f1d18  
    3737#include <assert.h>
    3838#include <malloc.h>
     39#include <errno.h>
    3940#include <mem.h>
    4041#include <as.h>
  • uspace/drv/uhci-hcd/batch.c

    rf35b294 ra43f1d18  
    103103        usb_target_t target =
    104104            { .address = ep->address, .endpoint = ep->endpoint };
    105         usb_transfer_batch_init(instance, target,
    106             ep->transfer_type, ep->speed, ep->max_packet_size,
    107             buffer, NULL, buffer_size, NULL, setup_size, func_in,
    108             func_out, arg, fun, ep, NULL);
     105        usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed,
     106            ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
     107            func_in, func_out, arg, fun, ep, NULL);
    109108
    110109
    111110        uhci_batch_t *data = malloc(sizeof(uhci_batch_t));
    112         CHECK_NULL_DISPOSE_RETURN(instance,
    113             "Failed to allocate batch instance.\n");
     111        CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
    114112        bzero(data, sizeof(uhci_batch_t));
    115113        instance->private_data = data;
  • uspace/drv/uhci-hcd/hc.c

    rf35b294 ra43f1d18  
    240240        usb_log_debug("Initialized device manager.\n");
    241241
    242         ret =
    243             usb_endpoint_manager_init(&instance->ep_manager,
    244                 BANDWIDTH_AVAILABLE_USB11);
     242        ret = usb_endpoint_manager_init(&instance->ep_manager,
     243            BANDWIDTH_AVAILABLE_USB11);
    245244        assert(ret == EOK);
    246245
  • uspace/drv/uhci-hcd/iface.c

    rf35b294 ra43f1d18  
    7474            name, target.address, target.endpoint, size, ep->max_packet_size);
    7575
    76         assert(ep->speed ==
    77             usb_device_keeper_get_speed(&(*hc)->manager, target.address));
     76//      assert(ep->speed ==
     77//          usb_device_keeper_get_speed(&(*hc)->manager, target.address));
    7878//      assert(ep->max_packet_size == max_packet_size);
    7979//      assert(ep->transfer_type == USB_TRANSFER_CONTROL);
     
    198198/*----------------------------------------------------------------------------*/
    199199static int register_endpoint(
    200     ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
     200    ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
     201    usb_endpoint_t endpoint,
    201202    usb_transfer_type_t transfer_type, usb_direction_t direction,
    202203    size_t max_packet_size, unsigned int interval)
     
    204205        hc_t *hc = fun_to_hc(fun);
    205206        assert(hc);
    206         const usb_speed_t speed =
    207             usb_device_keeper_get_speed(&hc->manager, address);
     207        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
     208        if (speed >= USB_SPEED_MAX) {
     209                speed = ep_speed;
     210        }
    208211        const size_t size =
    209212            (transfer_type == USB_TRANSFER_INTERRUPT
     
    243246        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    244247            address, endpoint, direction);
     248        endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
     249            address, endpoint, direction, NULL);
     250        if (ep != NULL) {
     251                usb_device_keeper_del_ep(&hc->manager, address, ep);
     252        }
    245253        return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    246254            endpoint, direction);
     
    251259 * @param[in] fun DDF function that was called.
    252260 * @param[in] target USB device to write to.
    253  * @param[in] max_packet_size maximum size of data packet the device accepts
    254261 * @param[in] data Source of data.
    255262 * @param[in] size Size of data source.
     
    259266 */
    260267static int interrupt_out(
    261     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     268    ddf_fun_t *fun, usb_target_t target, void *data,
    262269    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    263270{
     
    280287 * @param[in] fun DDF function that was called.
    281288 * @param[in] target USB device to write to.
    282  * @param[in] max_packet_size maximum size of data packet the device accepts
    283289 * @param[out] data Data destination.
    284290 * @param[in] size Size of data source.
     
    288294 */
    289295static int interrupt_in(
    290     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     296    ddf_fun_t *fun, usb_target_t target, void *data,
    291297    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    292298{
     
    309315 * @param[in] fun DDF function that was called.
    310316 * @param[in] target USB device to write to.
    311  * @param[in] max_packet_size maximum size of data packet the device accepts
    312317 * @param[in] data Source of data.
    313318 * @param[in] size Size of data source.
     
    317322 */
    318323static int bulk_out(
    319     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     324    ddf_fun_t *fun, usb_target_t target, void *data,
    320325    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    321326{
     
    338343 * @param[in] fun DDF function that was called.
    339344 * @param[in] target USB device to write to.
    340  * @param[in] max_packet_size maximum size of data packet the device accepts
    341345 * @param[out] data Data destination.
    342346 * @param[in] size Size of data source.
     
    346350 */
    347351static int bulk_in(
    348     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     352    ddf_fun_t *fun, usb_target_t target, void *data,
    349353    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    350354{
     
    367371 * @param[in] fun DDF function that was called.
    368372 * @param[in] target USB device to write to.
    369  * @param[in] max_packet_size maximum size of data packet the device accepts.
    370373 * @param[in] setup_data Data to send with SETUP transfer.
    371374 * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
     
    377380 */
    378381static int control_write(
    379     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     382    ddf_fun_t *fun, usb_target_t target,
    380383    void *setup_data, size_t setup_size, void *data, size_t size,
    381384    usbhc_iface_transfer_out_callback_t callback, void *arg)
     
    401404 * @param[in] fun DDF function that was called.
    402405 * @param[in] target USB device to write to.
    403  * @param[in] max_packet_size maximum size of data packet the device accepts.
    404406 * @param[in] setup_data Data to send with SETUP packet.
    405407 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
     
    411413 */
    412414static int control_read(
    413     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     415    ddf_fun_t *fun, usb_target_t target,
    414416    void *setup_data, size_t setup_size, void *data, size_t size,
    415417    usbhc_iface_transfer_in_callback_t callback, void *arg)
  • uspace/drv/usbmid/main.c

    rf35b294 ra43f1d18  
    5555        int rc;
    5656
    57         rc = usb_pipe_start_session(&dev->ctrl_pipe);
     57        rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
    5858        if (rc != EOK) {
    59                 usb_log_error("Failed to start session on control pipe: %s.\n",
     59                usb_log_error("Failed to start transfer on control pipe: %s.\n",
    6060                    str_error(rc));
    6161                return rc;
     
    6464        bool accept = usbmid_explore_device(dev);
    6565
    66         rc = usb_pipe_end_session(&dev->ctrl_pipe);
    67         if (rc != EOK) {
    68                 usb_log_warning("Failed to end session on control pipe: %s.\n",
    69                     str_error(rc));
    70         }
     66        usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    7167
    7268        if (!accept) {
  • uspace/drv/vhc/connhost.c

    rf35b294 ra43f1d18  
    257257
    258258static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
    259     size_t max_packet_size,
    260259    void *data, size_t size,
    261260    usbhc_iface_transfer_out_callback_t callback, void *arg)
     
    267266
    268267static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
    269     size_t max_packet_size,
    270268    void *data, size_t size,
    271269    usbhc_iface_transfer_in_callback_t callback, void *arg)
     
    277275
    278276static int control_write(ddf_fun_t *fun, usb_target_t target,
    279     size_t max_packet_size,
    280277    void *setup_packet, size_t setup_packet_size,
    281278    void *data, size_t data_size,
     
    295292
    296293static int control_read(ddf_fun_t *fun, usb_target_t target,
    297     size_t max_packet_size,
    298294    void *setup_packet, size_t setup_packet_size,
    299295    void *data, size_t data_size,
  • uspace/lib/drv/generic/remote_usbhc.c

    rf35b294 ra43f1d18  
    270270        }
    271271
    272         size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    273272        usb_target_t target = {
    274273                .address = DEV_IPC_GET_ARG1(*call),
     
    300299        trans->size = len;
    301300
    302         rc = transfer_func(fun, target, max_packet_size,
     301        rc = transfer_func(fun, target,
    303302            buffer, len,
    304303            callback_out, trans);
     
    326325        }
    327326
    328         size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    329327        usb_target_t target = {
    330328                .address = DEV_IPC_GET_ARG1(*call),
     
    348346        trans->size = len;
    349347
    350         int rc = transfer_func(fun, target, max_packet_size,
     348        int rc = transfer_func(fun, target,
    351349            trans->buffer, len,
    352350            callback_in, trans);
     
    414412        };
    415413        size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
    416         size_t max_packet_size = DEV_IPC_GET_ARG4(*call);
    417414
    418415        int rc;
     
    450447        trans->size = data_buffer_len;
    451448
    452         rc = usb_iface->control_write(fun, target, max_packet_size,
     449        rc = usb_iface->control_write(fun, target,
    453450            setup_packet, setup_packet_len,
    454451            data_buffer, data_buffer_len,
     
    477474                .endpoint = DEV_IPC_GET_ARG2(*call)
    478475        };
    479         size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    480476
    481477        int rc;
     
    515511        }
    516512
    517         rc = usb_iface->control_read(fun, target, max_packet_size,
     513        rc = usb_iface->control_read(fun, target,
    518514            setup_packet, setup_packet_len,
    519515            trans->buffer, trans->size,
     
    537533        }
    538534
    539 #define INIT_FROM_HIGH_DATA(type, var, arg_no) \
    540         type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256
    541 #define INIT_FROM_LOW_DATA(type, var, arg_no) \
    542         type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256
    543 
    544         INIT_FROM_HIGH_DATA(usb_address_t, address, 1);
    545         INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1);
    546         INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2);
    547         INIT_FROM_LOW_DATA(usb_direction_t, direction, 2);
    548 
    549 #undef INIT_FROM_HIGH_DATA
    550 #undef INIT_FROM_LOW_DATA
    551 
    552         size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call);
    553         unsigned int interval  = (unsigned int) DEV_IPC_GET_ARG4(*call);
    554 
    555         int rc = usb_iface->register_endpoint(fun, address, endpoint,
     535#define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \
     536        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)
     537#define _INIT_FROM_LOW_DATA2(type, var, arg_no) \
     538        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 16)
     539#define _INIT_FROM_HIGH_DATA3(type, var, arg_no) \
     540        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)
     541#define _INIT_FROM_MIDDLE_DATA3(type, var, arg_no) \
     542        type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) / (1 << 8)) % (1 << 8)
     543#define _INIT_FROM_LOW_DATA3(type, var, arg_no) \
     544        type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8)
     545
     546        _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1);
     547        _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1);
     548
     549        _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2);
     550        _INIT_FROM_MIDDLE_DATA3(usb_transfer_type_t, transfer_type, 2);
     551        _INIT_FROM_LOW_DATA3(usb_direction_t, direction, 2);
     552
     553        _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3);
     554        _INIT_FROM_LOW_DATA2(unsigned int, interval, 3);
     555
     556#undef _INIT_FROM_HIGH_DATA2
     557#undef _INIT_FROM_LOW_DATA2
     558#undef _INIT_FROM_HIGH_DATA3
     559#undef _INIT_FROM_MIDDLE_DATA3
     560#undef _INIT_FROM_LOW_DATA3
     561
     562        int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,
    556563            transfer_type, direction, max_packet_size, interval);
    557564
  • uspace/lib/drv/include/usbhc_iface.h

    rf35b294 ra43f1d18  
    6666 *   - argument #1 is target address
    6767 *   - argument #2 is target endpoint
    68  *   - argument #3 is max packet size of the endpoint
    6968 * - this call is immediately followed by IPC data read (async version)
    7069 * - the call is not answered until the device returns some data (or until
     
    169168        /** Register endpoint attributes at host controller.
    170169         * This is used to reserve portion of USB bandwidth.
     170         * When speed is invalid, speed of the device is used.
    171171         * Parameters:
    172          * - USB address + endpoint number (ADDR * 256 + EP)
    173          * - transfer type + direction (TYPE * 256 + DIR)
    174          * - maximum packet size
    175          * - interval (in milliseconds)
     172         * - USB address + endpoint number
     173         *   - packed as ADDR << 16 + EP
     174         * - speed + transfer type + direction
     175         *   - packed as ( SPEED << 8 + TYPE ) << 8 + DIR
     176         * - maximum packet size + interval (in milliseconds)
     177         *   - packed as MPS << 16 + INT
    176178         * Answer:
    177179         * - EOK - reservation successful
     
    202204
    203205/** Out transfer processing function prototype. */
    204 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, size_t,
     206typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t,
    205207    void *, size_t,
    206208    usbhc_iface_transfer_out_callback_t, void *);
     
    210212
    211213/** In transfer processing function prototype. */
    212 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, size_t,
     214typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t,
    213215    void *, size_t,
    214216    usbhc_iface_transfer_in_callback_t, void *);
     
    222224        int (*release_address)(ddf_fun_t *, usb_address_t);
    223225
    224         int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
     226        int (*register_endpoint)(ddf_fun_t *,
     227            usb_address_t, usb_speed_t, usb_endpoint_t,
    225228            usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
    226229        int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
     
    234237
    235238        int (*control_write)(ddf_fun_t *, usb_target_t,
    236             size_t,
    237239            void *, size_t, void *, size_t,
    238240            usbhc_iface_transfer_out_callback_t, void *);
    239241
    240242        int (*control_read)(ddf_fun_t *, usb_target_t,
    241             size_t,
    242243            void *, size_t, void *, size_t,
    243244            usbhc_iface_transfer_in_callback_t, void *);
  • uspace/lib/usb/Makefile

    rf35b294 ra43f1d18  
    4343        src/hidparser.c \
    4444        src/hub.c \
     45        src/pipepriv.c \
    4546        src/pipes.c \
    4647        src/pipesinit.c \
  • uspace/lib/usb/include/usb/devdrv.h

    rf35b294 ra43f1d18  
    169169    usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
    170170
     171int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
     172int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *,
     173    usb_endpoint_description_t **, uint8_t *, size_t, int, int,
     174    usb_endpoint_mapping_t **, size_t *);
     175int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
     176
     177size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t);
     178
    171179#endif
    172180/**
  • uspace/lib/usb/include/usb/host/device_keeper.h

    rf35b294 ra43f1d18  
    7373void usb_device_keeper_add_ep(
    7474    usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);
     75void usb_device_keeper_del_ep(
     76    usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);
    7577
    7678void usb_device_keeper_reserve_default_address(
  • uspace/lib/usb/include/usb/pipes.h

    rf35b294 ra43f1d18  
    4242#include <ipc/devman.h>
    4343#include <ddf/driver.h>
     44#include <fibril_synch.h>
    4445
    4546/** Abstraction of a physical connection to the device.
     
    5960 * This endpoint must be bound with existing usb_device_connection_t
    6061 * (i.e. the wire to send data over).
     62 *
     63 * Locking order: if you want to lock both mutexes
     64 * (@c guard and @c hc_phone_mutex), lock @c guard first.
     65 * It is not necessary to lock @c guard if you want to lock @c hc_phone_mutex
     66 * only.
    6167 */
    6268typedef struct {
     69        /** Guard of the whole pipe. */
     70        fibril_mutex_t guard;
     71
    6372        /** The connection used for sending the data. */
    6473        usb_device_connection_t *wire;
     
    7887        /** Phone to the host controller.
    7988         * Negative when no session is active.
     89         * It is an error to access this member without @c hc_phone_mutex
     90         * being locked.
     91         * If call over the phone is to be made, it must be preceeded by
     92         * call to pipe_add_ref() [internal libusb function].
    8093         */
    8194        int hc_phone;
     95
     96        /** Guard for serialization of requests over the phone. */
     97        fibril_mutex_t hc_phone_mutex;
     98
     99        /** Number of active transfers over the pipe. */
     100        int refcount;
    82101} usb_pipe_t;
    83102
     
    134153int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    135154    size_t, uint8_t *, size_t, usb_device_connection_t *);
     155int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t,
     156    unsigned int, usb_hc_connection_t *);
    136157int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);
    137158int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
     
    140161int usb_pipe_end_session(usb_pipe_t *);
    141162bool usb_pipe_is_session_started(usb_pipe_t *);
     163
     164int usb_pipe_start_long_transfer(usb_pipe_t *);
     165void usb_pipe_end_long_transfer(usb_pipe_t *);
    142166
    143167int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *);
  • uspace/lib/usb/include/usb/usb.h

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

    rf35b294 ra43f1d18  
    7272}
    7373
    74 /** Log out of memory error on given device.
    75  *
    76  * @param dev Device causing the trouble.
    77  */
    78 static void usb_log_oom(ddf_dev_t *dev)
    79 {
    80         usb_log_error("Out of memory when adding device `%s'.\n",
    81             dev->name);
    82 }
    83 
    8474/** Count number of pipes the driver expects.
    8575 *
     
    10898 */
    10999static int initialize_other_pipes(usb_endpoint_description_t **endpoints,
    110     usb_device_t *dev)
    111 {
    112         int rc;
    113 
    114         size_t pipe_count = count_other_pipes(endpoints);
    115         if (pipe_count == 0) {
    116                 return EOK;
    117         }
    118 
    119         dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
    120         if (dev->pipes == NULL) {
    121                 usb_log_oom(dev->ddf_dev);
    122                 return ENOMEM;
    123         }
    124 
    125         size_t i;
    126 
    127         /* Initialize to NULL first for rollback purposes. */
    128         for (i = 0; i < pipe_count; i++) {
    129                 dev->pipes[i].pipe = NULL;
    130         }
    131 
    132         for (i = 0; i < pipe_count; i++) {
    133                 dev->pipes[i].pipe = malloc(sizeof(usb_pipe_t));
    134                 if (dev->pipes[i].pipe == NULL) {
    135                         usb_log_oom(dev->ddf_dev);
    136                         rc = ENOMEM;
    137                         goto rollback;
    138                 }
    139 
    140                 dev->pipes[i].description = endpoints[i];
    141                 dev->pipes[i].interface_no = dev->interface_no;
    142                 dev->pipes[i].interface_setting = 0;
    143         }
    144 
    145         rc = usb_pipe_initialize_from_configuration(dev->pipes, pipe_count,
     100    usb_device_t *dev, int alternate_setting)
     101{
     102        usb_endpoint_mapping_t *pipes;
     103        size_t pipes_count;
     104
     105        int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints,
    146106            dev->descriptors.configuration, dev->descriptors.configuration_size,
    147             &dev->wire);
    148         if (rc != EOK) {
    149                 usb_log_error("Failed initializing USB endpoints: %s.\n",
    150                     str_error(rc));
    151                 goto rollback;
    152         }
    153 
    154         /* Register the endpoints. */
    155         usb_hc_connection_t hc_conn;
    156         rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev);
     107            dev->interface_no, alternate_setting,
     108            &pipes, &pipes_count);
     109
    157110        if (rc != EOK) {
    158111                usb_log_error(
    159                     "Failed initializing connection to host controller: %s.\n",
    160                     str_error(rc));
    161                 goto rollback;
    162         }
    163         rc = usb_hc_connection_open(&hc_conn);
    164         if (rc != EOK) {
    165                 usb_log_error("Failed to connect to host controller: %s.\n",
    166                     str_error(rc));
    167                 goto rollback;
    168         }
    169         for (i = 0; i < pipe_count; i++) {
    170                 if (dev->pipes[i].present) {
    171                         rc = usb_pipe_register(dev->pipes[i].pipe,
    172                             dev->pipes[i].descriptor->poll_interval,
    173                             &hc_conn);
    174                         /* Ignore error when operation not supported by HC. */
    175                         if ((rc != EOK) && (rc != ENOTSUP)) {
    176                                 /* FIXME: what shall we do? */
    177                                 dev->pipes[i].present = false;
    178                                 free(dev->pipes[i].pipe);
    179                                 dev->pipes[i].pipe = NULL;
    180                         }
    181                 }
    182         }
    183         /* Ignoring errors here. */
    184         usb_hc_connection_close(&hc_conn);
    185 
    186         dev->pipes_count = pipe_count;
     112                    "Failed to create endpoint pipes for `%s': %s.\n",
     113                    dev->ddf_dev->name, str_error(rc));
     114                return rc;
     115        }
     116
     117        dev->pipes = pipes;
     118        dev->pipes_count = pipes_count;
    187119
    188120        return EOK;
    189 
    190 rollback:
    191         for (i = 0; i < pipe_count; i++) {
    192                 if (dev->pipes[i].pipe != NULL) {
    193                         free(dev->pipes[i].pipe);
    194                 }
    195         }
    196         free(dev->pipes);
    197 
    198         return rc;
    199121}
    200122
     
    239161
    240162        /*
    241          * For further actions, we need open session on default control pipe.
     163         * We will do some querying of the device, it is worth to prepare
     164         * the long transfer.
    242165         */
    243         rc = usb_pipe_start_session(&dev->ctrl_pipe);
    244         if (rc != EOK) {
    245                 usb_log_error("Failed to start an IPC session: %s.\n",
     166        rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
     167        if (rc != EOK) {
     168                usb_log_error("Failed to start transfer: %s.\n",
    246169                    str_error(rc));
    247170                return rc;
    248171        }
    249172
    250         /* Get the device descriptor. */
    251         rc = usb_request_get_device_descriptor(&dev->ctrl_pipe,
    252             &dev->descriptors.device);
    253         if (rc != EOK) {
    254                 usb_log_error("Failed to retrieve device descriptor: %s.\n",
    255                     str_error(rc));
    256                 return rc;
    257         }
    258 
    259         /* Get the full configuration descriptor. */
    260         rc = usb_request_get_full_configuration_descriptor_alloc(
    261             &dev->ctrl_pipe, 0, (void **) &dev->descriptors.configuration,
    262             &dev->descriptors.configuration_size);
    263         if (rc != EOK) {
    264                 usb_log_error("Failed retrieving configuration descriptor: %s. %s\n",
     173        /* Retrieve the descriptors. */
     174        rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
     175            &dev->descriptors);
     176        if (rc != EOK) {
     177                usb_log_error("Failed to retrieve standard device " \
     178                    "descriptors of %s: %s.\n",
    265179                    dev->ddf_dev->name, str_error(rc));
    266180                return rc;
    267181        }
    268182
     183
    269184        if (driver->endpoints != NULL) {
    270                 rc = initialize_other_pipes(driver->endpoints, dev);
    271         }
    272 
    273         /* No checking here. */
    274         usb_pipe_end_session(&dev->ctrl_pipe);
     185                rc = initialize_other_pipes(driver->endpoints, dev, 0);
     186        }
     187
     188        usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    275189
    276190        /* Rollback actions. */
     
    291205 * @return Number of alternate interfaces for @p interface_no interface.
    292206 */
    293 static size_t count_alternate_interfaces(uint8_t *config_descr,
    294     size_t config_descr_size, int interface_no)
     207size_t usb_interface_count_alternates(uint8_t *config_descr,
     208    size_t config_descr_size, uint8_t interface_no)
    295209{
    296210        assert(config_descr != NULL);
     211        assert(config_descr_size > 0);
     212
    297213        usb_dp_parser_t dp_parser = {
    298214                .nesting = usb_dp_standard_descriptor_nesting
     
    343259
    344260        alternates->alternative_count
    345             = count_alternate_interfaces(dev->descriptors.configuration,
     261            = usb_interface_count_alternates(dev->descriptors.configuration,
    346262            dev->descriptors.configuration_size, dev->interface_no);
    347263
     
    457373static int destroy_current_pipes(usb_device_t *dev)
    458374{
    459         size_t i;
    460         int rc;
    461 
    462         /* TODO: this shall be done under some device mutex. */
    463 
    464         /* First check that no session is opened. */
    465         for (i = 0; i < dev->pipes_count; i++) {
    466                 if (usb_pipe_is_session_started(dev->pipes[i].pipe)) {
    467                         return EBUSY;
    468                 }
    469         }
    470 
    471         /* Prepare connection to HC. */
    472         usb_hc_connection_t hc_conn;
    473         rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev);
    474         if (rc != EOK) {
    475                 return rc;
    476         }
    477         rc = usb_hc_connection_open(&hc_conn);
    478         if (rc != EOK) {
    479                 return rc;
    480         }
    481 
    482         /* Destroy the pipes. */
    483         for (i = 0; i < dev->pipes_count; i++) {
    484                 usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn);
    485                 free(dev->pipes[i].pipe);
    486         }
    487 
    488         usb_hc_connection_close(&hc_conn);
    489 
    490         free(dev->pipes);
     375        int rc = usb_device_destroy_pipes(dev->ddf_dev,
     376            dev->pipes, dev->pipes_count);
     377        if (rc != EOK) {
     378                return rc;
     379        }
     380
    491381        dev->pipes = NULL;
    492382        dev->pipes_count = 0;
     
    535425
    536426        /* Create new pipes. */
    537         rc = initialize_other_pipes(endpoints, dev);
     427        rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting);
    538428
    539429        return rc;
     430}
     431
     432/** Retrieve basic descriptors from the device.
     433 *
     434 * @param[in] ctrl_pipe Control pipe with opened session.
     435 * @param[out] descriptors Where to store the descriptors.
     436 * @return Error code.
     437 */
     438int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe,
     439    usb_device_descriptors_t *descriptors)
     440{
     441        assert(descriptors != NULL);
     442        assert(usb_pipe_is_session_started(ctrl_pipe));
     443
     444        descriptors->configuration = NULL;
     445
     446        int rc;
     447
     448        /* Get the device descriptor. */
     449        rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);
     450        if (rc != EOK) {
     451                return rc;
     452        }
     453
     454        /* Get the full configuration descriptor. */
     455        rc = usb_request_get_full_configuration_descriptor_alloc(
     456            ctrl_pipe, 0, (void **) &descriptors->configuration,
     457            &descriptors->configuration_size);
     458        if (rc != EOK) {
     459                return rc;
     460        }
     461
     462        return EOK;
     463}
     464
     465/** Create pipes for a device.
     466 *
     467 * This is more or less a wrapper that does following actions:
     468 * - allocate and initialize pipes
     469 * - map endpoints to the pipes based on the descriptions
     470 * - registers endpoints with the host controller
     471 *
     472 * @param[in] dev Generic DDF device backing the USB one.
     473 * @param[in] wire Initialized backing connection to the host controller.
     474 * @param[in] endpoints Endpoints description, NULL terminated.
     475 * @param[in] config_descr Configuration descriptor of active configuration.
     476 * @param[in] config_descr_size Size of @p config_descr in bytes.
     477 * @param[in] interface_no Interface to map from.
     478 * @param[in] interface_setting Interface setting (default is usually 0).
     479 * @param[out] pipes_ptr Where to store array of created pipes
     480 *      (not NULL terminated).
     481 * @param[out] pipes_count_ptr Where to store number of pipes
     482 *      (set to if you wish to ignore the count).
     483 * @return Error code.
     484 */
     485int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire,
     486    usb_endpoint_description_t **endpoints,
     487    uint8_t *config_descr, size_t config_descr_size,
     488    int interface_no, int interface_setting,
     489    usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
     490{
     491        assert(dev != NULL);
     492        assert(wire != NULL);
     493        assert(endpoints != NULL);
     494        assert(config_descr != NULL);
     495        assert(config_descr_size > 0);
     496        assert(pipes_ptr != NULL);
     497
     498        size_t i;
     499        int rc;
     500
     501        size_t pipe_count = count_other_pipes(endpoints);
     502        if (pipe_count == 0) {
     503                *pipes_ptr = NULL;
     504                return EOK;
     505        }
     506
     507        usb_endpoint_mapping_t *pipes
     508            = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
     509        if (pipes == NULL) {
     510                return ENOMEM;
     511        }
     512
     513        /* Initialize to NULL to allow smooth rollback. */
     514        for (i = 0; i < pipe_count; i++) {
     515                pipes[i].pipe = NULL;
     516        }
     517
     518        /* Now allocate and fully initialize. */
     519        for (i = 0; i < pipe_count; i++) {
     520                pipes[i].pipe = malloc(sizeof(usb_pipe_t));
     521                if (pipes[i].pipe == NULL) {
     522                        rc = ENOMEM;
     523                        goto rollback_free_only;
     524                }
     525                pipes[i].description = endpoints[i];
     526                pipes[i].interface_no = interface_no;
     527                pipes[i].interface_setting = interface_setting;
     528        }
     529
     530        /* Find the mapping from configuration descriptor. */
     531        rc = usb_pipe_initialize_from_configuration(pipes, pipe_count,
     532            config_descr, config_descr_size, wire);
     533        if (rc != EOK) {
     534                goto rollback_free_only;
     535        }
     536
     537        /* Register the endpoints with HC. */
     538        usb_hc_connection_t hc_conn;
     539        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     540        if (rc != EOK) {
     541                goto rollback_free_only;
     542        }
     543
     544        rc = usb_hc_connection_open(&hc_conn);
     545        if (rc != EOK) {
     546                goto rollback_free_only;
     547        }
     548
     549        for (i = 0; i < pipe_count; i++) {
     550                if (pipes[i].present) {
     551                        rc = usb_pipe_register(pipes[i].pipe,
     552                            pipes[i].descriptor->poll_interval, &hc_conn);
     553                        if (rc != EOK) {
     554                                goto rollback_unregister_endpoints;
     555                        }
     556                }
     557        }
     558
     559        usb_hc_connection_close(&hc_conn);
     560
     561        *pipes_ptr = pipes;
     562        if (pipes_count_ptr != NULL) {
     563                *pipes_count_ptr = pipe_count;
     564        }
     565
     566        return EOK;
     567
     568        /*
     569         * Jump here if something went wrong after endpoints have
     570         * been registered.
     571         * This is also the target when the registration of
     572         * endpoints fails.
     573         */
     574rollback_unregister_endpoints:
     575        for (i = 0; i < pipe_count; i++) {
     576                if (pipes[i].present) {
     577                        usb_pipe_unregister(pipes[i].pipe, &hc_conn);
     578                }
     579        }
     580
     581        usb_hc_connection_close(&hc_conn);
     582
     583        /*
     584         * Jump here if something went wrong before some actual communication
     585         * with HC. Then the only thing that needs to be done is to free
     586         * allocated memory.
     587         */
     588rollback_free_only:
     589        for (i = 0; i < pipe_count; i++) {
     590                if (pipes[i].pipe != NULL) {
     591                        free(pipes[i].pipe);
     592                }
     593        }
     594        free(pipes);
     595
     596        return rc;
     597}
     598
     599/** Destroy pipes previously created by usb_device_create_pipes.
     600 *
     601 * @param[in] dev Generic DDF device backing the USB one.
     602 * @param[in] pipes Endpoint mapping to be destroyed.
     603 * @param[in] pipes_count Number of endpoints.
     604 */
     605int usb_device_destroy_pipes(ddf_dev_t *dev,
     606    usb_endpoint_mapping_t *pipes, size_t pipes_count)
     607{
     608        assert(dev != NULL);
     609        assert(((pipes != NULL) && (pipes_count > 0))
     610            || ((pipes == NULL) && (pipes_count == 0)));
     611
     612        if (pipes_count == 0) {
     613                return EOK;
     614        }
     615
     616        int rc;
     617
     618        /* Prepare connection to HC to allow endpoint unregistering. */
     619        usb_hc_connection_t hc_conn;
     620        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     621        if (rc != EOK) {
     622                return rc;
     623        }
     624        rc = usb_hc_connection_open(&hc_conn);
     625        if (rc != EOK) {
     626                return rc;
     627        }
     628
     629        /* Destroy the pipes. */
     630        size_t i;
     631        for (i = 0; i < pipes_count; i++) {
     632                usb_pipe_unregister(pipes[i].pipe, &hc_conn);
     633                free(pipes[i].pipe);
     634        }
     635
     636        usb_hc_connection_close(&hc_conn);
     637
     638        free(pipes);
     639
     640        return EOK;
    540641}
    541642
  • uspace/lib/usb/src/devpoll.c

    rf35b294 ra43f1d18  
    7777                int rc;
    7878
    79                 rc = usb_pipe_start_session(pipe);
    80                 if (rc != EOK) {
    81                         failed_attempts++;
    82                         continue;
    83                 }
    84 
    8579                size_t actual_size;
    8680                rc = usb_pipe_read(pipe, polling_data->buffer,
    8781                    polling_data->request_size, &actual_size);
    8882
    89                 /* Quit the session regardless of errors. */
    90                 usb_pipe_end_session(pipe);
    9183               
    9284//              if (rc == ESTALL) {
  • uspace/lib/usb/src/host/batch.c

    rf35b294 ra43f1d18  
    6363        instance->transfer_type = transfer_type;
    6464        instance->speed = speed;
    65         instance->direction = USB_DIRECTION_BOTH;
     65        instance->direction = ep->direction;
    6666        instance->callback_in = func_in;
    6767        instance->callback_out = func_out;
  • uspace/lib/usb/src/host/device_keeper.c

    rf35b294 ra43f1d18  
    5656                instance->devices[i].control_used = 0;
    5757                instance->devices[i].handle = 0;
     58                instance->devices[i].speed = USB_SPEED_MAX;
    5859                list_initialize(&instance->devices[i].endpoints);
    5960        }
     61        // TODO: is this hack enough?
     62        // (it is needed to allow smooth registration at default address)
     63        instance->devices[0].occupied = true;
    6064}
    6165/*----------------------------------------------------------------------------*/
     
    6771        assert(instance->devices[address].occupied);
    6872        list_append(&ep->same_device_eps, &instance->devices[address].endpoints);
     73        fibril_mutex_unlock(&instance->guard);
     74}
     75/*----------------------------------------------------------------------------*/
     76void usb_device_keeper_del_ep(
     77    usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep)
     78{
     79        assert(instance);
     80        fibril_mutex_lock(&instance->guard);
     81        assert(instance->devices[address].occupied);
     82        list_remove(&ep->same_device_eps);
     83        list_initialize(&ep->same_device_eps);
    6984        fibril_mutex_unlock(&instance->guard);
    7085}
  • uspace/lib/usb/src/hub.c

    rf35b294 ra43f1d18  
    4040#include <errno.h>
    4141#include <assert.h>
     42#include <usb/debug.h>
    4243
    4344/** Check that HC connection is alright.
     
    5556
    5657/** Tell host controller to reserve default address.
     58 * @deprecated
    5759 *
    5860 * @param connection Opened connection to host controller.
     
    6567        CHECK_CONNECTION(connection);
    6668
     69        usb_log_warning("usb_hc_reserve_default_address() considered obsolete");
     70
    6771        return async_req_2_0(connection->hc_phone,
    6872            DEV_IFACE_ID(USBHC_DEV_IFACE),
     
    7175
    7276/** Tell host controller to release default address.
     77 * @deprecated
    7378 *
    7479 * @param connection Opened connection to host controller.
     
    7883{
    7984        CHECK_CONNECTION(connection);
     85
     86        usb_log_warning("usb_hc_release_default_address() considered obsolete");
    8087
    8188        return async_req_1_0(connection->hc_phone,
     
    235242        }
    236243
    237 
    238         /*
    239          * Reserve the default address.
    240          */
    241         rc = usb_hc_reserve_default_address(&hc_conn, dev_speed);
    242         if (rc != EOK) {
    243                 rc = EBUSY;
    244                 goto leave_release_free_address;
    245         }
    246 
    247         /*
    248          * Enable the port (i.e. allow signaling through this port).
    249          */
    250         rc = enable_port(port_no, arg);
    251         if (rc != EOK) {
    252                 goto leave_release_default_address;
    253         }
    254 
    255         /*
    256          * Change the address from default to the free one.
    257          * We need to create a new control pipe for that.
     244        /*
     245         * We will not register control pipe on default address.
     246         * The registration might fail. That means that someone else already
     247         * registered that endpoint. We will simply wait and try again.
     248         * (Someone else already wants to add a new device.)
    258249         */
    259250        usb_device_connection_t dev_conn;
     
    262253        if (rc != EOK) {
    263254                rc = ENOTCONN;
    264                 goto leave_release_default_address;
     255                goto leave_release_free_address;
    265256        }
    266257
     
    270261        if (rc != EOK) {
    271262                rc = ENOTCONN;
     263                goto leave_release_free_address;
     264        }
     265
     266        do {
     267                rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0,
     268                    &hc_conn);
     269                if (rc != EOK) {
     270                        /* Do not overheat the CPU ;-). */
     271                        async_usleep(10);
     272                }
     273        } while (rc != EOK);
     274
     275        /*
     276         * Endpoint is registered. We can enable the port and change
     277         * device address.
     278         */
     279        rc = enable_port(port_no, arg);
     280        if (rc != EOK) {
    272281                goto leave_release_default_address;
    273282        }
    274283
    275         /* Before sending any traffic, we need to register this
    276          * endpoint.
     284        rc = usb_pipe_probe_default_control(&ctrl_pipe);
     285        if (rc != EOK) {
     286                rc = ESTALL;
     287                goto leave_release_default_address;
     288        }
     289
     290        rc = usb_request_set_address(&ctrl_pipe, dev_addr);
     291        if (rc != EOK) {
     292                rc = ESTALL;
     293                goto leave_release_default_address;
     294        }
     295
     296        /*
     297         * Address changed. We can release the original endpoint, thus
     298         * allowing other to access the default address.
     299         */
     300        unregister_control_endpoint_on_default_address(&hc_conn);
     301
     302        /*
     303         * Time to register the new endpoint.
    277304         */
    278305        rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
    279306        if (rc != EOK) {
    280                 rc = EREFUSED;
    281                 goto leave_release_default_address;
    282         }
    283         rc = usb_pipe_probe_default_control(&ctrl_pipe);
    284         if (rc != EOK) {
    285                 rc = ENOTCONN;
    286                 goto leave_release_default_address;
    287         }
    288 
    289         rc = usb_pipe_start_session(&ctrl_pipe);
    290         if (rc != EOK) {
    291                 rc = ENOTCONN;
    292                 goto leave_unregister_endpoint;
    293         }
    294 
    295         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
    296         if (rc != EOK) {
    297                 rc = ESTALL;
    298                 goto leave_stop_session;
    299         }
    300 
    301         usb_pipe_end_session(&ctrl_pipe);
    302 
    303         /*
    304          * Register the control endpoint for the new device.
    305          */
    306         rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
    307         if (rc != EOK) {
    308                 rc = EREFUSED;
    309                 goto leave_unregister_endpoint;
    310         }
    311 
    312         /*
    313          * Release the original endpoint.
    314          */
    315         unregister_control_endpoint_on_default_address(&hc_conn);
    316 
    317         /*
    318          * Once the address is changed, we can return the default address.
    319          */
    320         usb_hc_release_default_address(&hc_conn);
    321 
     307                goto leave_release_free_address;
     308        }
    322309
    323310        /*
     
    334321        }
    335322
    336 
    337 
    338323        /*
    339324         * And now inform the host controller about the handle.
     
    367352         * Completely ignoring errors here.
    368353         */
    369 
    370 leave_stop_session:
    371         usb_pipe_end_session(&ctrl_pipe);
    372 
    373 leave_unregister_endpoint:
     354leave_release_default_address:
    374355        usb_pipe_unregister(&ctrl_pipe, &hc_conn);
    375 
    376 leave_release_default_address:
    377         usb_hc_release_default_address(&hc_conn);
    378356
    379357leave_release_free_address:
  • uspace/lib/usb/src/pipes.c

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

    rf35b294 ra43f1d18  
    356356        assert(connection);
    357357
     358        fibril_mutex_initialize(&pipe->guard);
    358359        pipe->wire = connection;
    359360        pipe->hc_phone = -1;
     361        fibril_mutex_initialize(&pipe->hc_phone_mutex);
    360362        pipe->endpoint_no = endpoint_no;
    361363        pipe->transfer_type = transfer_type;
    362364        pipe->max_packet_size = max_packet_size;
    363365        pipe->direction = direction;
     366        pipe->refcount = 0;
    364367
    365368        return EOK;
     
    413416        int rc;
    414417
    415         TRY_LOOP(failed_attempts) {
    416                 rc = usb_pipe_start_session(pipe);
    417                 if (rc == EOK) {
    418                         break;
    419                 }
    420         }
     418        rc = usb_pipe_start_long_transfer(pipe);
    421419        if (rc != EOK) {
    422420                return rc;
     
    439437                }
    440438        }
    441         usb_pipe_end_session(pipe);
     439        usb_pipe_end_long_transfer(pipe);
    442440        if (rc != EOK) {
    443441                return rc;
     
    461459    usb_hc_connection_t *hc_connection)
    462460{
     461        return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1,
     462            interval, hc_connection);
     463}
     464
     465/** Register endpoint with a speed at the host controller.
     466 *
     467 * You will rarely need to use this function because it is needed only
     468 * if the registered endpoint is of address 0 and there is no other way
     469 * to tell speed of the device at address 0.
     470 *
     471 * @param pipe Pipe to be registered.
     472 * @param speed Speed of the device
     473 *      (invalid speed means use previously specified one).
     474 * @param interval Polling interval.
     475 * @param hc_connection Connection to the host controller (must be opened).
     476 * @return Error code.
     477 */
     478int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed,
     479    unsigned int interval,
     480    usb_hc_connection_t *hc_connection)
     481{
    463482        assert(pipe);
    464483        assert(hc_connection);
     
    468487        }
    469488
    470 #define _PACK(high, low) ((high) * 256 + (low))
    471 
    472         return async_req_5_0(hc_connection->hc_phone,
     489#define _PACK2(high, low) (((high) << 16) + (low))
     490#define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
     491
     492        return async_req_4_0(hc_connection->hc_phone,
    473493            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,
    474             _PACK(pipe->wire->address, pipe->endpoint_no),
    475             _PACK(pipe->transfer_type, pipe->direction),
    476             pipe->max_packet_size, interval);
    477 
    478 #undef _PACK
     494            _PACK2(pipe->wire->address, pipe->endpoint_no),
     495            _PACK3(speed, pipe->transfer_type, pipe->direction),
     496            _PACK2(pipe->max_packet_size, interval));
     497
     498#undef _PACK2
     499#undef _PACK3
    479500}
    480501
  • uspace/lib/usb/src/pipesio.c

    rf35b294 ra43f1d18  
    4949#include <assert.h>
    5050#include <usbhc_iface.h>
     51#include "pipepriv.h"
    5152
    5253/** Request an in transfer, no checking of input parameters.
     
    7879        }
    7980
     81        /* Ensure serialization over the phone. */
     82        pipe_start_transaction(pipe);
     83
    8084        /*
    8185         * Make call identifying target USB device and type of transfer.
    8286         */
    83         aid_t opening_request = async_send_4(pipe->hc_phone,
     87        aid_t opening_request = async_send_3(pipe->hc_phone,
    8488            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    8589            pipe->wire->address, pipe->endpoint_no,
    86             pipe->max_packet_size,
    8790            NULL);
    8891        if (opening_request == 0) {
     92                pipe_end_transaction(pipe);
    8993                return ENOMEM;
    9094        }
     
    96100        aid_t data_request = async_data_read(pipe->hc_phone, buffer, size,
    97101            &data_request_call);
     102
     103        /*
     104         * Since now on, someone else might access the backing phone
     105         * without breaking the transfer IPC protocol.
     106         */
     107        pipe_end_transaction(pipe);
    98108
    99109        if (data_request == 0) {
     
    146156
    147157        if (buffer == NULL) {
    148                         return EINVAL;
     158                return EINVAL;
    149159        }
    150160
    151161        if (size == 0) {
    152162                return EINVAL;
    153         }
    154 
    155         if (!usb_pipe_is_session_started(pipe)) {
    156                 return EBADF;
    157163        }
    158164
     
    165171        }
    166172
     173        int rc;
     174        rc = pipe_add_ref(pipe);
     175        if (rc != EOK) {
     176                return rc;
     177        }
     178
     179
    167180        size_t act_size = 0;
    168         int rc;
    169181
    170182        rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);
     183
     184        pipe_drop_ref(pipe);
     185
    171186        if (rc != EOK) {
    172187                return rc;
     
    210225        }
    211226
     227        /* Ensure serialization over the phone. */
     228        pipe_start_transaction(pipe);
     229
    212230        /*
    213231         * Make call identifying target USB device and type of transfer.
    214232         */
    215         aid_t opening_request = async_send_4(pipe->hc_phone,
     233        aid_t opening_request = async_send_3(pipe->hc_phone,
    216234            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    217235            pipe->wire->address, pipe->endpoint_no,
    218             pipe->max_packet_size,
    219236            NULL);
    220237        if (opening_request == 0) {
     238                pipe_end_transaction(pipe);
    221239                return ENOMEM;
    222240        }
     
    226244         */
    227245        int rc = async_data_write_start(pipe->hc_phone, buffer, size);
     246
     247        /*
     248         * Since now on, someone else might access the backing phone
     249         * without breaking the transfer IPC protocol.
     250         */
     251        pipe_end_transaction(pipe);
     252
    228253        if (rc != EOK) {
    229254                async_wait_for(opening_request, NULL);
     
    260285        }
    261286
    262         if (!usb_pipe_is_session_started(pipe)) {
    263                 return EBADF;
    264         }
    265 
    266287        if (pipe->direction != USB_DIRECTION_OUT) {
    267288                return EBADF;
     
    272293        }
    273294
    274         int rc = usb_pipe_write_no_check(pipe, buffer, size);
     295        int rc;
     296
     297        rc = pipe_add_ref(pipe);
     298        if (rc != EOK) {
     299                return rc;
     300        }
     301
     302        rc = usb_pipe_write_no_check(pipe, buffer, size);
     303
     304        pipe_drop_ref(pipe);
    275305
    276306        return rc;
     
    293323    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
    294324{
     325        /* Ensure serialization over the phone. */
     326        pipe_start_transaction(pipe);
     327
    295328        /*
    296329         * Make call identifying target USB device and control transfer type.
    297330         */
    298         aid_t opening_request = async_send_4(pipe->hc_phone,
     331        aid_t opening_request = async_send_3(pipe->hc_phone,
    299332            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
    300333            pipe->wire->address, pipe->endpoint_no,
    301             pipe->max_packet_size,
    302334            NULL);
    303335        if (opening_request == 0) {
     
    311343            setup_buffer, setup_buffer_size);
    312344        if (rc != EOK) {
     345                pipe_end_transaction(pipe);
    313346                async_wait_for(opening_request, NULL);
    314347                return rc;
     
    322355            data_buffer, data_buffer_size,
    323356            &data_request_call);
     357
     358        /*
     359         * Since now on, someone else might access the backing phone
     360         * without breaking the transfer IPC protocol.
     361         */
     362        pipe_end_transaction(pipe);
     363
     364
    324365        if (data_request == 0) {
    325366                async_wait_for(opening_request, NULL);
     
    379420        }
    380421
    381         if (!usb_pipe_is_session_started(pipe)) {
    382                 return EBADF;
    383         }
    384 
    385422        if ((pipe->direction != USB_DIRECTION_BOTH)
    386423            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    388425        }
    389426
     427        int rc;
     428
     429        rc = pipe_add_ref(pipe);
     430        if (rc != EOK) {
     431                return rc;
     432        }
     433
    390434        size_t act_size = 0;
    391         int rc = usb_pipe_control_read_no_check(pipe,
     435        rc = usb_pipe_control_read_no_check(pipe,
    392436            setup_buffer, setup_buffer_size,
    393437            data_buffer, data_buffer_size, &act_size);
     438
     439        pipe_drop_ref(pipe);
    394440
    395441        if (rc != EOK) {
     
    418464    void *data_buffer, size_t data_buffer_size)
    419465{
     466        /* Ensure serialization over the phone. */
     467        pipe_start_transaction(pipe);
     468
    420469        /*
    421470         * Make call identifying target USB device and control transfer type.
    422471         */
    423         aid_t opening_request = async_send_5(pipe->hc_phone,
     472        aid_t opening_request = async_send_4(pipe->hc_phone,
    424473            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
    425474            pipe->wire->address, pipe->endpoint_no,
    426475            data_buffer_size,
    427             pipe->max_packet_size,
    428476            NULL);
    429477        if (opening_request == 0) {
     478                pipe_end_transaction(pipe);
    430479                return ENOMEM;
    431480        }
     
    437486            setup_buffer, setup_buffer_size);
    438487        if (rc != EOK) {
     488                pipe_end_transaction(pipe);
    439489                async_wait_for(opening_request, NULL);
    440490                return rc;
     
    447497                rc = async_data_write_start(pipe->hc_phone,
    448498                    data_buffer, data_buffer_size);
     499
     500                /* All data sent, pipe can be released. */
     501                pipe_end_transaction(pipe);
     502
    449503                if (rc != EOK) {
    450504                        async_wait_for(opening_request, NULL);
    451505                        return rc;
    452506                }
     507        } else {
     508                /* No data to send, we can release the pipe for others. */
     509                pipe_end_transaction(pipe);
    453510        }
    454511
     
    491548        }
    492549
    493         if (!usb_pipe_is_session_started(pipe)) {
    494                 return EBADF;
    495         }
    496 
    497550        if ((pipe->direction != USB_DIRECTION_BOTH)
    498551            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    500553        }
    501554
    502         int rc = usb_pipe_control_write_no_check(pipe,
     555        int rc;
     556
     557        rc = pipe_add_ref(pipe);
     558        if (rc != EOK) {
     559                return rc;
     560        }
     561
     562        rc = usb_pipe_control_write_no_check(pipe,
    503563            setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
     564
     565        pipe_drop_ref(pipe);
    504566
    505567        return rc;
  • uspace/lib/usb/src/recognise.c

    rf35b294 ra43f1d18  
    404404        child->driver_data = dev_data;
    405405
    406         rc = usb_pipe_start_session(&ctrl_pipe);
    407         if (rc != EOK) {
    408                 goto failure;
    409         }
    410 
    411406        rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
    412         if (rc != EOK) {
    413                 goto failure;
    414         }
    415 
    416         rc = usb_pipe_end_session(&ctrl_pipe);
    417407        if (rc != EOK) {
    418408                goto failure;
Note: See TracChangeset for help on using the changeset viewer.