Changeset dc4c19e in mainline


Ignore:
Timestamp:
2011-04-10T12:18:09Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
60c0573
Parents:
a49e171 (diff), 82e8861 (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:

Development changes

Location:
uspace
Files:
6 added
54 edited

Legend:

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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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(%p): %x:%x:%x:%x.\n", data->ed,
     230            data->ed->status, data->ed->td_tail, data->ed->td_head,
     231            data->ed->next);
     232        int toggle = 0;
     233        /* setup stage */
     234        td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     235                instance->setup_size, toggle);
     236        td_set_next(&data->tds[0], &data->tds[1]);
     237        usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0].status,
     238            data->tds[0].cbp, data->tds[0].next, data->tds[0].be);
     239
     240        /* data stage */
     241        size_t td_current = 1;
     242        size_t remain_size = instance->buffer_size;
     243        char *transfer_buffer = instance->transport_buffer;
     244        while (remain_size > 0) {
     245                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     246                    OHCI_TD_MAX_TRANSFER : remain_size;
     247                toggle = 1 - toggle;
     248
     249                td_init(&data->tds[td_current], data_dir, transfer_buffer,
     250                    transfer_size, toggle);
     251                td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
     252                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     253                    data->tds[td_current].status, data->tds[td_current].cbp,
     254                    data->tds[td_current].next, data->tds[td_current].be);
     255
     256                transfer_buffer += transfer_size;
     257                remain_size -= transfer_size;
     258                assert(td_current < data->td_count - 2);
     259                ++td_current;
     260        }
     261
     262        /* status stage */
     263        assert(td_current == data->td_count - 2);
     264        td_init(&data->tds[td_current], status_dir, NULL, 0, 1);
     265        usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
     266            data->tds[td_current].status, data->tds[td_current].cbp,
     267            data->tds[td_current].next, data->tds[td_current].be);
     268}
     269/*----------------------------------------------------------------------------*/
    162270/** Helper function calls callback and correctly disposes of batch structure.
    163271 *
  • uspace/drv/ohci/batch.h

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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        }
     
    97108            ret, str_error(ret));
    98109
     110        hc_gain_control(instance);
     111        ret = hc_init_memory(instance);
     112        CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures:%s.\n",
     113            ret, str_error(ret));
     114        hc_init_hw(instance);
     115
     116        rh_init(&instance->rh, dev, instance->registers);
     117
    99118        if (!interrupts) {
    100119                instance->interrupt_emulator =
     
    103122        }
    104123
    105         hc_gain_control(instance);
    106 
    107         rh_init(&instance->rh, dev, instance->registers);
    108 
    109         hc_init_hw(instance);
    110 
    111         /* TODO: implement */
    112124        return EOK;
    113125}
     
    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->control &= ~C_CLE;
     143                instance->registers->command_status |= CS_CLF;
     144                usb_log_debug2("Set control transfer filled: %x.\n",
     145                        instance->registers->command_status);
     146                instance->registers->control |= C_CLE;
     147                break;
     148        case USB_TRANSFER_BULK:
     149                instance->registers->command_status |= CS_BLF;
     150                usb_log_debug2("Set bulk transfer filled: %x.\n",
     151                        instance->registers->command_status);
     152                break;
     153        default:
     154                break;
     155        }
     156        return EOK;
    124157}
    125158/*----------------------------------------------------------------------------*/
     
    127160{
    128161        assert(instance);
    129         if (status == 0)
     162        if ((status & ~IS_SF) == 0) /* ignore sof status */
    130163                return;
    131164        if (status & IS_RHSC)
     
    134167        usb_log_info("OHCI interrupt: %x.\n", status);
    135168
    136         /* TODO: Check for further interrupt causes */
    137         /* TODO: implement */
     169
     170        LIST_INITIALIZE(done);
     171        transfer_list_remove_finished(&instance->transfers_interrupt, &done);
     172        transfer_list_remove_finished(&instance->transfers_isochronous, &done);
     173        transfer_list_remove_finished(&instance->transfers_control, &done);
     174        transfer_list_remove_finished(&instance->transfers_bulk, &done);
     175
     176        while (!list_empty(&done)) {
     177                link_t *item = done.next;
     178                list_remove(item);
     179                usb_transfer_batch_t *batch =
     180                    list_get_instance(item, usb_transfer_batch_t, link);
     181                usb_transfer_batch_finish(batch);
     182        }
    138183}
    139184/*----------------------------------------------------------------------------*/
     
    154199{
    155200        assert(instance);
     201        /* Turn off legacy emulation */
     202        volatile uint32_t *ohci_emulation_reg =
     203            (uint32_t*)((char*)instance->registers + 0x100);
     204        usb_log_debug("OHCI legacy register %p: %x.\n",
     205                ohci_emulation_reg, *ohci_emulation_reg);
     206        *ohci_emulation_reg = 0;
     207
    156208        /* Interrupt routing enabled => smm driver is active */
    157209        if (instance->registers->control & C_IR) {
    158                 usb_log_info("Found SMM driver requesting ownership change.\n");
     210                usb_log_debug("SMM driver: request ownership change.\n");
    159211                instance->registers->command_status |= CS_OCR;
    160212                while (instance->registers->control & C_IR) {
    161213                        async_usleep(1000);
    162214                }
    163                 usb_log_info("Ownership taken from SMM driver.\n");
     215                usb_log_info("SMM driver: Ownership taken.\n");
    164216                return;
    165217        }
     
    169221        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    170222        if (hc_status != C_HCFS_RESET) {
    171                 usb_log_info("Found BIOS driver.\n");
     223                usb_log_debug("BIOS driver found.\n");
    172224                if (hc_status == C_HCFS_OPERATIONAL) {
    173                         usb_log_info("HC operational(BIOS).\n");
     225                        usb_log_info("BIOS driver: HC operational.\n");
    174226                        return;
    175227                }
     
    177229                instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
    178230                async_usleep(20000);
     231                usb_log_info("BIOS driver: HC resumed.\n");
    179232                return;
    180233        }
     
    182235        /* HC is in reset (hw startup) => no other driver
    183236         * maintain reset for at least the time specified in USB spec (50 ms)*/
     237        usb_log_info("HC found in reset.\n");
    184238        async_usleep(50000);
    185 
    186         /* turn off legacy emulation */
    187         volatile uint32_t *ohci_emulation_reg =
    188             (uint32_t*)((char*)instance->registers + 0x100);
    189         usb_log_info("OHCI legacy register status %p: %x.\n",
    190                 ohci_emulation_reg, *ohci_emulation_reg);
    191         *ohci_emulation_reg = 0;
    192 
    193239}
    194240/*----------------------------------------------------------------------------*/
    195241void hc_init_hw(hc_t *instance)
    196242{
    197         assert(instance);
     243        /* OHCI guide page 42 */
     244        assert(instance);
     245        usb_log_debug2("Started hc initialization routine.\n");
     246
     247        /* Save contents of fm_interval register */
    198248        const uint32_t fm_interval = instance->registers->fm_interval;
     249        usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
     250
     251        /* Reset hc */
     252        usb_log_debug2("HC reset.\n");
     253        size_t time = 0;
    199254        instance->registers->command_status = CS_HCR;
    200         async_usleep(10);
     255        while (instance->registers->command_status & CS_HCR) {
     256                async_usleep(10);
     257                time += 10;
     258        }
     259        usb_log_debug2("HC reset complete in %zu us.\n", time);
     260
     261        /* Restore fm_interval */
    201262        instance->registers->fm_interval = fm_interval;
    202263        assert((instance->registers->command_status & CS_HCR) == 0);
     264
    203265        /* hc is now in suspend state */
    204         /* TODO: init HCCA block */
    205         /* TODO: init queues */
    206         /* TODO: enable queues */
    207         /* TODO: enable interrupts */
    208         /* TODO: set periodic start to 90% */
     266        usb_log_debug2("HC should be in suspend state(%x).\n",
     267            instance->registers->control);
     268
     269        /* Enable queues */
     270        instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
     271        usb_log_debug2("All queues enabled(%x).\n",
     272            instance->registers->control);
     273
     274        /* Disable interrupts */
     275        instance->registers->interrupt_disable = I_SF | I_OC;
     276        usb_log_debug2("Disabling interrupts: %x.\n",
     277            instance->registers->interrupt_disable);
     278        instance->registers->interrupt_disable = I_MI;
     279        usb_log_debug2("Enabled interrupts: %x.\n",
     280            instance->registers->interrupt_enable);
     281
     282        /* Set periodic start to 90% */
     283        uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
     284        instance->registers->periodic_start = (frame_length / 10) * 9;
     285        usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
     286            instance->registers->periodic_start,
     287            instance->registers->periodic_start, frame_length);
    209288
    210289        instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
    211         usb_log_info("OHCI HC up and running.\n");
     290        usb_log_info("OHCI HC up and running(%x).\n",
     291            instance->registers->control);
     292}
     293/*----------------------------------------------------------------------------*/
     294int hc_init_transfer_lists(hc_t *instance)
     295{
     296        assert(instance);
     297
     298#define SETUP_TRANSFER_LIST(type, name) \
     299do { \
     300        int ret = transfer_list_init(&instance->type, name); \
     301        if (ret != EOK) { \
     302                usb_log_error("Failed(%d) to setup %s transfer list.\n", \
     303                    ret, name); \
     304                transfer_list_fini(&instance->transfers_isochronous); \
     305                transfer_list_fini(&instance->transfers_interrupt); \
     306                transfer_list_fini(&instance->transfers_control); \
     307                transfer_list_fini(&instance->transfers_bulk); \
     308        } \
     309} while (0)
     310
     311        SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS");
     312        SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT");
     313        SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
     314        SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
     315
     316        transfer_list_set_next(&instance->transfers_interrupt,
     317            &instance->transfers_isochronous);
     318
     319        /* Assign pointers to be used during scheduling */
     320        instance->transfers[USB_TRANSFER_INTERRUPT] =
     321          &instance->transfers_interrupt;
     322        instance->transfers[USB_TRANSFER_ISOCHRONOUS] =
     323          &instance->transfers_interrupt;
     324        instance->transfers[USB_TRANSFER_CONTROL] =
     325          &instance->transfers_control;
     326        instance->transfers[USB_TRANSFER_BULK] =
     327          &instance->transfers_bulk;
     328
     329        return EOK;
     330#undef CHECK_RET_CLEAR_RETURN
     331}
     332/*----------------------------------------------------------------------------*/
     333int hc_init_memory(hc_t *instance)
     334{
     335        assert(instance);
     336        /* Init queues */
     337        hc_init_transfer_lists(instance);
     338
     339        /*Init HCCA */
     340        instance->hcca = malloc32(sizeof(hcca_t));
     341        if (instance->hcca == NULL)
     342                return ENOMEM;
     343        bzero(instance->hcca, sizeof(hcca_t));
     344        instance->registers->hcca = addr_to_phys(instance->hcca);
     345        usb_log_debug2("OHCI HCCA initialized at %p(%p).\n",
     346            instance->hcca, instance->registers->hcca);
     347
     348        /* Use queues */
     349        instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
     350        usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
     351            instance->transfers_bulk.list_head,
     352            instance->transfers_bulk.list_head_pa);
     353
     354        instance->registers->control_head =
     355            instance->transfers_control.list_head_pa;
     356        usb_log_debug2("Control HEAD set to: %p(%p).\n",
     357            instance->transfers_control.list_head,
     358            instance->transfers_control.list_head_pa);
     359
     360        unsigned i = 0;
     361        for (; i < 32; ++i) {
     362                instance->hcca->int_ep[i] =
     363                    instance->transfers_interrupt.list_head_pa;
     364        }
     365        usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
     366            instance->transfers_interrupt.list_head,
     367            instance->transfers_interrupt.list_head_pa);
     368
     369        return EOK;
    212370}
    213371/**
  • uspace/drv/ohci/hc.h

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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.
    53  * @return Error code.
    54  */
    55 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    56 {
     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);
    5752        assert(fun);
    58         hc_t *hc = fun_to_hc(fun);
    59         assert(hc);
    60         usb_log_debug("Default address request with speed %d.\n", speed);
    61         usb_device_keeper_reserve_default_address(&hc->manager, speed);
     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        usb_log_debug("%s %d:%d %zu(%zu).\n",
     66            name, target.address, target.endpoint, size, ep->max_packet_size);
     67
     68        const size_t bw = bandwidth_count_usb11(
     69            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     70        if (res_bw < bw) {
     71                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
     72                    "but only %zu is reserved.\n",
     73                    target.address, target.endpoint, name, bw, res_bw);
     74                return ENOSPC;
     75        }
     76
     77        *batch = batch_get(
     78            fun, ep, data, size, setup_data, setup_size, in, out, arg);
     79        if (!*batch)
     80                return ENOMEM;
    6281        return EOK;
    6382}
    6483/*----------------------------------------------------------------------------*/
    65 /** Release default address.
    66  *
    67  * @param[in] fun Device function the action was invoked on.
    68  * @return Error code.
    69  */
    70 static int release_default_address(ddf_fun_t *fun)
    71 {
    72         assert(fun);
    73         hc_t *hc = fun_to_hc(fun);
    74         assert(hc);
    75         usb_log_debug("Default address release.\n");
    76         usb_device_keeper_release_default_address(&hc->manager);
    77         return EOK;
    78 }
    79 /*----------------------------------------------------------------------------*/
    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.
     84/** Request address interface function
     85 *
     86 * @param[in] fun DDF function that was called.
     87 * @param[in] speed Speed to associate with the new default address.
     88 * @param[out] address Place to write a new address.
    8589 * @return Error code.
    8690 */
     
    101105}
    102106/*----------------------------------------------------------------------------*/
    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.
     107/** Bind address interface function
     108 *
     109 * @param[in] fun DDF function that was called.
     110 * @param[in] address Address of the device
     111 * @param[in] handle Devman handle of the device driver.
    108112 * @return Error code.
    109113 */
    110114static int bind_address(
    111     ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
     115  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
    112116{
    113117        assert(fun);
     
    119123}
    120124/*----------------------------------------------------------------------------*/
    121 /** Release previously requested address.
    122  *
    123  * @param[in] fun Device function the action was invoked on.
     125/** Release address interface function
     126 *
     127 * @param[in] fun DDF function that was called.
    124128 * @param[in] address USB address to be released.
    125129 * @return Error code.
     
    139143 * @param[in] fun Device function the action was invoked on.
    140144 * @param[in] address USB address of the device.
     145 * @param[in] ep_speed Endpoint speed (invalid means to use device one).
    141146 * @param[in] endpoint Endpoint number.
    142147 * @param[in] transfer_type USB transfer type.
     
    146151 * @return Error code.
    147152 */
    148 static int register_endpoint(
    149     ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
     153static int register_endpoint(ddf_fun_t *fun,
     154    usb_address_t address, usb_speed_t ep_speed, usb_endpoint_t endpoint,
    150155    usb_transfer_type_t transfer_type, usb_direction_t direction,
    151156    size_t max_packet_size, unsigned int interval)
    152157{
    153         assert(fun);
    154158        hc_t *hc = fun_to_hc(fun);
    155159        assert(hc);
    156         if (address == hc->rh.address)
    157                 return EOK;
    158         const usb_speed_t speed =
    159                 usb_device_keeper_get_speed(&hc->manager, address);
     160
     161        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
     162        if (speed >= USB_SPEED_MAX) {
     163                speed = ep_speed;
     164        }
    160165        const size_t size = max_packet_size;
     166        int ret;
     167
    161168        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    162169            address, endpoint, usb_str_transfer_type(transfer_type),
    163170            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  */
     171
     172        endpoint_t *ep = malloc(sizeof(endpoint_t));
     173        if (ep == NULL)
     174                return ENOMEM;
     175        ret = endpoint_init(ep, address, endpoint, direction,
     176            transfer_type, speed, max_packet_size);
     177        if (ret != EOK) {
     178                free(ep);
     179                return ret;
     180        }
     181
     182        ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
     183        if (ret != EOK) {
     184                endpoint_destroy(ep);
     185        }
     186        return ret;
     187}
     188/*----------------------------------------------------------------------------*/
    176189static int unregister_endpoint(
    177190    ddf_fun_t *fun, usb_address_t address,
    178191    usb_endpoint_t endpoint, usb_direction_t direction)
    179192{
    180         assert(fun);
    181193        hc_t *hc = fun_to_hc(fun);
    182194        assert(hc);
     
    196208 * @param[in] fun Device function the action was invoked on.
    197209 * @param[in] target Target pipe (address and endpoint number) specification.
    198  * @param[in] max_packet_size Max packet size for the transfer.
    199210 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    200211 *      by the caller).
     
    205216 */
    206217static int interrupt_out(
    207     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     218    ddf_fun_t *fun, usb_target_t target, void *data,
    208219    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    209220{
    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;
     221        usb_transfer_batch_t *batch = NULL;
     222        hc_t *hc = NULL;
     223        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     224            NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
     225        if (ret != EOK)
     226                return ret;
    224227        batch_interrupt_out(batch);
    225         const int ret = hc_schedule(hc, batch);
     228        ret = hc_schedule(hc, batch);
    226229        if (ret != EOK) {
    227230                batch_dispose(batch);
     
    239242 * @param[in] fun Device function the action was invoked on.
    240243 * @param[in] target Target pipe (address and endpoint number) specification.
    241  * @param[in] max_packet_size Max packet size for the transfer.
    242244 * @param[in] data Buffer where to store the data (in USB endianess,
    243245 *      allocated and deallocated by the caller).
     
    248250 */
    249251static int interrupt_in(
    250     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     252    ddf_fun_t *fun, usb_target_t target, void *data,
    251253    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    252254{
    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;
     255        usb_transfer_batch_t *batch = NULL;
     256        hc_t *hc = NULL;
     257        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     258            NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
     259        if (ret != EOK)
     260                return ret;
    266261        batch_interrupt_in(batch);
    267         const int ret = hc_schedule(hc, batch);
     262        ret = hc_schedule(hc, batch);
    268263        if (ret != EOK) {
    269264                batch_dispose(batch);
     
    281276 * @param[in] fun Device function the action was invoked on.
    282277 * @param[in] target Target pipe (address and endpoint number) specification.
    283  * @param[in] max_packet_size Max packet size for the transfer.
    284278 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    285279 *      by the caller).
     
    290284 */
    291285static int bulk_out(
    292     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     286    ddf_fun_t *fun, usb_target_t target, void *data,
    293287    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    294288{
    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;
     289        usb_transfer_batch_t *batch = NULL;
     290        hc_t *hc = NULL;
     291        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     292            NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
     293        if (ret != EOK)
     294                return ret;
    309295        batch_bulk_out(batch);
    310         const int ret = hc_schedule(hc, batch);
     296        ret = hc_schedule(hc, batch);
    311297        if (ret != EOK) {
    312298                batch_dispose(batch);
     
    324310 * @param[in] fun Device function the action was invoked on.
    325311 * @param[in] target Target pipe (address and endpoint number) specification.
    326  * @param[in] max_packet_size Max packet size for the transfer.
    327312 * @param[in] data Buffer where to store the data (in USB endianess,
    328313 *      allocated and deallocated by the caller).
     
    333318 */
    334319static int bulk_in(
    335     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     320    ddf_fun_t *fun, usb_target_t target, void *data,
    336321    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    337322{
    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;
     323        usb_transfer_batch_t *batch = NULL;
     324        hc_t *hc = NULL;
     325        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     326            NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
     327        if (ret != EOK)
     328                return ret;
    351329        batch_bulk_in(batch);
    352         const int ret = hc_schedule(hc, batch);
     330        ret = hc_schedule(hc, batch);
    353331        if (ret != EOK) {
    354332                batch_dispose(batch);
     
    366344 * @param[in] fun Device function the action was invoked on.
    367345 * @param[in] target Target pipe (address and endpoint number) specification.
    368  * @param[in] max_packet_size Max packet size for the transfer.
    369346 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    370347 *      and deallocated by the caller).
     
    378355 */
    379356static int control_write(
    380     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     357    ddf_fun_t *fun, usb_target_t target,
    381358    void *setup_data, size_t setup_size, void *data, size_t size,
    382359    usbhc_iface_transfer_out_callback_t callback, void *arg)
    383360{
    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;
    401         usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
     361        usb_transfer_batch_t *batch = NULL;
     362        hc_t *hc = NULL;
     363        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     364            setup_data, setup_size, NULL, callback, arg, "Control WRITE",
     365            &hc, &batch);
     366        if (ret != EOK)
     367                return ret;
     368        usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
    402369        batch_control_write(batch);
    403         const int ret = hc_schedule(hc, batch);
     370        ret = hc_schedule(hc, batch);
    404371        if (ret != EOK) {
    405372                batch_dispose(batch);
     
    417384 * @param[in] fun Device function the action was invoked on.
    418385 * @param[in] target Target pipe (address and endpoint number) specification.
    419  * @param[in] max_packet_size Max packet size for the transfer.
    420386 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    421387 *      and deallocated by the caller).
     
    429395 */
    430396static int control_read(
    431     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     397    ddf_fun_t *fun, usb_target_t target,
    432398    void *setup_data, size_t setup_size, void *data, size_t size,
    433399    usbhc_iface_transfer_in_callback_t callback, void *arg)
    434400{
    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;
     401        usb_transfer_batch_t *batch = NULL;
     402        hc_t *hc = NULL;
     403        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     404            setup_data, setup_size, callback, NULL, arg, "Control READ",
     405            &hc, &batch);
     406        if (ret != EOK)
     407                return ret;
    449408        batch_control_read(batch);
    450         const int ret = hc_schedule(hc, batch);
    451         if (ret != EOK) {
    452                 batch_dispose(batch);
    453         }
    454         return ret;
    455 }
    456 /*----------------------------------------------------------------------------*/
    457 /** Host controller interface implementation for OHCI. */
     409        ret = hc_schedule(hc, batch);
     410        if (ret != EOK) {
     411                batch_dispose(batch);
     412        }
     413        return ret;
     414}
     415/*----------------------------------------------------------------------------*/
    458416usbhc_iface_t hc_iface = {
    459         .reserve_default_address = reserve_default_address,
    460         .release_default_address = release_default_address,
    461417        .request_address = request_address,
    462418        .bind_address = bind_address,
     
    475431        .control_read = control_read,
    476432};
    477 
    478433/**
    479434 * @}
  • uspace/drv/ohci/ohci_regs.h

    ra49e171 rdc4c19e  
    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 
    79         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 
     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 */
     86        volatile uint32_t interrupt_enable;
    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 (0x3fff) /* 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 (0x3fff) /* 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/root_hub.c

    ra49e171 rdc4c19e  
    4747 *      standart device descriptor for ohci root hub
    4848 */
    49 static const usb_standard_device_descriptor_t ohci_rh_device_descriptor =
    50 {
    51                 .configuration_count = 1,
    52                 .descriptor_type = USB_DESCTYPE_DEVICE,
    53                 .device_class = USB_CLASS_HUB,
    54                 .device_protocol = 0,
    55                 .device_subclass = 0,
    56                 .device_version = 0,
    57                 .length = sizeof(usb_standard_device_descriptor_t),
    58                 /// \TODO this value is guessed
    59                 .max_packet_size = 8,
    60                 .vendor_id = 0x16db,
    61                 .product_id = 0x0001,
    62                 /// \TODO these values migt be different
    63                 .str_serial_number = 0,
    64                 .usb_spec_version = 0x110,
     49static const usb_standard_device_descriptor_t ohci_rh_device_descriptor = {
     50        .configuration_count = 1,
     51        .descriptor_type = USB_DESCTYPE_DEVICE,
     52        .device_class = USB_CLASS_HUB,
     53        .device_protocol = 0,
     54        .device_subclass = 0,
     55        .device_version = 0,
     56        .length = sizeof (usb_standard_device_descriptor_t),
     57        /// \TODO this value is guessed
     58        .max_packet_size = 8,
     59        .vendor_id = 0x16db,
     60        .product_id = 0x0001,
     61        /// \TODO these values migt be different
     62        .str_serial_number = 0,
     63        .usb_spec_version = 0x110,
    6564};
    6665
     
    6968 * for ohci root hubs
    7069 */
    71 static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor =
    72 {
     70static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = {
    7371        /// \TODO some values are default or guessed
    74         .attributes = 1<<7,
     72        .attributes = 1 << 7,
    7573        .configuration_number = 1,
    7674        .descriptor_type = USB_DESCTYPE_CONFIGURATION,
    7775        .interface_count = 1,
    78         .length = sizeof(usb_standard_configuration_descriptor_t),
     76        .length = sizeof (usb_standard_configuration_descriptor_t),
    7977        .max_power = 100,
    8078        .str_configuration = 0,
     
    8482 * standart ohci root hub interface descriptor
    8583 */
    86 static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor =
    87 {
     84static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor = {
    8885        .alternate_setting = 0,
    8986        .descriptor_type = USB_DESCTYPE_INTERFACE,
     
    9491        .interface_protocol = 0,
    9592        .interface_subclass = 0,
    96         .length = sizeof(usb_standard_interface_descriptor_t),
     93        .length = sizeof (usb_standard_interface_descriptor_t),
    9794        .str_interface = 0,
    9895};
     
    10198 * standart ohci root hub endpoint descriptor
    10299 */
    103 static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor =
    104 {
     100static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor = {
    105101        .attributes = USB_TRANSFER_INTERRUPT,
    106102        .descriptor_type = USB_DESCTYPE_ENDPOINT,
    107         .endpoint_address = 1 + (1<<7),
    108         .length = sizeof(usb_standard_endpoint_descriptor_t),
     103        .endpoint_address = 1 + (1 << 7),
     104        .length = sizeof (usb_standard_endpoint_descriptor_t),
    109105        .max_packet_size = 8,
    110106        .poll_interval = 255,
     
    112108
    113109static const uint32_t hub_clear_feature_valid_mask =
    114         (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) +
    115         (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
     110        (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) |
     111(1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
    116112
    117113static const uint32_t hub_clear_feature_by_writing_one_mask =
     
    119115
    120116static const uint32_t hub_set_feature_valid_mask =
    121         (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
    122 
    123        
     117        (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT) |
     118(1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
     119
     120
    124121static const uint32_t hub_set_feature_direct_mask =
    125122        (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
    126123
    127124static const uint32_t port_set_feature_valid_mask =
    128         (1 << USB_HUB_FEATURE_PORT_ENABLE) +
    129         (1 << USB_HUB_FEATURE_PORT_SUSPEND) +
    130         (1 << USB_HUB_FEATURE_PORT_RESET) +
    131         (1 << USB_HUB_FEATURE_PORT_POWER);
     125        (1 << USB_HUB_FEATURE_PORT_ENABLE) |
     126(1 << USB_HUB_FEATURE_PORT_SUSPEND) |
     127(1 << USB_HUB_FEATURE_PORT_RESET) |
     128(1 << USB_HUB_FEATURE_PORT_POWER);
    132129
    133130static const uint32_t port_clear_feature_valid_mask =
    134         (1 << USB_HUB_FEATURE_PORT_CONNECTION) +
    135         (1 << USB_HUB_FEATURE_PORT_SUSPEND) +
    136         (1 << USB_HUB_FEATURE_PORT_OVER_CURRENT) +
    137         (1 << USB_HUB_FEATURE_PORT_POWER) +
    138         (1 << USB_HUB_FEATURE_C_PORT_CONNECTION) +
    139         (1 << USB_HUB_FEATURE_C_PORT_ENABLE) +
    140         (1 << USB_HUB_FEATURE_C_PORT_SUSPEND) +
    141         (1 << USB_HUB_FEATURE_C_PORT_OVER_CURRENT) +
    142         (1 << USB_HUB_FEATURE_C_PORT_RESET);
    143 //note that USB_HUB_FEATURE_PORT_POWER bit is translated into USB_HUB_FEATURE_PORT_LOW_SPEED
    144 
    145 
    146 
     131        (1 << USB_HUB_FEATURE_PORT_CONNECTION) |
     132(1 << USB_HUB_FEATURE_PORT_SUSPEND) |
     133(1 << USB_HUB_FEATURE_PORT_OVER_CURRENT) |
     134(1 << USB_HUB_FEATURE_PORT_POWER) |
     135(1 << USB_HUB_FEATURE_C_PORT_CONNECTION) |
     136(1 << USB_HUB_FEATURE_C_PORT_ENABLE) |
     137(1 << USB_HUB_FEATURE_C_PORT_SUSPEND) |
     138(1 << USB_HUB_FEATURE_C_PORT_OVER_CURRENT) |
     139(1 << USB_HUB_FEATURE_C_PORT_RESET);
     140//note that USB_HUB_FEATURE_PORT_POWER bit is translated into
     141//USB_HUB_FEATURE_PORT_LOW_SPEED
     142
     143static const uint32_t port_status_change_mask =
     144(1<< USB_HUB_FEATURE_C_PORT_CONNECTION) |
     145(1<< USB_HUB_FEATURE_C_PORT_ENABLE) |
     146(1<< USB_HUB_FEATURE_C_PORT_OVER_CURRENT) |
     147(1<< USB_HUB_FEATURE_C_PORT_RESET) |
     148(1<< USB_HUB_FEATURE_C_PORT_SUSPEND);
     149
     150
     151static void usb_create_serialized_hub_descriptor(rh_t *instance,
     152        uint8_t ** out_result,
     153        size_t * out_size);
     154
     155static void rh_init_descriptors(rh_t *instance);
     156
     157static int process_get_port_status_request(rh_t *instance, uint16_t port,
     158        usb_transfer_batch_t * request);
     159
     160static int process_get_hub_status_request(rh_t *instance,
     161        usb_transfer_batch_t * request);
     162
     163static int process_get_status_request(rh_t *instance,
     164        usb_transfer_batch_t * request);
     165
     166static void create_interrupt_mask(rh_t *instance, void ** buffer,
     167        size_t * buffer_size);
     168
     169static int process_get_descriptor_request(rh_t *instance,
     170        usb_transfer_batch_t *request);
     171
     172static int process_get_configuration_request(rh_t *instance,
     173        usb_transfer_batch_t *request);
     174
     175static int process_hub_feature_set_request(rh_t *instance, uint16_t feature);
     176
     177static int process_hub_feature_clear_request(rh_t *instance,
     178        uint16_t feature);
     179
     180static int process_port_feature_set_request(rh_t *instance,
     181        uint16_t feature, uint16_t port);
     182
     183static int process_port_feature_clear_request(rh_t *instance,
     184        uint16_t feature, uint16_t port);
     185
     186static int process_address_set_request(rh_t *instance,
     187        uint16_t address);
     188
     189static int process_request_with_output(rh_t *instance,
     190        usb_transfer_batch_t *request);
     191
     192static int process_request_with_input(rh_t *instance,
     193        usb_transfer_batch_t *request);
     194
     195static int process_request_without_data(rh_t *instance,
     196        usb_transfer_batch_t *request);
     197
     198static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
     199
     200
     201
     202
     203
     204/** Root hub initialization
     205 * @return Error code.
     206 */
     207int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs) {
     208        assert(instance);
     209        //instance->address = -1;
     210        instance->registers = regs;
     211        instance->device = dev;
     212        instance->port_count =
     213            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
     214        rh_init_descriptors(instance);
     215        // set port power mode to no-power-switching
     216        instance->registers->rh_desc_a =
     217                instance->registers->rh_desc_a | (1<<9);
     218
     219        usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
     220
     221        //start generic usb hub driver
     222
     223        /* TODO: implement */
     224        return EOK;
     225}
     226/*----------------------------------------------------------------------------*/
     227
     228/**
     229 * process root hub request
     230 *
     231 * @param instance root hub instance
     232 * @param request structure containing both request and response information
     233 * @return error code
     234 */
     235int rh_request(rh_t *instance, usb_transfer_batch_t *request) {
     236        assert(instance);
     237        assert(request);
     238        int opResult;
     239        if (request->transfer_type == USB_TRANSFER_CONTROL) {
     240                usb_log_info("Root hub got CONTROL packet\n");
     241                opResult = process_ctrl_request(instance, request);
     242        } else if (request->transfer_type == USB_TRANSFER_INTERRUPT) {
     243                usb_log_info("Root hub got INTERRUPT packet\n");
     244                void * buffer;
     245                create_interrupt_mask(instance, &buffer,
     246                        &(request->transfered_size));
     247                memcpy(request->transport_buffer, buffer,
     248                        request->transfered_size);
     249                opResult = EOK;
     250        } else {
     251                opResult = EINVAL;
     252        }
     253        usb_transfer_batch_finish_error(request, opResult);
     254        return EOK;
     255}
     256
     257/*----------------------------------------------------------------------------*/
     258
     259
     260void rh_interrupt(rh_t *instance) {
     261        usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
     262                "interrupts, am I?\n");
     263        /* TODO: implement? */
     264}
     265/*----------------------------------------------------------------------------*/
    147266
    148267/**
     
    157276 */
    158277static void usb_create_serialized_hub_descriptor(rh_t *instance,
    159                 uint8_t ** out_result,
    160                 size_t * out_size) {
     278        uint8_t ** out_result,
     279        size_t * out_size) {
    161280        //base size
    162281        size_t size = 7;
    163282        //variable size according to port count
    164283        size_t var_size = instance->port_count / 8 +
    165                         ((instance->port_count % 8 > 0) ? 1 : 0);
     284                ((instance->port_count % 8 > 0) ? 1 : 0);
    166285        size += 2 * var_size;
    167286        uint8_t * result = (uint8_t*) malloc(size);
    168         bzero(result,size);
     287        bzero(result, size);
    169288        //size
    170289        result[0] = size;
     
    174293        uint32_t hub_desc_reg = instance->registers->rh_desc_a;
    175294        result[3] =
    176                         ((hub_desc_reg >> 8) %2) +
    177                         (((hub_desc_reg >> 9) %2) << 1) +
    178                         (((hub_desc_reg >> 10) %2) << 2) +
    179                         (((hub_desc_reg >> 11) %2) << 3) +
    180                         (((hub_desc_reg >> 12) %2) << 4);
     295                ((hub_desc_reg >> 8) % 2) +
     296                (((hub_desc_reg >> 9) % 2) << 1) +
     297                (((hub_desc_reg >> 10) % 2) << 2) +
     298                (((hub_desc_reg >> 11) % 2) << 3) +
     299                (((hub_desc_reg >> 12) % 2) << 4);
    181300        result[4] = 0;
    182301        result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
     
    185304        int port;
    186305        for (port = 1; port <= instance->port_count; ++port) {
    187                 result[7 + port/8] +=
    188                                 ((instance->registers->rh_desc_b >> port)%2) << (port%8);
     306                uint8_t is_non_removable =
     307                        instance->registers->rh_desc_b >> port % 2;
     308                result[7 + port / 8] +=
     309                        is_non_removable << (port % 8);
    189310        }
    190311        size_t i;
     
    195316        (*out_size) = size;
    196317}
    197 
     318/*----------------------------------------------------------------------------*/
    198319
    199320/** initialize hub descriptors
     
    203324 * @instance root hub instance
    204325 */
    205 static void rh_init_descriptors(rh_t *instance){
     326static void rh_init_descriptors(rh_t *instance) {
    206327        memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    207                 sizeof(ohci_rh_device_descriptor)
    208         );
     328                sizeof (ohci_rh_device_descriptor)
     329                );
    209330        usb_standard_configuration_descriptor_t descriptor;
    210         memcpy(&descriptor,&ohci_rh_conf_descriptor,
    211                         sizeof(ohci_rh_conf_descriptor));
     331        memcpy(&descriptor, &ohci_rh_conf_descriptor,
     332                sizeof (ohci_rh_conf_descriptor));
    212333        uint8_t * hub_descriptor;
    213334        size_t hub_desc_size;
    214335        usb_create_serialized_hub_descriptor(instance, &hub_descriptor,
    215                         &hub_desc_size);
     336                &hub_desc_size);
    216337
    217338        descriptor.total_length =
    218                         sizeof(usb_standard_configuration_descriptor_t)+
    219                         sizeof(usb_standard_endpoint_descriptor_t)+
    220                         sizeof(usb_standard_interface_descriptor_t)+
    221                         hub_desc_size;
    222        
     339                sizeof (usb_standard_configuration_descriptor_t) +
     340                sizeof (usb_standard_endpoint_descriptor_t) +
     341                sizeof (usb_standard_interface_descriptor_t) +
     342                hub_desc_size;
     343
    223344        uint8_t * full_config_descriptor =
    224                         (uint8_t*) malloc(descriptor.total_length);
    225         memcpy(full_config_descriptor, &descriptor, sizeof(descriptor));
    226         memcpy(full_config_descriptor + sizeof(descriptor),
    227                         &ohci_rh_iface_descriptor, sizeof(ohci_rh_iface_descriptor));
    228         memcpy(full_config_descriptor + sizeof(descriptor) +
    229                                 sizeof(ohci_rh_iface_descriptor),
    230                         &ohci_rh_ep_descriptor, sizeof(ohci_rh_ep_descriptor));
    231         memcpy(full_config_descriptor + sizeof(descriptor) +
    232                                 sizeof(ohci_rh_iface_descriptor) +
    233                                 sizeof(ohci_rh_ep_descriptor),
    234                         hub_descriptor, hub_desc_size);
    235        
     345                (uint8_t*) malloc(descriptor.total_length);
     346        memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
     347        memcpy(full_config_descriptor + sizeof (descriptor),
     348                &ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor));
     349        memcpy(full_config_descriptor + sizeof (descriptor) +
     350                sizeof (ohci_rh_iface_descriptor),
     351                &ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor));
     352        memcpy(full_config_descriptor + sizeof (descriptor) +
     353                sizeof (ohci_rh_iface_descriptor) +
     354                sizeof (ohci_rh_ep_descriptor),
     355                hub_descriptor, hub_desc_size);
     356
    236357        instance->descriptors.configuration = full_config_descriptor;
    237358        instance->descriptors.configuration_size = descriptor.total_length;
    238359}
    239 
    240 /** Root hub initialization
    241  * @return Error code.
    242  */
    243 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs)
    244 {
    245         assert(instance);
    246         instance->address = -1;
    247         instance->registers = regs;
    248         instance->device = dev;
    249         instance->port_count = instance->registers->rh_desc_a & 0xff;
    250         rh_init_descriptors(instance);
    251         /// \TODO set port power mode
    252 
    253 
    254         usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
    255 
    256         //start generic usb hub driver
    257        
    258         /* TODO: implement */
    259         return EOK;
    260 }
    261360/*----------------------------------------------------------------------------*/
    262361
     
    272371 */
    273372static int process_get_port_status_request(rh_t *instance, uint16_t port,
    274                 usb_transfer_batch_t * request){
    275         if(port<1 || port>instance->port_count)
    276                 return EINVAL;
    277         uint32_t * uint32_buffer = (uint32_t*)request->transport_buffer;
     373        usb_transfer_batch_t * request) {
     374        if (port < 1 || port > instance->port_count)
     375                return EINVAL;
     376        uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
    278377        request->transfered_size = 4;
    279         uint32_buffer[0] = instance->registers->rh_port_status[port -1];
    280         return EOK;
    281 }
     378        uint32_buffer[0] = instance->registers->rh_port_status[port - 1];
     379#if 0
     380        int i;
     381        for (i = 0; i < instance->port_count; ++i) {
     382                usb_log_debug("port status %d,x%x\n",
     383                        instance->registers->rh_port_status[i],
     384                        instance->registers->rh_port_status[i]);
     385        }
     386#endif
     387        return EOK;
     388}
     389/*----------------------------------------------------------------------------*/
    282390
    283391/**
     
    291399 */
    292400static int process_get_hub_status_request(rh_t *instance,
    293                 usb_transfer_batch_t * request){
    294         uint32_t * uint32_buffer = (uint32_t*)request->transport_buffer;
     401        usb_transfer_batch_t * request) {
     402        uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
     403        request->transfered_size = 4;
    295404        //bits, 0,1,16,17
    296         request->transfered_size = 4;
    297         uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17);
     405        uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17);
    298406        uint32_buffer[0] = mask & instance->registers->rh_status;
    299407        return EOK;
    300 
    301 }
    302 
    303 
     408}
     409/*----------------------------------------------------------------------------*/
    304410
    305411/**
     
    313419 */
    314420static int process_get_status_request(rh_t *instance,
    315                 usb_transfer_batch_t * request)
    316 {
     421        usb_transfer_batch_t * request) {
    317422        size_t buffer_size = request->buffer_size;
    318423        usb_device_request_setup_packet_t * request_packet =
    319                         (usb_device_request_setup_packet_t*)
    320                         request->setup_buffer;
     424                (usb_device_request_setup_packet_t*)
     425                request->setup_buffer;
    321426
    322427        usb_hub_bm_request_type_t request_type = request_packet->request_type;
    323         if(buffer_size<4/*request_packet->length*/){///\TODO
     428        if (buffer_size < 4/*request_packet->length*/) {///\TODO
    324429                usb_log_warning("requested more data than buffer size\n");
    325430                return EINVAL;
    326431        }
    327432
    328         if(request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
     433        if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
    329434                return process_get_hub_status_request(instance, request);
    330         if(request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
    331                 return process_get_port_status_request(instance, request_packet->index,
    332                                 request);
     435        if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
     436                return process_get_port_status_request(instance,
     437                request_packet->index,
     438                request);
    333439        return ENOTSUP;
    334440}
     441/*----------------------------------------------------------------------------*/
    335442
    336443/**
     
    339446 * Result contains bitmap where bit 0 indicates change on hub and
    340447 * bit i indicates change on i`th port (i>0). For more info see
    341  * Hub and Port status bitmap specification in USB specification.
     448 * Hub and Port status bitmap specification in USB specification
     449 * (chapter 11.13.4)
    342450 * @param instance root hub instance
    343451 * @param@out buffer pointer to created interrupt mas
     
    345453 */
    346454static void create_interrupt_mask(rh_t *instance, void ** buffer,
    347                 size_t * buffer_size){
     455        size_t * buffer_size) {
    348456        int bit_count = instance->port_count + 1;
    349         (*buffer_size) = (bit_count / 8) + (bit_count%8==0)?0:1;
     457        (*buffer_size) = (bit_count / 8) + ((bit_count % 8 == 0) ? 0 : 1);
     458
    350459        (*buffer) = malloc(*buffer_size);
    351         uint8_t * bitmap = (uint8_t*)(*buffer);
    352         uint32_t mask = (1<<16) + (1<<17);
    353         bzero(bitmap,(*buffer_size));
    354         if(instance->registers->rh_status & mask){
     460        uint8_t * bitmap = (uint8_t*) (*buffer);
     461        uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
     462                | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
     463        bzero(bitmap, (*buffer_size));
     464        if (instance->registers->rh_status & mask) {
    355465                bitmap[0] = 1;
    356466        }
    357467        int port;
    358         mask = 0;
    359         int i;
    360         for(i=16;i<=20;++i)
    361                 mask += 1<<i;
    362         for(port = 1; port<=instance->port_count;++port){
    363                 if(mask & instance->registers->rh_port_status[port-1]){
    364                         bitmap[(port+1)/8] += 1<<(port%8);
    365                 }
    366         }
    367 }
    368  
     468        mask = port_status_change_mask;
     469        for (port = 1; port <= instance->port_count; ++port) {
     470                if (mask & instance->registers->rh_port_status[port - 1]) {
     471                        bitmap[(port) / 8] += 1 << (port % 8);
     472                }
     473        }
     474}
     475/*----------------------------------------------------------------------------*/
     476
    369477/**
    370478 * create answer to a descriptor request
     
    377485 */
    378486static int process_get_descriptor_request(rh_t *instance,
    379                 usb_transfer_batch_t *request){
     487        usb_transfer_batch_t *request) {
    380488        usb_device_request_setup_packet_t * setup_request =
    381                         (usb_device_request_setup_packet_t*)request->setup_buffer;
     489                (usb_device_request_setup_packet_t*) request->setup_buffer;
    382490        size_t size;
    383491        const void * result_descriptor = NULL;
    384492        const uint16_t setup_request_value = setup_request->value_high;
    385                         //(setup_request->value_low << 8);
     493        //(setup_request->value_low << 8);
    386494        bool del = false;
    387         switch (setup_request_value)
    388         {
    389                 case USB_DESCTYPE_HUB: {
     495        switch (setup_request_value) {
     496                case USB_DESCTYPE_HUB:
     497                {
    390498                        uint8_t * descriptor;
    391499                        usb_create_serialized_hub_descriptor(
    392500                                instance, &descriptor, &size);
    393501                        result_descriptor = descriptor;
    394                         if(result_descriptor) del = true;
     502                        if (result_descriptor) del = true;
    395503                        break;
    396504                }
    397                 case USB_DESCTYPE_DEVICE: {
     505                case USB_DESCTYPE_DEVICE:
     506                {
    398507                        usb_log_debug("USB_DESCTYPE_DEVICE\n");
    399508                        result_descriptor = &ohci_rh_device_descriptor;
    400                         size = sizeof(ohci_rh_device_descriptor);
     509                        size = sizeof (ohci_rh_device_descriptor);
    401510                        break;
    402511                }
    403                 case USB_DESCTYPE_CONFIGURATION: {
     512                case USB_DESCTYPE_CONFIGURATION:
     513                {
    404514                        usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
    405515                        result_descriptor = instance->descriptors.configuration;
     
    407517                        break;
    408518                }
    409                 case USB_DESCTYPE_INTERFACE: {
     519                case USB_DESCTYPE_INTERFACE:
     520                {
    410521                        usb_log_debug("USB_DESCTYPE_INTERFACE\n");
    411522                        result_descriptor = &ohci_rh_iface_descriptor;
    412                         size = sizeof(ohci_rh_iface_descriptor);
     523                        size = sizeof (ohci_rh_iface_descriptor);
    413524                        break;
    414525                }
    415                 case USB_DESCTYPE_ENDPOINT: {
     526                case USB_DESCTYPE_ENDPOINT:
     527                {
    416528                        usb_log_debug("USB_DESCTYPE_ENDPOINT\n");
    417529                        result_descriptor = &ohci_rh_ep_descriptor;
    418                         size = sizeof(ohci_rh_ep_descriptor);
     530                        size = sizeof (ohci_rh_ep_descriptor);
    419531                        break;
    420532                }
    421                 default: {
    422                         usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value);
    423                         usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ",
    424                                         setup_request->request_type,
    425                                         setup_request->request,
    426                                         setup_request_value,
    427                                         setup_request->index,
    428                                         setup_request->length
    429                                         );
     533                default:
     534                {
     535                        usb_log_debug("USB_DESCTYPE_EINVAL %d \n",
     536                                setup_request->value);
     537                        usb_log_debug("\ttype %d\n\trequest %d\n\tvalue "
     538                                "%d\n\tindex %d\n\tlen %d\n ",
     539                                setup_request->request_type,
     540                                setup_request->request,
     541                                setup_request_value,
     542                                setup_request->index,
     543                                setup_request->length
     544                                );
    430545                        return EINVAL;
    431546                }
    432547        }
    433         if(request->buffer_size < size){
     548        if (request->buffer_size < size) {
    434549                size = request->buffer_size;
    435550        }
    436551        request->transfered_size = size;
    437         memcpy(request->transport_buffer,result_descriptor,size);
    438         usb_log_debug("sent desctiptor: %s\n",
    439                         usb_debug_str_buffer((uint8_t*)request->transport_buffer,size,size));
     552        memcpy(request->transport_buffer, result_descriptor, size);
    440553        if (del)
    441554                free(result_descriptor);
    442555        return EOK;
    443556}
     557/*----------------------------------------------------------------------------*/
    444558
    445559/**
     
    451565 * @return error code
    452566 */
    453 static int process_get_configuration_request(rh_t *instance, 
    454                 usb_transfer_batch_t *request){
     567static int process_get_configuration_request(rh_t *instance,
     568        usb_transfer_batch_t *request) {
    455569        //set and get configuration requests do not have any meaning, only dummy
    456570        //values are returned
    457         if(request->buffer_size != 1)
     571        if (request->buffer_size != 1)
    458572                return EINVAL;
    459573        request->transport_buffer[0] = 1;
     
    461575        return EOK;
    462576}
     577/*----------------------------------------------------------------------------*/
    463578
    464579/**
    465580 * process feature-enabling request on hub
    466  * 
     581 *
    467582 * @param instance root hub instance
    468583 * @param feature feature selector
     
    470585 */
    471586static int process_hub_feature_set_request(rh_t *instance,
    472                 uint16_t feature){
    473         if(! ((1<<feature) & hub_set_feature_valid_mask))
    474                 return EINVAL;
     587        uint16_t feature) {
     588        if (!((1 << feature) & hub_set_feature_valid_mask))
     589                return EINVAL;
     590        if(feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
     591                feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;
    475592        instance->registers->rh_status =
    476                         (instance->registers->rh_status | (1<<feature))
    477                         & (~ hub_clear_feature_by_writing_one_mask);
    478         return EOK;
    479 }
     593                (instance->registers->rh_status | (1 << feature))
     594                & (~hub_clear_feature_by_writing_one_mask);
     595        return EOK;
     596}
     597/*----------------------------------------------------------------------------*/
    480598
    481599/**
     
    487605 */
    488606static int process_hub_feature_clear_request(rh_t *instance,
    489                 uint16_t feature){
    490         if(! ((1<<feature) & hub_clear_feature_valid_mask))
     607        uint16_t feature) {
     608        if (!((1 << feature) & hub_clear_feature_valid_mask))
    491609                return EINVAL;
    492610        //is the feature cleared directly?
    493         if ((1<<feature) & hub_set_feature_direct_mask){
     611        if ((1 << feature) & hub_set_feature_direct_mask) {
    494612                instance->registers->rh_status =
    495                         (instance->registers->rh_status & (~(1<<feature)))
    496                         & (~ hub_clear_feature_by_writing_one_mask);
    497         }else{//the feature is cleared by writing '1'
     613                        (instance->registers->rh_status & (~(1 << feature)))
     614                        & (~hub_clear_feature_by_writing_one_mask);
     615        } else {//the feature is cleared by writing '1'
    498616                instance->registers->rh_status =
    499                                 (instance->registers->rh_status
    500                                 & (~ hub_clear_feature_by_writing_one_mask))
    501                                 | (1<<feature);
    502         }
    503         return EOK;
    504 }
    505 
    506 
     617                        (instance->registers->rh_status
     618                        & (~hub_clear_feature_by_writing_one_mask))
     619                        | (1 << feature);
     620        }
     621        return EOK;
     622}
     623/*----------------------------------------------------------------------------*/
    507624
    508625/**
    509626 * process feature-enabling request on hub
    510  * 
     627 *
    511628 * @param instance root hub instance
    512629 * @param feature feature selector
     
    516633 */
    517634static int process_port_feature_set_request(rh_t *instance,
    518                 uint16_t feature, uint16_t port){
    519         if(!((1<<feature) & port_set_feature_valid_mask))
    520                 return EINVAL;
    521         if(port<1 || port>instance->port_count)
     635        uint16_t feature, uint16_t port) {
     636        if (!((1 << feature) & port_set_feature_valid_mask))
     637                return EINVAL;
     638        if (port < 1 || port > instance->port_count)
    522639                return EINVAL;
    523640        instance->registers->rh_port_status[port - 1] =
    524                         (instance->registers->rh_port_status[port - 1] | (1<<feature))
    525                         & (~port_clear_feature_valid_mask);
     641                (instance->registers->rh_port_status[port - 1] | (1 << feature))
     642                & (~port_clear_feature_valid_mask);
    526643        /// \TODO any error?
    527644        return EOK;
    528645}
     646/*----------------------------------------------------------------------------*/
    529647
    530648/**
     
    538656 */
    539657static int process_port_feature_clear_request(rh_t *instance,
    540                 uint16_t feature, uint16_t port){
    541         if(!((1<<feature) & port_clear_feature_valid_mask))
    542                 return EINVAL;
    543         if(port<1 || port>instance->port_count)
    544                 return EINVAL;
    545         if(feature == USB_HUB_FEATURE_PORT_POWER)
     658        uint16_t feature, uint16_t port) {
     659        if (!((1 << feature) & port_clear_feature_valid_mask))
     660                return EINVAL;
     661        if (port < 1 || port > instance->port_count)
     662                return EINVAL;
     663        if (feature == USB_HUB_FEATURE_PORT_POWER)
    546664                feature = USB_HUB_FEATURE_PORT_LOW_SPEED;
    547         if(feature == USB_HUB_FEATURE_PORT_SUSPEND)
     665        if (feature == USB_HUB_FEATURE_PORT_SUSPEND)
    548666                feature = USB_HUB_FEATURE_PORT_OVER_CURRENT;
    549667        instance->registers->rh_port_status[port - 1] =
    550                         (instance->registers->rh_port_status[port - 1]
    551                         & (~port_clear_feature_valid_mask))
    552                         | (1<<feature);
     668                (instance->registers->rh_port_status[port - 1]
     669                & (~port_clear_feature_valid_mask))
     670                | (1 << feature);
    553671        /// \TODO any error?
    554672        return EOK;
    555673}
    556 
     674/*----------------------------------------------------------------------------*/
    557675
    558676/**
    559677 * register address to this device
    560  * 
     678 *
    561679 * @param instance root hub instance
    562680 * @param address new address
     
    564682 */
    565683static int process_address_set_request(rh_t *instance,
    566                 uint16_t address){
     684        uint16_t address) {
    567685        instance->address = address;
    568686        return EOK;
    569687}
     688/*----------------------------------------------------------------------------*/
    570689
    571690/**
     
    579698 */
    580699static int process_request_with_output(rh_t *instance,
    581                 usb_transfer_batch_t *request){
     700        usb_transfer_batch_t *request) {
    582701        usb_device_request_setup_packet_t * setup_request =
    583                         (usb_device_request_setup_packet_t*)request->setup_buffer;
    584         if(setup_request->request == USB_DEVREQ_GET_STATUS){
     702                (usb_device_request_setup_packet_t*) request->setup_buffer;
     703        if (setup_request->request == USB_DEVREQ_GET_STATUS) {
    585704                usb_log_debug("USB_DEVREQ_GET_STATUS\n");
    586705                return process_get_status_request(instance, request);
    587706        }
    588         if(setup_request->request == USB_DEVREQ_GET_DESCRIPTOR){
     707        if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) {
    589708                usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
    590709                return process_get_descriptor_request(instance, request);
    591710        }
    592         if(setup_request->request == USB_DEVREQ_GET_CONFIGURATION){
     711        if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) {
    593712                usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
    594713                return process_get_configuration_request(instance, request);
     
    596715        return ENOTSUP;
    597716}
     717/*----------------------------------------------------------------------------*/
    598718
    599719/**
     
    607727 */
    608728static int process_request_with_input(rh_t *instance,
    609                 usb_transfer_batch_t *request){
     729        usb_transfer_batch_t *request) {
    610730        usb_device_request_setup_packet_t * setup_request =
    611                         (usb_device_request_setup_packet_t*)request->setup_buffer;
     731                (usb_device_request_setup_packet_t*) request->setup_buffer;
    612732        request->transfered_size = 0;
    613         if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR){
     733        if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) {
    614734                return ENOTSUP;
    615735        }
    616         if(setup_request->request == USB_DEVREQ_SET_CONFIGURATION){
     736        if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) {
    617737                //set and get configuration requests do not have any meaning,
    618738                //only dummy values are returned
     
    621741        return ENOTSUP;
    622742}
     743/*----------------------------------------------------------------------------*/
    623744
    624745/**
     
    632753 */
    633754static int process_request_without_data(rh_t *instance,
    634                 usb_transfer_batch_t *request){
     755        usb_transfer_batch_t *request) {
    635756        usb_device_request_setup_packet_t * setup_request =
    636                         (usb_device_request_setup_packet_t*)request->setup_buffer;
     757                (usb_device_request_setup_packet_t*) request->setup_buffer;
    637758        request->transfered_size = 0;
    638         if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE){
    639                 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){
     759        if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) {
     760                if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
    640761                        usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    641762                        return process_hub_feature_clear_request(instance,
    642                                         setup_request->value);
    643                 }
    644                 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
     763                                setup_request->value);
     764                }
     765                if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
    645766                        usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    646767                        return process_port_feature_clear_request(instance,
    647                                         setup_request->value,
    648                                         setup_request->index);
     768                                setup_request->value,
     769                                setup_request->index);
    649770                }
    650771                usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
    651                                 setup_request->request_type);
    652                 return EINVAL;
    653         }
    654         if(setup_request->request == USB_DEVREQ_SET_FEATURE){
    655                 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){
     772                        setup_request->request_type);
     773                return EINVAL;
     774        }
     775        if (setup_request->request == USB_DEVREQ_SET_FEATURE) {
     776                if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
    656777                        usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    657778                        return process_hub_feature_set_request(instance,
    658                                         setup_request->value);
    659                 }
    660                 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
     779                                setup_request->value);
     780                }
     781                if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
    661782                        usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    662783                        return process_port_feature_set_request(instance,
    663                                         setup_request->value,
    664                                         setup_request->index);
    665                 }
    666                 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",setup_request->request_type);
    667                 return EINVAL;
    668         }
    669         if(setup_request->request == USB_DEVREQ_SET_ADDRESS){
     784                                setup_request->value,
     785                                setup_request->index);
     786                }
     787                usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
     788                        setup_request->request_type);
     789                return EINVAL;
     790        }
     791        if (setup_request->request == USB_DEVREQ_SET_ADDRESS) {
    670792                usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
    671                 return process_address_set_request(instance, setup_request->value);
    672         }
    673         usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",setup_request->request_type);
     793                return process_address_set_request(instance,
     794                        setup_request->value);
     795        }
     796        usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",
     797                setup_request->request_type);
    674798        return ENOTSUP;
    675799}
     800/*----------------------------------------------------------------------------*/
    676801
    677802/**
     
    693818 * @return error code
    694819 */
    695 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request){
     820static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) {
     821        if (!request->setup_buffer) {
     822                usb_log_error("root hub received empty transaction?");
     823                return EINVAL;
     824        }
    696825        int opResult;
    697         if (request->setup_buffer) {
    698                 if(sizeof(usb_device_request_setup_packet_t)>request->setup_size){
    699                         usb_log_error("setup packet too small\n");
    700                         return EINVAL;
    701                 }
    702                 usb_log_info("CTRL packet: %s.\n",
    703                         usb_debug_str_buffer((const uint8_t *)request->setup_buffer, 8, 8));
    704                 usb_device_request_setup_packet_t * setup_request =
    705                                 (usb_device_request_setup_packet_t*)request->setup_buffer;
    706                 if(
    707                         setup_request->request == USB_DEVREQ_GET_STATUS
    708                         || setup_request->request == USB_DEVREQ_GET_DESCRIPTOR
    709                         || setup_request->request == USB_DEVREQ_GET_CONFIGURATION
    710                 ){
     826        if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) {
     827                usb_log_error("setup packet too small\n");
     828                return EINVAL;
     829        }
     830        usb_log_info("CTRL packet: %s.\n",
     831                usb_debug_str_buffer(
     832                (const uint8_t *) request->setup_buffer, 8, 8));
     833        usb_device_request_setup_packet_t * setup_request =
     834                (usb_device_request_setup_packet_t*)
     835                request->setup_buffer;
     836        switch (setup_request->request) {
     837                case USB_DEVREQ_GET_STATUS:
     838                case USB_DEVREQ_GET_DESCRIPTOR:
     839                case USB_DEVREQ_GET_CONFIGURATION:
    711840                        usb_log_debug("processing request with output\n");
    712                         opResult = process_request_with_output(instance,request);
    713                 }else if(
    714                         setup_request->request == USB_DEVREQ_CLEAR_FEATURE
    715                         || setup_request->request == USB_DEVREQ_SET_FEATURE
    716                         || setup_request->request == USB_DEVREQ_SET_ADDRESS
    717                 ){
    718                         usb_log_debug("processing request without additional data\n");
    719                         opResult = process_request_without_data(instance,request);
    720                 }else if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR
    721                                 || setup_request->request == USB_DEVREQ_SET_CONFIGURATION
    722                 ){
    723                         usb_log_debug("processing request with input\n");
    724                         opResult = process_request_with_input(instance,request);
    725                 }else{
    726                         usb_log_warning("received unsuported request: %d\n",
    727                                         setup_request->request
    728                                         );
     841                        opResult = process_request_with_output(
     842                                instance, request);
     843                        break;
     844                case USB_DEVREQ_CLEAR_FEATURE:
     845                case USB_DEVREQ_SET_FEATURE:
     846                case USB_DEVREQ_SET_ADDRESS:
     847                        usb_log_debug("processing request without "
     848                                "additional data\n");
     849                        opResult = process_request_without_data(
     850                                instance, request);
     851                        break;
     852                case USB_DEVREQ_SET_DESCRIPTOR:
     853                case USB_DEVREQ_SET_CONFIGURATION:
     854                        usb_log_debug("processing request with "
     855                                "input\n");
     856                        opResult = process_request_with_input(
     857                                instance, request);
     858                        break;
     859                default:
     860                        usb_log_warning("received unsuported request: "
     861                                "%d\n",
     862                                setup_request->request
     863                                );
    729864                        opResult = ENOTSUP;
    730                 }
    731         }else{
    732                 usb_log_error("root hub received empty transaction?");
    733                 opResult = EINVAL;
    734865        }
    735866        return opResult;
     
    737868
    738869/**
    739  * process root hub request
    740  *
    741  * @param instance root hub instance
    742  * @param request structure containing both request and response information
    743  * @return error code
    744  */
    745 int rh_request(rh_t *instance, usb_transfer_batch_t *request)
    746 {
    747         assert(instance);
    748         assert(request);
    749         int opResult;
    750         if(request->transfer_type == USB_TRANSFER_CONTROL){
    751                 usb_log_info("Root hub got CONTROL packet\n");
    752                 opResult = process_ctrl_request(instance,request);
    753         }else if(request->transfer_type == USB_TRANSFER_INTERRUPT){
    754                 usb_log_info("Root hub got INTERRUPT packet\n");
    755                 void * buffer;
    756                 create_interrupt_mask(instance, &buffer,
    757                         &(request->transfered_size));
    758                 memcpy(request->transport_buffer,buffer, request->transfered_size);
    759                 opResult = EOK;
    760         }else{
    761                 opResult = EINVAL;
    762         }
    763         usb_transfer_batch_finish(request, opResult);
    764         return EOK;
    765 }
    766 /*----------------------------------------------------------------------------*/
    767 
    768 
    769 void rh_interrupt(rh_t *instance)
    770 {
    771         usb_log_info("Whoa whoa wait, I`m not supposed to receive any interrupts, am I?\n");
    772         /* TODO: implement? */
    773 }
    774 /**
    775870 * @}
    776871 */
  • uspace/drv/ohci/utils/malloc32.h

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    8080 * transaction and callback.
    8181 */
    82 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    83     usb_transfer_type_t transfer_type, size_t max_packet_size,
    84     usb_speed_t speed, char *buffer, size_t buffer_size,
    85     char* setup_buffer, size_t setup_size,
     82usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
     83    char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
    8684    usbhc_iface_transfer_in_callback_t func_in,
    87     usbhc_iface_transfer_out_callback_t func_out, void *arg, endpoint_t *ep
    88     )
    89 {
     85    usbhc_iface_transfer_out_callback_t func_out, void *arg)
     86{
     87        assert(ep);
    9088        assert(func_in == NULL || func_out == NULL);
    9189        assert(func_in != NULL || func_out != NULL);
     
    103101        CHECK_NULL_DISPOSE_RETURN(instance,
    104102            "Failed to allocate batch instance.\n");
    105         usb_transfer_batch_init(instance, target,
    106             transfer_type, speed, max_packet_size,
    107             buffer, NULL, buffer_size, NULL, setup_size, func_in,
    108             func_out, arg, fun, ep, NULL);
     103        usb_target_t target =
     104            { .address = ep->address, .endpoint = ep->endpoint };
     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;
    116114
    117         data->transfers = (buffer_size + max_packet_size - 1) / max_packet_size;
    118         if (transfer_type == USB_TRANSFER_CONTROL) {
     115        data->transfers =
     116            (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
     117        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
    119118                data->transfers += 2;
    120119        }
     
    178177                            instance, i, data->tds[i].status);
    179178                        td_print_status(&data->tds[i]);
    180                         if (instance->ep != NULL)
    181                                 endpoint_toggle_set(instance->ep,
    182                                     td_toggle(&data->tds[i]));
     179                        assert(instance->ep != NULL);
     180
     181                        endpoint_toggle_set(instance->ep,
     182                            td_toggle(&data->tds[i]));
    183183                        if (i > 0)
    184184                                goto substract_ret;
  • uspace/drv/uhci-hcd/batch.h

    ra49e171 rdc4c19e  
    4444
    4545usb_transfer_batch_t * batch_get(
    46     ddf_fun_t *fun,
    47                 usb_target_t target,
    48     usb_transfer_type_t transfer_type,
    49                 size_t max_packet_size,
    50     usb_speed_t speed,
    51                 char *buffer,
    52                 size_t size,
    53                 char *setup_buffer,
    54                 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,
    5548    usbhc_iface_transfer_in_callback_t func_in,
    5649    usbhc_iface_transfer_out_callback_t func_out,
    57                 void *arg,
    58                 endpoint_t *ep
    59                 );
     50    void *arg);
    6051
    6152void batch_dispose(usb_transfer_batch_t *instance);
  • uspace/drv/uhci-hcd/hc.c

    ra49e171 rdc4c19e  
    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
     
    332331            instance->transfers[batch->speed][batch->transfer_type];
    333332        assert(list);
    334         if (batch->transfer_type == USB_TRANSFER_CONTROL) {
    335                 usb_device_keeper_use_control(
    336                     &instance->manager, batch->target);
    337         }
    338333        transfer_list_add_batch(list, batch);
    339334
     
    373368                        usb_transfer_batch_t *batch =
    374369                            list_get_instance(item, usb_transfer_batch_t, link);
    375                         switch (batch->transfer_type)
    376                         {
    377                         case USB_TRANSFER_CONTROL:
    378                                 usb_device_keeper_release_control(
    379                                     &instance->manager, batch->target);
    380                                 break;
    381                         case USB_TRANSFER_INTERRUPT:
    382                         case USB_TRANSFER_ISOCHRONOUS: {
    383 /*
    384                                 int ret = bandwidth_free(&instance->bandwidth,
    385                                     batch->target.address,
    386                                     batch->target.endpoint,
    387                                     batch->direction);
    388                                 if (ret != EOK)
    389                                         usb_log_warning("Failed(%d) to free "
    390                                             "reserved bw: %s.\n", ret,
    391                                             str_error(ret));
    392 */
    393                                 }
    394                         default:
    395                                 break;
    396                         }
    397                         batch->next_step(batch);
     370                        usb_transfer_batch_finish(batch);
    398371                }
    399372        }
  • uspace/drv/uhci-hcd/iface.c

    ra49e171 rdc4c19e  
    4141#include "hc.h"
    4242
    43 /** Reserve default address interface function
    44  *
    45  * @param[in] fun DDF function that was called.
    46  * @param[in] speed Speed to associate with the new default address.
    47  * @return Error code.
    48  */
    49 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    50 {
     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);
    5152        assert(fun);
    52         hc_t *hc = fun_to_hc(fun);
    53         assert(hc);
    54         usb_log_debug("Default address request with speed %d.\n", speed);
    55         usb_device_keeper_reserve_default_address(&hc->manager, speed);
    56         return EOK;
    57 #if 0
    58         endpoint_t *ep = malloc(sizeof(endpoint_t));
    59         if (ep == NULL)
     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        usb_log_debug("%s %d:%d %zu(%zu).\n",
     66            name, target.address, target.endpoint, size, ep->max_packet_size);
     67
     68        const size_t bw = bandwidth_count_usb11(
     69            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     70        if (res_bw < bw) {
     71                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
     72                    "but only %zu is reserved.\n",
     73                    target.address, target.endpoint, name, bw, res_bw);
     74                return ENOSPC;
     75        }
     76
     77        *batch = batch_get(
     78                fun, ep, data, size, setup_data, setup_size, in, out, arg);
     79        if (!*batch)
    6080                return ENOMEM;
    61         const size_t max_packet_size = speed == USB_SPEED_LOW ? 8 : 64;
    62         endpoint_init(ep, USB_TRANSFER_CONTROL, speed, max_packet_size);
    63         int ret;
    64 try_retgister:
    65         ret = usb_endpoint_manager_register_ep(&hc->ep_manager,
    66             USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH, ep, endpoint_destroy, 0);
    67         if (ret == EEXISTS) {
    68                 async_usleep(1000);
    69                 goto try_retgister;
    70         }
    71         if (ret != EOK) {
    72                 endpoint_destroy(ep);
    73         }
    74         return ret;
    75 #endif
    76 }
    77 /*----------------------------------------------------------------------------*/
    78 /** Release default address interface function
    79  *
    80  * @param[in] fun DDF function that was called.
    81  * @return Error code.
    82  */
    83 static int release_default_address(ddf_fun_t *fun)
    84 {
    85         assert(fun);
    86         hc_t *hc = fun_to_hc(fun);
    87         assert(hc);
    88         usb_log_debug("Default address release.\n");
    89 //      return usb_endpoint_manager_unregister_ep(&hc->ep_manager,
    90 //          USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH);
    91         usb_device_keeper_release_default_address(&hc->manager);
    9281        return EOK;
    9382}
     
    151140/*----------------------------------------------------------------------------*/
    152141static int register_endpoint(
    153     ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
     142    ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
     143    usb_endpoint_t endpoint,
    154144    usb_transfer_type_t transfer_type, usb_direction_t direction,
    155145    size_t max_packet_size, unsigned int interval)
     
    157147        hc_t *hc = fun_to_hc(fun);
    158148        assert(hc);
    159         const usb_speed_t speed =
    160             usb_device_keeper_get_speed(&hc->manager, address);
    161         const size_t size =
    162             (transfer_type == USB_TRANSFER_INTERRUPT
    163             || transfer_type == USB_TRANSFER_ISOCHRONOUS) ?
    164             max_packet_size : 0;
     149        const size_t size = max_packet_size;
    165150        int ret;
     151        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
     152        if (speed >= USB_SPEED_MAX) {
     153                speed = ep_speed;
     154        }
     155        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
     156            address, endpoint, usb_str_transfer_type(transfer_type),
     157            usb_str_speed(speed), direction, size, max_packet_size, interval);
     158
    166159
    167160        endpoint_t *ep = malloc(sizeof(endpoint_t));
     
    175168        }
    176169
    177         usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    178             address, endpoint, usb_str_transfer_type(transfer_type),
    179             usb_str_speed(speed), direction, size, max_packet_size, interval);
    180 
    181170        ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    182171        if (ret != EOK) {
    183172                endpoint_destroy(ep);
    184         } else {
    185                 usb_device_keeper_add_ep(&hc->manager, address, ep);
    186173        }
    187174        return ret;
     
    204191 * @param[in] fun DDF function that was called.
    205192 * @param[in] target USB device to write to.
    206  * @param[in] max_packet_size maximum size of data packet the device accepts
    207193 * @param[in] data Source of data.
    208194 * @param[in] size Size of data source.
     
    212198 */
    213199static int interrupt_out(
    214     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     200    ddf_fun_t *fun, usb_target_t target, void *data,
    215201    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    216202{
    217         assert(fun);
    218         hc_t *hc = fun_to_hc(fun);
    219         assert(hc);
    220 
    221         usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n",
    222             target.address, target.endpoint, size, max_packet_size);
    223 
    224         size_t res_bw;
    225         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    226             target.address, target.endpoint, USB_DIRECTION_OUT, &res_bw);
    227         if (ep == NULL) {
    228                 usb_log_error("Endpoint(%d:%d) not registered for INT OUT.\n",
    229                         target.address, target.endpoint);
    230                 return ENOENT;
    231         }
    232         const size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,
    233             size, ep->max_packet_size);
    234         if (res_bw < bw)
    235         {
    236                 usb_log_error("Endpoint(%d:%d) INT IN needs %zu bw "
    237                     "but only %zu is reserved.\n",
    238                     target.address, target.endpoint, bw, res_bw);
    239                 return ENOENT;
    240         }
    241         assert(ep->speed ==
    242             usb_device_keeper_get_speed(&hc->manager, target.address));
    243         assert(ep->max_packet_size == max_packet_size);
    244         assert(ep->transfer_type == USB_TRANSFER_INTERRUPT);
    245 
    246         usb_transfer_batch_t *batch =
    247             batch_get(fun, target, ep->transfer_type, ep->max_packet_size,
    248                 ep->speed, data, size, NULL, 0, NULL, callback, arg, ep);
    249         if (!batch)
    250                 return ENOMEM;
     203        usb_transfer_batch_t *batch = NULL;
     204        hc_t *hc = NULL;
     205        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     206            NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
     207        if (ret != EOK)
     208                return ret;
    251209        batch_interrupt_out(batch);
    252         const int ret = hc_schedule(hc, batch);
     210        ret = hc_schedule(hc, batch);
    253211        if (ret != EOK) {
    254212                batch_dispose(batch);
     
    261219 * @param[in] fun DDF function that was called.
    262220 * @param[in] target USB device to write to.
    263  * @param[in] max_packet_size maximum size of data packet the device accepts
    264221 * @param[out] data Data destination.
    265222 * @param[in] size Size of data source.
     
    269226 */
    270227static int interrupt_in(
    271     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     228    ddf_fun_t *fun, usb_target_t target, void *data,
    272229    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    273230{
    274         assert(fun);
    275         hc_t *hc = fun_to_hc(fun);
    276         assert(hc);
    277 
    278         usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n",
    279             target.address, target.endpoint, size, max_packet_size);
    280 
    281         size_t res_bw;
    282         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    283             target.address, target.endpoint, USB_DIRECTION_IN, &res_bw);
    284         if (ep == NULL) {
    285                 usb_log_error("Endpoint(%d:%d) not registered for INT IN.\n",
    286                     target.address, target.endpoint);
    287                 return ENOENT;
    288         }
    289         const size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,
    290             size, ep->max_packet_size);
    291         if (res_bw < bw)
    292         {
    293                 usb_log_error("Endpoint(%d:%d) INT IN needs %zu bw "
    294                     "but only %zu bw is reserved.\n",
    295                     target.address, target.endpoint, bw, res_bw);
    296                 return ENOENT;
    297         }
    298 
    299         assert(ep->speed ==
    300             usb_device_keeper_get_speed(&hc->manager, target.address));
    301         assert(ep->max_packet_size == max_packet_size);
    302         assert(ep->transfer_type == USB_TRANSFER_INTERRUPT);
    303 
    304         usb_transfer_batch_t *batch =
    305             batch_get(fun, target, ep->transfer_type, ep->max_packet_size,
    306                 ep->speed, data, size, NULL, 0, callback, NULL, arg, ep);
    307         if (!batch)
    308                 return ENOMEM;
     231        usb_transfer_batch_t *batch = NULL;
     232        hc_t *hc = NULL;
     233        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     234            NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
     235        if (ret != EOK)
     236                return ret;
    309237        batch_interrupt_in(batch);
    310         const int ret = hc_schedule(hc, batch);
     238        ret = hc_schedule(hc, batch);
    311239        if (ret != EOK) {
    312240                batch_dispose(batch);
     
    319247 * @param[in] fun DDF function that was called.
    320248 * @param[in] target USB device to write to.
    321  * @param[in] max_packet_size maximum size of data packet the device accepts
    322249 * @param[in] data Source of data.
    323250 * @param[in] size Size of data source.
     
    327254 */
    328255static int bulk_out(
    329     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     256    ddf_fun_t *fun, usb_target_t target, void *data,
    330257    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    331258{
    332         assert(fun);
    333         hc_t *hc = fun_to_hc(fun);
    334         assert(hc);
    335 
    336         usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
    337             target.address, target.endpoint, size, max_packet_size);
    338 
    339         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    340             target.address, target.endpoint, USB_DIRECTION_OUT, NULL);
    341         if (ep == NULL) {
    342                 usb_log_error("Endpoint(%d:%d) not registered for BULK OUT.\n",
    343                         target.address, target.endpoint);
    344                 return ENOENT;
    345         }
    346         assert(ep->speed ==
    347             usb_device_keeper_get_speed(&hc->manager, target.address));
    348         assert(ep->max_packet_size == max_packet_size);
    349         assert(ep->transfer_type == USB_TRANSFER_BULK);
    350 
    351         usb_transfer_batch_t *batch =
    352             batch_get(fun, target, ep->transfer_type, ep->max_packet_size,
    353                 ep->speed, data, size, NULL, 0, NULL, callback, arg, ep);
    354         if (!batch)
    355                 return ENOMEM;
     259        usb_transfer_batch_t *batch = NULL;
     260        hc_t *hc = NULL;
     261        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     262            NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
     263        if (ret != EOK)
     264                return ret;
    356265        batch_bulk_out(batch);
    357         const int ret = hc_schedule(hc, batch);
     266        ret = hc_schedule(hc, batch);
    358267        if (ret != EOK) {
    359268                batch_dispose(batch);
     
    366275 * @param[in] fun DDF function that was called.
    367276 * @param[in] target USB device to write to.
    368  * @param[in] max_packet_size maximum size of data packet the device accepts
    369277 * @param[out] data Data destination.
    370278 * @param[in] size Size of data source.
     
    374282 */
    375283static int bulk_in(
    376     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     284    ddf_fun_t *fun, usb_target_t target, void *data,
    377285    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    378286{
    379         assert(fun);
    380         hc_t *hc = fun_to_hc(fun);
    381         assert(hc);
    382         usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
    383             target.address, target.endpoint, size, max_packet_size);
    384 
    385         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    386             target.address, target.endpoint, USB_DIRECTION_IN, NULL);
    387         if (ep == NULL) {
    388                 usb_log_error("Endpoint(%d:%d) not registered for BULK IN.\n",
    389                         target.address, target.endpoint);
    390                 return ENOENT;
    391         }
    392         assert(ep->speed ==
    393             usb_device_keeper_get_speed(&hc->manager, target.address));
    394         assert(ep->max_packet_size == max_packet_size);
    395         assert(ep->transfer_type == USB_TRANSFER_BULK);
    396 
    397         usb_transfer_batch_t *batch =
    398             batch_get(fun, target, ep->transfer_type, ep->max_packet_size,
    399                 ep->speed, data, size, NULL, 0, callback, NULL, arg, ep);
    400         if (!batch)
    401                 return ENOMEM;
     287        usb_transfer_batch_t *batch = NULL;
     288        hc_t *hc = NULL;
     289        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     290            NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
     291        if (ret != EOK)
     292                return ret;
    402293        batch_bulk_in(batch);
    403         const int ret = hc_schedule(hc, batch);
     294        ret = hc_schedule(hc, batch);
    404295        if (ret != EOK) {
    405296                batch_dispose(batch);
     
    412303 * @param[in] fun DDF function that was called.
    413304 * @param[in] target USB device to write to.
    414  * @param[in] max_packet_size maximum size of data packet the device accepts.
    415305 * @param[in] setup_data Data to send with SETUP transfer.
    416306 * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
     
    422312 */
    423313static int control_write(
    424     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     314    ddf_fun_t *fun, usb_target_t target,
    425315    void *setup_data, size_t setup_size, void *data, size_t size,
    426316    usbhc_iface_transfer_out_callback_t callback, void *arg)
    427317{
    428         assert(fun);
    429         hc_t *hc = fun_to_hc(fun);
    430         assert(hc);
    431         usb_speed_t speed =
    432             usb_device_keeper_get_speed(&hc->manager, target.address);
    433         usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n",
    434             speed, target.address, target.endpoint, size, max_packet_size);
    435         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    436             target.address, target.endpoint, USB_DIRECTION_BOTH, NULL);
    437         if (ep == NULL) {
    438                 usb_log_warning("Endpoint(%d:%d) not registered for CONTROL.\n",
    439                         target.address, target.endpoint);
    440         }
    441 
    442         if (setup_size != 8)
    443                 return EINVAL;
    444 
    445         usb_transfer_batch_t *batch =
    446             batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size, speed,
    447                 data, size, setup_data, setup_size, NULL, callback, arg, ep);
    448         if (!batch)
    449                 return ENOMEM;
    450         usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
     318        usb_transfer_batch_t *batch = NULL;
     319        hc_t *hc = NULL;
     320        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     321            setup_data, setup_size, NULL, callback, arg, "Control WRITE",
     322            &hc, &batch);
     323        if (ret != EOK)
     324                return ret;
     325        usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
    451326        batch_control_write(batch);
    452         const int ret = hc_schedule(hc, batch);
     327        ret = hc_schedule(hc, batch);
    453328        if (ret != EOK) {
    454329                batch_dispose(batch);
     
    461336 * @param[in] fun DDF function that was called.
    462337 * @param[in] target USB device to write to.
    463  * @param[in] max_packet_size maximum size of data packet the device accepts.
    464338 * @param[in] setup_data Data to send with SETUP packet.
    465339 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
     
    471345 */
    472346static int control_read(
    473     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     347    ddf_fun_t *fun, usb_target_t target,
    474348    void *setup_data, size_t setup_size, void *data, size_t size,
    475349    usbhc_iface_transfer_in_callback_t callback, void *arg)
    476350{
    477         assert(fun);
    478         hc_t *hc = fun_to_hc(fun);
    479         assert(hc);
    480         usb_speed_t speed =
    481             usb_device_keeper_get_speed(&hc->manager, target.address);
    482 
    483         usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n",
    484             speed, target.address, target.endpoint, size, max_packet_size);
    485         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    486             target.address, target.endpoint, USB_DIRECTION_BOTH, NULL);
    487         if (ep == NULL) {
    488                 usb_log_warning("Endpoint(%d:%d) not registered for CONTROL.\n",
    489                         target.address, target.endpoint);
    490         }
    491         usb_transfer_batch_t *batch =
    492             batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size, speed,
    493                 data, size, setup_data, setup_size, callback, NULL, arg, ep);
    494         if (!batch)
    495                 return ENOMEM;
     351        usb_transfer_batch_t *batch = NULL;
     352        hc_t *hc = NULL;
     353        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     354            setup_data, setup_size, callback, NULL, arg, "Control READ",
     355            &hc, &batch);
     356        if (ret != EOK)
     357                return ret;
    496358        batch_control_read(batch);
    497         const int ret = hc_schedule(hc, batch);
     359        ret = hc_schedule(hc, batch);
    498360        if (ret != EOK) {
    499361                batch_dispose(batch);
     
    503365/*----------------------------------------------------------------------------*/
    504366usbhc_iface_t hc_iface = {
    505         .reserve_default_address = reserve_default_address,
    506         .release_default_address = release_default_address,
    507367        .request_address = request_address,
    508368        .bind_address = bind_address,
  • uspace/drv/uhci-hcd/transfer_list.c

    ra49e171 rdc4c19e  
    132132}
    133133/*----------------------------------------------------------------------------*/
    134 /** Check list for finished batches.
    135  *
    136  * @param[in] instance List to use.
    137  * @return Error code
    138  *
    139  * Creates a local list of finished batches and calls next_step on each and
    140  * every one. This is safer because next_step may theoretically access
    141  * this transfer list leading to the deadlock if its done inline.
     134/** Create list for finished batches.
     135 *
     136 * @param[in] instance List to use.
     137 * @param[in] done list to fill
    142138 */
    143139void transfer_list_remove_finished(transfer_list_t *instance, link_t *done)
     
    161157        }
    162158        fibril_mutex_unlock(&instance->guard);
    163 
    164159}
    165160/*----------------------------------------------------------------------------*/
     
    176171                    list_get_instance(current, usb_transfer_batch_t, link);
    177172                transfer_list_remove_batch(instance, batch);
    178                 usb_transfer_batch_finish(batch, EIO);
     173                usb_transfer_batch_finish_error(batch, EIO);
    179174        }
    180175        fibril_mutex_unlock(&instance->guard);
  • uspace/drv/uhci-rhd/root_hub.h

    ra49e171 rdc4c19e  
    4040
    4141#define UHCI_ROOT_HUB_PORT_COUNT 2
    42 #define ROOT_HUB_WAIT_USEC 5000000 /* 5 seconds */
     42#define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */
    4343
    4444typedef struct root_hub {
  • uspace/drv/usbhub/Makefile

    ra49e171 rdc4c19e  
    3434SOURCES = \
    3535        main.c \
    36         ports.c \
    3736        utils.c \
    38         usbhub.c
     37        usbhub.c \
     38        ports.c
    3939
    4040include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/usbhub/port_status.h

    ra49e171 rdc4c19e  
    4949
    5050/**
     51 * structure holding hub status and changes flags.
     52 * should not be accessed directly, use supplied getter/setter methods.
     53 *
     54 * For more information refer to table 11.16.2.5 in
     55 * "Universal Serial Bus Specification Revision 1.1"
     56 *
     57 */
     58typedef uint32_t usb_hub_status_t;
     59
     60/**
    5161 * set values in request to be it a port status request
    5262 * @param request
     
    5464 */
    5565static inline void usb_hub_set_port_status_request(
    56 usb_device_request_setup_packet_t * request, uint16_t port
    57 ){
     66        usb_device_request_setup_packet_t * request, uint16_t port
     67        ) {
    5868        request->index = port;
    5969        request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS;
     
    6373}
    6474
     75/**
     76 * set values in request to be it a port status request
     77 * @param request
     78 * @param port
     79 */
     80static inline void usb_hub_set_hub_status_request(
     81        usb_device_request_setup_packet_t * request
     82        ) {
     83        request->index = 0;
     84        request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;
     85        request->request = USB_HUB_REQUEST_GET_STATUS;
     86        request->value = 0;
     87        request->length = 4;
     88}
    6589
    6690/**
     
    7094 */
    7195static inline usb_device_request_setup_packet_t *
    72 usb_hub_create_port_status_request(uint16_t port){
     96usb_hub_create_port_status_request(uint16_t port) {
    7397        usb_device_request_setup_packet_t * result =
    74                 usb_new(usb_device_request_setup_packet_t);
    75         usb_hub_set_port_status_request(result,port);
     98                malloc(sizeof(usb_device_request_setup_packet_t));
     99        usb_hub_set_port_status_request(result, port);
    76100        return result;
    77101}
    78102
    79 
    80103/**
    81104 * set the device request to be a port feature enable request
     
    85108 */
    86109static inline void usb_hub_set_enable_port_feature_request(
    87 usb_device_request_setup_packet_t * request, uint16_t port,
    88                 uint16_t feature_selector
    89 ){
     110        usb_device_request_setup_packet_t * request, uint16_t port,
     111        uint16_t feature_selector
     112        ) {
    90113        request->index = port;
    91114        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    102125 */
    103126static inline void usb_hub_set_disable_port_feature_request(
    104 usb_device_request_setup_packet_t * request, uint16_t port,
    105                 uint16_t feature_selector
    106 ){
     127        usb_device_request_setup_packet_t * request, uint16_t port,
     128        uint16_t feature_selector
     129        ) {
    107130        request->index = port;
    108131        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    118141 */
    119142static inline void usb_hub_set_enable_port_request(
    120 usb_device_request_setup_packet_t * request, uint16_t port
    121 ){
     143        usb_device_request_setup_packet_t * request, uint16_t port
     144        ) {
    122145        request->index = port;
    123146        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    133156 */
    134157static inline usb_device_request_setup_packet_t *
    135 usb_hub_create_enable_port_request(uint16_t port){
     158usb_hub_create_enable_port_request(uint16_t port) {
    136159        usb_device_request_setup_packet_t * result =
    137                 usb_new(usb_device_request_setup_packet_t);
    138         usb_hub_set_enable_port_request(result,port);
     160                malloc(sizeof(usb_device_request_setup_packet_t));
     161        usb_hub_set_enable_port_request(result, port);
    139162        return result;
    140163}
     
    146169 */
    147170static inline void usb_hub_set_disable_port_request(
    148 usb_device_request_setup_packet_t * request, uint16_t port
    149 ){
     171        usb_device_request_setup_packet_t * request, uint16_t port
     172        ) {
    150173        request->index = port;
    151174        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    161184 */
    162185static inline usb_device_request_setup_packet_t *
    163 usb_hub_create_disable_port_request(uint16_t port){
     186usb_hub_create_disable_port_request(uint16_t port) {
    164187        usb_device_request_setup_packet_t * result =
    165                 usb_new(usb_device_request_setup_packet_t);
    166         usb_hub_set_disable_port_request(result,port);
     188                malloc(sizeof(usb_device_request_setup_packet_t));
     189        usb_hub_set_disable_port_request(result, port);
    167190        return result;
    168191}
     
    174197 */
    175198static inline void usb_hub_set_reset_port_request(
    176 usb_device_request_setup_packet_t * request, uint16_t port
    177 ){
     199        usb_device_request_setup_packet_t * request, uint16_t port
     200        ) {
    178201        request->index = port;
    179202        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    189212 */
    190213static inline usb_device_request_setup_packet_t *
    191 usb_hub_create_reset_port_request(uint16_t port){
     214usb_hub_create_reset_port_request(uint16_t port) {
    192215        usb_device_request_setup_packet_t * result =
    193                 usb_new(usb_device_request_setup_packet_t);
    194         usb_hub_set_reset_port_request(result,port);
     216                malloc(sizeof(usb_device_request_setup_packet_t));
     217        usb_hub_set_reset_port_request(result, port);
    195218        return result;
    196219}
     
    202225 */
    203226static inline void usb_hub_set_power_port_request(
    204 usb_device_request_setup_packet_t * request, uint16_t port
    205 ){
     227        usb_device_request_setup_packet_t * request, uint16_t port
     228        ) {
    206229        request->index = port;
    207230        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    217240 */
    218241static inline void usb_hub_unset_power_port_request(
    219 usb_device_request_setup_packet_t * request, uint16_t port
    220 ){
     242        usb_device_request_setup_packet_t * request, uint16_t port
     243        ) {
    221244        request->index = port;
    222245        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    226249}
    227250
    228 
    229 /** get i`th bit of port status */
    230 static inline bool usb_port_get_bit(usb_port_status_t * status, int idx)
    231 {
    232         return (((*status)>>(idx))%2);
    233 }
    234 
    235 /** set i`th bit of port status */
    236 static inline void usb_port_set_bit(
    237         usb_port_status_t * status, int idx, bool value)
    238 {
    239         (*status) = value?
    240                                ((*status)|(1<<(idx))):
    241                                ((*status)&(~(1<<(idx))));
    242 }
    243 
    244 //device connnected on port
    245 static inline bool usb_port_dev_connected(usb_port_status_t * status){
    246         return usb_port_get_bit(status,0);
    247 }
    248 
    249 static inline void usb_port_set_dev_connected(usb_port_status_t * status,bool connected){
    250         usb_port_set_bit(status,0,connected);
     251/**
     252 * get i`th bit of port status
     253 *
     254 * @param status
     255 * @param idx
     256 * @return
     257 */
     258static inline bool usb_port_is_status(usb_port_status_t status, int idx) {
     259        return (status&(1 << idx))!=0;
     260}
     261
     262/**
     263 * set i`th bit of port status
     264 *
     265 * @param status
     266 * @param idx
     267 * @param value
     268 */
     269static inline void usb_port_status_set_bit(
     270        usb_port_status_t * status, int idx, bool value) {
     271        (*status) = value ?
     272                ((*status) | (1 << (idx))) :
     273                ((*status)&(~(1 << (idx))));
     274}
     275
     276/**
     277 * get i`th bit of hub status
     278 *
     279 * @param status
     280 * @param idx
     281 * @return
     282 */
     283static inline bool usb_hub_is_status(usb_hub_status_t status, int idx) {
     284        return (status&(1 << idx))!=0;
     285}
     286
     287/**
     288 * set i`th bit of hub status
     289 *
     290 * @param status
     291 * @param idx
     292 * @param value
     293 */
     294static inline void usb_hub_status_set_bit(
     295        usb_hub_status_t * status, int idx, bool value) {
     296        (*status) = value ?
     297                ((*status) | (1 << (idx))) :
     298                ((*status)&(~(1 << (idx))));
     299}
     300
     301
     302#if 0
     303/**
     304 * connection status geter for port status
     305 *
     306 * @param status
     307 * @return true if there is something connected
     308 */
     309static inline bool usb_port_dev_connected(usb_port_status_t * status) {
     310        return usb_port_get_bit(status, 0);
     311}
     312
     313/**
     314 * set device connected bit in port status
     315 *
     316 * @param status
     317 * @param connected value of the bit
     318 */
     319static inline void usb_port_set_dev_connected(usb_port_status_t * status, bool connected) {
     320        usb_port_set_bit(status, 0, connected);
    251321}
    252322
    253323//port enabled
    254 static inline bool usb_port_enabled(usb_port_status_t * status){
    255         return usb_port_get_bit(status,1);
    256 }
    257 
    258 static inline void usb_port_set_enabled(usb_port_status_t * status,bool enabled){
    259         usb_port_set_bit(status,1,enabled);
     324
     325/**
     326 * port enabled getter for port status
     327 *
     328 * @param status
     329 * @return true if the port is enabled
     330 */
     331static inline bool usb_port_enabled(usb_port_status_t * status) {
     332        return usb_port_get_bit(status, 1);
     333}
     334
     335/**
     336 * set port enabled bit in port status
     337 *
     338 * @param status
     339 * @param enabled value of the bit
     340 */
     341static inline void usb_port_set_enabled(usb_port_status_t * status, bool enabled) {
     342        usb_port_set_bit(status, 1, enabled);
    260343}
    261344
    262345//port suspended
    263 static inline bool usb_port_suspended(usb_port_status_t * status){
    264         return usb_port_get_bit(status,2);
    265 }
    266 
    267 static inline void usb_port_set_suspended(usb_port_status_t * status,bool suspended){
    268         usb_port_set_bit(status,2,suspended);
     346/**
     347 * port suspended getter for port status
     348 *
     349 * @param status
     350 * @return true if port is suspended
     351 */
     352static inline bool usb_port_suspended(usb_port_status_t * status) {
     353        return usb_port_get_bit(status, 2);
     354}
     355
     356/**
     357 * set port suspended bit in port status
     358 *
     359 * @param status
     360 * @param suspended value of the bit
     361 */
     362static inline void usb_port_set_suspended(usb_port_status_t * status, bool suspended) {
     363        usb_port_set_bit(status, 2, suspended);
    269364}
    270365
    271366//over currect
    272 static inline bool usb_port_over_current(usb_port_status_t * status){
    273         return usb_port_get_bit(status,3);
    274 }
    275 
    276 static inline void usb_port_set_over_current(usb_port_status_t * status,bool value){
    277         usb_port_set_bit(status,3,value);
     367/**
     368 * over current condition indicator getter for port status
     369 *
     370 * @param status
     371 * @return true if there is opver-current condition on the hub
     372 */
     373static inline bool usb_port_over_current(usb_port_status_t * status) {
     374        return usb_port_get_bit(status, 3);
     375}
     376
     377/**
     378 * set over current indicator bit in port status
     379 *
     380 * @param status
     381 * @param value value of the bit
     382 */
     383static inline void usb_port_set_over_current(usb_port_status_t * status, bool value) {
     384        usb_port_set_bit(status, 3, value);
    278385}
    279386
    280387//port reset
    281 static inline bool usb_port_reset(usb_port_status_t * status){
    282         return usb_port_get_bit(status,4);
    283 }
    284 
    285 static inline void usb_port_set_reset(usb_port_status_t * status,bool value){
    286         usb_port_set_bit(status,4,value);
     388/**
     389 * port reset indicator getter for port status
     390 *
     391 * @param status
     392 * @return true if port is reset
     393 */
     394static inline bool usb_port_reset(usb_port_status_t * status) {
     395        return usb_port_get_bit(status, 4);
     396}
     397
     398/**
     399 * set port reset bit in port status
     400 *
     401 * @param status
     402 * @param value value of the bit
     403 */
     404static inline void usb_port_set_reset(usb_port_status_t * status, bool value) {
     405        usb_port_set_bit(status, 4, value);
    287406}
    288407
    289408//powered
    290 static inline bool usb_port_powered(usb_port_status_t * status){
    291         return usb_port_get_bit(status,8);
    292 }
    293 
    294 static inline void usb_port_set_powered(usb_port_status_t * status,bool powered){
    295         usb_port_set_bit(status,8,powered);
    296 }
     409/**
     410 * power state getter for port status
     411 *
     412 * @param status
     413 * @return true if port is powered
     414 */
     415static inline bool usb_port_powered(usb_port_status_t * status) {
     416        return usb_port_get_bit(status, 8);
     417}
     418
     419/**
     420 * set port powered bit in port status
     421 *
     422 * @param status
     423 * @param powered value of the bit
     424 */
     425static inline void usb_port_set_powered(usb_port_status_t * status, bool powered) {
     426        usb_port_set_bit(status, 8, powered);
     427}
     428
     429#endif
    297430
    298431//low speed device attached
    299 static inline bool usb_port_low_speed(usb_port_status_t * status){
    300         return usb_port_get_bit(status,9);
    301 }
    302 
    303 static inline void usb_port_set_low_speed(usb_port_status_t * status,bool low_speed){
    304         usb_port_set_bit(status,9,low_speed);
    305 }
    306 
    307 //low speed device attached
    308 static inline bool usb_port_high_speed(usb_port_status_t * status){
    309         return usb_port_get_bit(status,10);
    310 }
    311 
    312 static inline void usb_port_set_high_speed(usb_port_status_t * status,bool high_speed){
    313         usb_port_set_bit(status,10,high_speed);
    314 }
    315 
    316 static inline usb_speed_t usb_port_speed(usb_port_status_t * status){
    317         if(usb_port_low_speed(status))
     432/**
     433 * low speed device on the port indicator
     434 *
     435 * @param status
     436 * @return true if low speed device is attached
     437 */
     438static inline bool usb_port_low_speed(usb_port_status_t status) {
     439        return usb_port_is_status(status, 9);
     440}
     441
     442/**
     443 * set low speed device connected bit in port status
     444 *
     445 * @param status
     446 * @param low_speed value of the bit
     447 */
     448static inline void usb_port_set_low_speed(usb_port_status_t * status, bool low_speed) {
     449        usb_port_status_set_bit(status, 9, low_speed);
     450}
     451
     452//high speed device attached
     453/**
     454 * high speed device on the port indicator
     455 *
     456 * @param status
     457 * @return true if high speed device is on port
     458 */
     459static inline bool usb_port_high_speed(usb_port_status_t status) {
     460        return usb_port_is_status(status, 10);
     461}
     462
     463/**
     464 * set high speed device bit in port status
     465 *
     466 * @param status
     467 * @param high_speed value of the bit
     468 */
     469static inline void usb_port_set_high_speed(usb_port_status_t * status, bool high_speed) {
     470        usb_port_status_set_bit(status, 10, high_speed);
     471}
     472
     473/**
     474 * speed getter for port status
     475 *
     476 * @param status
     477 * @return speed of usb device (for more see usb specification)
     478 */
     479static inline usb_speed_t usb_port_speed(usb_port_status_t status) {
     480        if (usb_port_low_speed(status))
    318481                return USB_SPEED_LOW;
    319         if(usb_port_high_speed(status))
     482        if (usb_port_high_speed(status))
    320483                return USB_SPEED_HIGH;
    321484        return USB_SPEED_FULL;
    322485}
    323486
    324 
     487#if 0
    325488//connect change
    326 static inline bool usb_port_connect_change(usb_port_status_t * status){
    327         return usb_port_get_bit(status,16);
    328 }
    329 
    330 static inline void usb_port_set_connect_change(usb_port_status_t * status,bool change){
    331         usb_port_set_bit(status,16,change);
     489/**
     490 * port connect change indicator
     491 *
     492 * @param status
     493 * @return true if connection has changed
     494 */
     495static inline bool usb_port_connect_change(usb_port_status_t * status) {
     496        return usb_port_get_bit(status, 16);
     497}
     498
     499/**
     500 * set connection change bit in port status
     501 * @param status
     502 * @param change value of the bit
     503 */
     504static inline void usb_port_set_connect_change(usb_port_status_t * status, bool change) {
     505        usb_port_set_bit(status, 16, change);
    332506}
    333507
    334508//port enable change
    335 static inline bool usb_port_enabled_change(usb_port_status_t * status){
    336         return usb_port_get_bit(status,17);
    337 }
    338 
    339 static inline void usb_port_set_enabled_change(usb_port_status_t * status,bool change){
    340         usb_port_set_bit(status,17,change);
     509/**
     510 * port enable change for port status
     511 *
     512 * @param status
     513 * @return true if the port has been enabled/disabled
     514 */
     515static inline bool usb_port_enabled_change(usb_port_status_t * status) {
     516        return usb_port_get_bit(status, 17);
     517}
     518
     519/**
     520 * set port enable change bit in port status
     521 *
     522 * @param status
     523 * @param change value of the bit
     524 */
     525static inline void usb_port_set_enabled_change(usb_port_status_t * status, bool change) {
     526        usb_port_set_bit(status, 17, change);
    341527}
    342528
    343529//suspend change
    344 static inline bool usb_port_suspend_change(usb_port_status_t * status){
    345         return usb_port_get_bit(status,18);
    346 }
    347 
    348 static inline void usb_port_set_suspend_change(usb_port_status_t * status,bool change){
    349         usb_port_set_bit(status,18,change);
     530/**
     531 * port suspend change for port status
     532 *
     533 * @param status
     534 * @return ture if suspend status has changed
     535 */
     536static inline bool usb_port_suspend_change(usb_port_status_t * status) {
     537        return usb_port_get_bit(status, 18);
     538}
     539
     540/**
     541 * set port suspend change bit in port status
     542 *
     543 * @param status
     544 * @param change value of the bit
     545 */
     546static inline void usb_port_set_suspend_change(usb_port_status_t * status, bool change) {
     547        usb_port_set_bit(status, 18, change);
    350548}
    351549
    352550//over current change
    353 static inline bool usb_port_overcurrent_change(usb_port_status_t * status){
    354         return usb_port_get_bit(status,19);
    355 }
    356 
    357 static inline void usb_port_set_overcurrent_change(usb_port_status_t * status,bool change){
    358         usb_port_set_bit(status,19,change);
     551/**
     552 * over current change indicator
     553 *
     554 * @param status
     555 * @return true if over-current condition on port has changed
     556 */
     557static inline bool usb_port_overcurrent_change(usb_port_status_t * status) {
     558        return usb_port_get_bit(status, 19);
     559}
     560
     561/**
     562 * set port over current change bit in port status
     563 *
     564 * @param status
     565 * @param change value of the bit
     566 */
     567static inline void usb_port_set_overcurrent_change(usb_port_status_t * status, bool change) {
     568        usb_port_set_bit(status, 19, change);
    359569}
    360570
    361571//reset change
    362 static inline bool usb_port_reset_completed(usb_port_status_t * status){
    363         return usb_port_get_bit(status,20);
    364 }
    365 
    366 static inline void usb_port_set_reset_completed(usb_port_status_t * status,bool completed){
    367         usb_port_set_bit(status,20,completed);
    368 }
    369 
     572/**
     573 * port reset change indicator
     574 * @param status
     575 * @return true if port has been reset
     576 */
     577static inline bool usb_port_reset_completed(usb_port_status_t * status) {
     578        return usb_port_get_bit(status, 20);
     579}
     580
     581/**
     582 * set port reset completed bit in port status
     583 *
     584 * @param status
     585 * @param change value of the bit
     586 */
     587static inline void usb_port_set_reset_completed(usb_port_status_t * status, bool completed) {
     588        usb_port_set_bit(status, 20, completed);
     589}
     590
     591//local power status
     592/**
     593 * local power lost indicator for hub status
     594 *
     595 * @param status
     596 * @return true if hub is not powered
     597 */
     598static inline bool usb_hub_local_power_lost(usb_hub_status_t * status) {
     599        return usb_hub_get_bit(status, 0);
     600}
     601
     602/**
     603 * set hub power lost bit in hub status
     604 *
     605 * @param status
     606 * @param change value of the bit
     607 */
     608static inline void usb_hub_set_local_power_lost(usb_port_status_t * status,
     609        bool power_lost) {
     610        usb_hub_set_bit(status, 0, power_lost);
     611}
     612
     613//over current ocndition
     614/**
     615 * hub over-current indicator
     616 *
     617 * @param status
     618 * @return true if over-current condition occurred on hub
     619 */
     620static inline bool usb_hub_over_current(usb_hub_status_t * status) {
     621        return usb_hub_get_bit(status, 1);
     622}
     623
     624/**
     625 * set hub over current bit in hub status
     626 *
     627 * @param status
     628 * @param change value of the bit
     629 */
     630static inline void usb_hub_set_over_current(usb_port_status_t * status,
     631        bool over_current) {
     632        usb_hub_set_bit(status, 1, over_current);
     633}
     634
     635//local power change
     636/**
     637 * hub power change indicator
     638 *
     639 * @param status
     640 * @return true if local power status has been changed - power has been
     641 * dropped or re-established
     642 */
     643static inline bool usb_hub_local_power_change(usb_hub_status_t * status) {
     644        return usb_hub_get_bit(status, 16);
     645}
     646
     647/**
     648 * set hub power change bit in hub status
     649 *
     650 * @param status
     651 * @param change value of the bit
     652 */
     653static inline void usb_hub_set_local_power_change(usb_port_status_t * status,
     654        bool change) {
     655        usb_hub_set_bit(status, 16, change);
     656}
     657
     658//local power status
     659/**
     660 * hub over-current condition change indicator
     661 *
     662 * @param status
     663 * @return true if over-current condition has changed
     664 */
     665static inline bool usb_hub_over_current_change(usb_hub_status_t * status) {
     666        return usb_hub_get_bit(status, 17);
     667}
     668
     669/**
     670 * set hub over current change bit in hub status
     671 *
     672 * @param status
     673 * @param change value of the bit
     674 */
     675static inline void usb_hub_set_over_current_change(usb_port_status_t * status,
     676        bool change) {
     677        usb_hub_set_bit(status, 17, change);
     678}
     679#endif
    370680
    371681
  • uspace/drv/usbhub/ports.c

    ra49e171 rdc4c19e  
    3333 * Hub ports functions.
    3434 */
    35 #include "port_status.h"
    36 #include <inttypes.h>
     35
     36#include <bool.h>
    3737#include <errno.h>
    3838#include <str_error.h>
    39 #include <usb/request.h>
     39#include <inttypes.h>
     40#include <fibril_synch.h>
     41
    4042#include <usb/debug.h>
     43
     44#include "ports.h"
     45#include "usbhub.h"
     46#include "usbhub_private.h"
     47#include "port_status.h"
     48
     49
     50/** Information for fibril for device discovery. */
     51struct add_device_phase1 {
     52        usb_hub_info_t *hub;
     53        size_t port;
     54        usb_speed_t speed;
     55};
     56
     57static void usb_hub_removed_device(
     58        usb_hub_info_t * hub, uint16_t port);
     59
     60static void usb_hub_port_reset_completed(usb_hub_info_t * hub,
     61        uint16_t port, uint32_t status);
     62
     63static void usb_hub_port_over_current(usb_hub_info_t * hub,
     64        uint16_t port, uint32_t status);
     65
     66static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
     67    usb_port_status_t *status);
     68
     69static int enable_port_callback(int port_no, void *arg);
     70
     71static int add_device_phase1_worker_fibril(void *arg);
     72
     73static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
     74    usb_speed_t speed);
     75
     76/**
     77 * Process interrupts on given hub port
     78 *
     79 * Accepts connection, over current and port reset change.
     80 * @param hub hub representation
     81 * @param port port number, starting from 1
     82 */
     83void usb_hub_process_interrupt(usb_hub_info_t * hub,
     84        uint16_t port) {
     85        usb_log_debug("interrupt at port %d\n", port);
     86        //determine type of change
     87        //usb_pipe_t *pipe = hub->control_pipe;
     88
     89        int opResult;
     90
     91        usb_port_status_t status;
     92        opResult = get_port_status(&hub->usb_device->ctrl_pipe, port, &status);
     93        if (opResult != EOK) {
     94                usb_log_error("Failed to get port %zu status: %s.\n",
     95                    port, str_error(opResult));
     96                return;
     97        }
     98        //connection change
     99        if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_CONNECTION)) {
     100                bool device_connected = usb_port_is_status(status,
     101                    USB_HUB_FEATURE_PORT_CONNECTION);
     102                usb_log_debug("Connection change on port %zu: %s.\n", port,
     103                    device_connected ? "device attached" : "device removed");
     104
     105                if (device_connected) {
     106                        opResult = create_add_device_fibril(hub, port,
     107                            usb_port_speed(status));
     108                        if (opResult != EOK) {
     109                                usb_log_error(
     110                                    "Cannot handle change on port %zu: %s.\n",
     111                                    str_error(opResult));
     112                        }
     113                } else {
     114                        usb_hub_removed_device(hub, port);
     115                }
     116        }
     117        //over current
     118        if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) {
     119                //check if it was not auto-resolved
     120                usb_log_debug("overcurrent change on port\n");
     121                usb_hub_port_over_current(hub, port, status);
     122        }
     123        //port reset
     124        if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_RESET)) {
     125                usb_hub_port_reset_completed(hub, port, status);
     126        }
     127        usb_log_debug("status x%x : %d\n ", status, status);
     128
     129        usb_port_status_set_bit(
     130            &status, USB_HUB_FEATURE_C_PORT_CONNECTION,false);
     131        usb_port_status_set_bit(
     132            &status, USB_HUB_FEATURE_PORT_RESET,false);
     133        usb_port_status_set_bit(
     134            &status, USB_HUB_FEATURE_C_PORT_RESET,false);
     135        usb_port_status_set_bit(
     136            &status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT,false);
     137        /// \TODO what about port power change?
     138        if (status >> 16) {
     139                usb_log_info("there was unsupported change on port %d: %X\n",
     140                        port, status);
     141
     142        }
     143}
     144
     145
     146/**
     147 * routine called when a device on port has been removed
     148 *
     149 * If the device on port had default address, it releases default address.
     150 * Otherwise does not do anything, because DDF does not allow to remove device
     151 * from it`s device tree.
     152 * @param hub hub representation
     153 * @param port port number, starting from 1
     154 */
     155static void usb_hub_removed_device(
     156        usb_hub_info_t * hub, uint16_t port) {
     157
     158        int opResult = usb_hub_clear_port_feature(hub->control_pipe,
     159                port, USB_HUB_FEATURE_C_PORT_CONNECTION);
     160        if (opResult != EOK) {
     161                usb_log_warning("could not clear port-change-connection flag\n");
     162        }
     163        /** \TODO remove device from device manager - not yet implemented in
     164         * devide manager
     165         */
     166
     167        //close address
     168        //if (hub->attached_devs[port].address != 0) {
     169        if(hub->ports[port].attached_device.address >= 0){
     170                /*uncomment this code to use it when DDF allows device removal
     171                opResult = usb_hc_unregister_device(
     172                        &hub->connection,
     173                        hub->attached_devs[port].address);
     174                if(opResult != EOK) {
     175                        dprintf(USB_LOG_LEVEL_WARNING, "could not release "
     176                                "address of "
     177                            "removed device: %d", opResult);
     178                }
     179                hub->attached_devs[port].address = 0;
     180                hub->attached_devs[port].handle = 0;
     181                 */
     182        } else {
     183                // TODO: is this really reason to print a warning?
     184                usb_log_warning("Device removed before being registered.\n");
     185
     186                /*
     187                 * Device was removed before port reset completed.
     188                 * We will announce a failed port reset to unblock the
     189                 * port reset callback from new device wrapper.
     190                 */
     191                usb_hub_port_t *the_port = hub->ports + port;
     192                fibril_mutex_lock(&the_port->reset_mutex);
     193                the_port->reset_completed = true;
     194                the_port->reset_okay = false;
     195                fibril_condvar_broadcast(&the_port->reset_cv);
     196                fibril_mutex_unlock(&the_port->reset_mutex);
     197        }
     198}
     199
     200
     201/**
     202 * Process port reset change
     203 *
     204 * After this change port should be enabled, unless some problem occured.
     205 * This functions triggers second phase of enabling new device.
     206 * @param hub
     207 * @param port
     208 * @param status
     209 */
     210static void usb_hub_port_reset_completed(usb_hub_info_t * hub,
     211        uint16_t port, uint32_t status){
     212        usb_log_debug("Port %zu reset complete.\n", port);
     213        if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_ENABLE)) {
     214                /* Finalize device adding. */
     215                usb_hub_port_t *the_port = hub->ports + port;
     216                fibril_mutex_lock(&the_port->reset_mutex);
     217                the_port->reset_completed = true;
     218                the_port->reset_okay = true;
     219                fibril_condvar_broadcast(&the_port->reset_cv);
     220                fibril_mutex_unlock(&the_port->reset_mutex);
     221        } else {
     222                usb_log_warning(
     223                    "Port %zu reset complete but port not enabled.\n",
     224                    port);
     225        }
     226}
     227
     228/**
     229 * Process over current condition on port.
     230 *
     231 * Turn off the power on the port.
     232 *
     233 * @param hub hub representation
     234 * @param port port number, starting from 1
     235 */
     236static void usb_hub_port_over_current(usb_hub_info_t * hub,
     237        uint16_t port, uint32_t status) {
     238        int opResult;
     239        if(usb_port_is_status(status, USB_HUB_FEATURE_PORT_OVER_CURRENT)){
     240                opResult = usb_hub_clear_port_feature(hub->control_pipe,
     241                        port, USB_HUB_FEATURE_PORT_POWER);
     242                if (opResult != EOK) {
     243                        usb_log_error("cannot power off port %d;  %d\n",
     244                                port, opResult);
     245                }
     246        }else{
     247                opResult = usb_hub_set_port_feature(hub->control_pipe,
     248                        port, USB_HUB_FEATURE_PORT_POWER);
     249                if (opResult != EOK) {
     250                        usb_log_error("cannot power on port %d;  %d\n",
     251                                port, opResult);
     252                }
     253        }
     254}
    41255
    42256/** Retrieve port status.
     
    73287}
    74288
    75 /** Information for fibril for device discovery. */
    76 struct add_device_phase1 {
    77         usb_hub_info_t *hub;
    78         size_t port;
    79         usb_speed_t speed;
    80 };
    81 
    82289/** Callback for enabling a specific port.
    83290 *
     
    91298static int enable_port_callback(int port_no, void *arg)
    92299{
    93         usb_hub_info_t *hub = (usb_hub_info_t *) arg;
     300        usb_hub_info_t *hub = arg;
    94301        int rc;
    95302        usb_device_request_setup_packet_t request;
     
    122329        }
    123330
    124         return EOK;
     331        if (my_port->reset_okay) {
     332                return EOK;
     333        } else {
     334                return ESTALL;
     335        }
    125336}
    126337
     
    156367        data->hub->ports[data->port].attached_device.address = new_address;
    157368
    158         usb_log_info("Detected new device on `%s' (port %zu), " \
     369        usb_log_info("Detected new device on `%s' (port %zu), "
    159370            "address %d (handle %" PRIun ").\n",
    160371            data->hub->usb_device->ddf_dev->name, data->port,
     
    166377        return EOK;
    167378}
     379
    168380
    169381/** Start device adding when connection change is detected.
     
    176388 * @return Error code.
    177389 */
    178 static int add_device_phase1_new_fibril(usb_hub_info_t *hub, size_t port,
     390static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
    179391    usb_speed_t speed)
    180392{
     
    213425}
    214426
    215 /** Process change on a single port.
    216  *
    217  * @param hub Hub to which the port belongs.
    218  * @param port Port index (starting at 1).
    219  */
    220 static void process_port_change(usb_hub_info_t *hub, size_t port)
    221 {
    222         int rc;
    223 
    224         usb_port_status_t port_status;
    225 
    226         rc = get_port_status(&hub->usb_device->ctrl_pipe, port, &port_status);
    227         if (rc != EOK) {
    228                 usb_log_error("Failed to get port %zu status: %s.\n",
    229                     port, str_error(rc));
    230                 return;
    231         }
    232 
    233         /*
    234          * Check exact nature of the change.
    235          */
    236         usb_log_debug("Port %zu change status: %x.\n", port,
    237             (unsigned int) port_status);
    238 
    239         if (usb_port_connect_change(&port_status)) {
    240                 bool device_connected = usb_port_dev_connected(&port_status);
    241                 usb_log_debug("Connection change on port %zu: %s.\n", port,
    242                     device_connected ? "device attached" : "device removed");
    243 
    244                 if (device_connected) {
    245                         rc = add_device_phase1_new_fibril(hub, port,
    246                             usb_port_speed(&port_status));
    247                         if (rc != EOK) {
    248                                 usb_log_error(
    249                                     "Cannot handle change on port %zu: %s.\n",
    250                                     str_error(rc));
    251                         }
    252                 } else {
    253                         usb_hub_removed_device(hub, port);
    254                 }
    255         }
    256 
    257         if (usb_port_overcurrent_change(&port_status)) {
    258                 if (usb_port_over_current(&port_status)) {
    259                         usb_log_warning("Overcurrent on port %zu.\n", port);
    260                         usb_hub_over_current(hub, port);
    261                 } else {
    262                         usb_log_debug("Overcurrent on port %zu autoresolved.\n",
    263                             port);
    264                 }
    265         }
    266 
    267         if (usb_port_reset_completed(&port_status)) {
    268                 usb_log_debug("Port %zu reset complete.\n", port);
    269                 if (usb_port_enabled(&port_status)) {
    270                         /* Finalize device adding. */
    271                         usb_hub_port_t *the_port = hub->ports + port;
    272                         fibril_mutex_lock(&the_port->reset_mutex);
    273                         the_port->reset_completed = true;
    274                         fibril_condvar_broadcast(&the_port->reset_cv);
    275                         fibril_mutex_unlock(&the_port->reset_mutex);
    276                 } else {
    277                         usb_log_warning(
    278                             "Port %zu reset complete but port not enabled.\n",
    279                             port);
    280                 }
    281         }
    282 
    283         usb_port_set_connect_change(&port_status, false);
    284         usb_port_set_reset(&port_status, false);
    285         usb_port_set_reset_completed(&port_status, false);
    286         usb_port_set_dev_connected(&port_status, false);
    287         if (port_status >> 16) {
    288                 usb_log_warning("Unsupported change on port %zu: %x.\n",
    289                     port, (unsigned int) port_status);
    290         }
    291 }
    292 
    293 
    294 /** Callback for polling hub for port changes.
    295  *
    296  * @param dev Device where the change occured.
    297  * @param change_bitmap Bitmap of changed ports.
    298  * @param change_bitmap_size Size of the bitmap in bytes.
    299  * @param arg Custom argument, points to @c usb_hub_info_t.
    300  * @return Whether to continue polling.
    301  */
    302 bool hub_port_changes_callback(usb_device_t *dev,
    303     uint8_t *change_bitmap, size_t change_bitmap_size, void *arg)
    304 {
    305         usb_hub_info_t *hub = (usb_hub_info_t *) arg;
    306 
    307         /* FIXME: check that we received enough bytes. */
    308         if (change_bitmap_size == 0) {
    309                 goto leave;
    310         }
    311 
    312         size_t port;
    313         for (port = 1; port < hub->port_count + 1; port++) {
    314                 bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;
    315                 if (change) {
    316                         process_port_change(hub, port);
    317                 }
    318         }
    319 
    320 
    321 leave:
    322         /* FIXME: proper interval. */
    323         async_usleep(1000 * 1000 * 10 );
    324 
    325         return true;
    326 }
    327 
    328 
    329427/**
    330428 * @}
  • uspace/drv/usbhub/ports.h

    ra49e171 rdc4c19e  
    3636#define DRV_USBHUB_PORTS_H
    3737
    38 #include <ipc/devman.h>
    39 #include <usb/usb.h>
    40 #include <ddf/driver.h>
    41 #include <fibril_synch.h>
    42 
     38#include <usb/devdrv.h>
    4339#include <usb/hub.h>
    4440
    45 #include <usb/pipes.h>
    46 #include <usb/devdrv.h>
     41typedef struct usb_hub_info_t usb_hub_info_t;
    4742
    4843/** Information about single port on a hub. */
     
    5651         */
    5752        bool reset_completed;
     53        /** Whether to announce the port reset as successful. */
     54        bool reset_okay;
    5855
    5956        /** Information about attached device. */
     
    7269}
    7370
    74 bool hub_port_changes_callback(usb_device_t *, uint8_t *, size_t, void *);
     71
     72void usb_hub_process_interrupt(usb_hub_info_t * hub,
     73        uint16_t port);
     74
    7575
    7676
  • uspace/drv/usbhub/usbhub.c

    ra49e171 rdc4c19e  
    3737#include <errno.h>
    3838#include <str_error.h>
     39#include <inttypes.h>
    3940
    4041#include <usb_iface.h>
     
    5354#include "usb/classes/classes.h"
    5455
    55 static int usb_hub_trigger_connecting_non_removable_devices(
    56                 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor);
    57 
     56
     57static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev);
     58
     59static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info);
     60
     61static int usb_hub_set_configuration(usb_hub_info_t * hub_info);
     62
     63static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info);
     64
     65static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     66    usb_hub_status_t status);
     67
     68static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
     69    usb_hub_status_t status);
     70
     71static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info);
     72
     73
     74/// \TODO malloc checking
    5875
    5976//*********************************************
    6077//
    6178//  hub driver code, initialization
     79//
     80//*********************************************
     81
     82/**
     83 * Initialize hub device driver fibril
     84 *
     85 * Creates hub representation and fibril that periodically checks hub`s status.
     86 * Hub representation is passed to the fibril.
     87 * @param usb_dev generic usb device information
     88 * @return error code
     89 */
     90int usb_hub_add_device(usb_device_t * usb_dev) {
     91        if (!usb_dev) return EINVAL;
     92        usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);
     93        //create hc connection
     94        usb_log_debug("Initializing USB wire abstraction.\n");
     95        int opResult = usb_hc_connection_initialize_from_device(
     96            &hub_info->connection,
     97            hub_info->usb_device->ddf_dev);
     98        if (opResult != EOK) {
     99                usb_log_error("could not initialize connection to device, "
     100                    "errno %d\n",
     101                    opResult);
     102                free(hub_info);
     103                return opResult;
     104        }
     105
     106        usb_pipe_start_session(hub_info->control_pipe);
     107        //set hub configuration
     108        opResult = usb_hub_set_configuration(hub_info);
     109        if (opResult != EOK) {
     110                usb_log_error("could not set hub configuration, errno %d\n",
     111                    opResult);
     112                free(hub_info);
     113                return opResult;
     114        }
     115        //get port count and create attached_devs
     116        opResult = usb_hub_process_hub_specific_info(hub_info);
     117        if (opResult != EOK) {
     118                usb_log_error("could process hub specific info, errno %d\n",
     119                    opResult);
     120                free(hub_info);
     121                return opResult;
     122        }
     123        usb_pipe_end_session(hub_info->control_pipe);
     124
     125        /// \TODO what is this?
     126        usb_log_debug("Creating `hub' function.\n");
     127        ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
     128            fun_exposed, "hub");
     129        assert(hub_fun != NULL);
     130        hub_fun->ops = NULL;
     131
     132        opResult = ddf_fun_bind(hub_fun);
     133        assert(opResult == EOK);
     134        opResult = ddf_fun_add_to_class(hub_fun, "hub");
     135        assert(opResult == EOK);
     136
     137        opResult = usb_hub_start_hub_fibril(hub_info);
     138        if(opResult!=EOK)
     139                free(hub_info);
     140        return opResult;
     141}
     142
     143
     144/** Callback for polling hub for changes.
     145 *
     146 * @param dev Device where the change occured.
     147 * @param change_bitmap Bitmap of changed ports.
     148 * @param change_bitmap_size Size of the bitmap in bytes.
     149 * @param arg Custom argument, points to @c usb_hub_info_t.
     150 * @return Whether to continue polling.
     151 */
     152bool hub_port_changes_callback(usb_device_t *dev,
     153    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) {
     154        usb_hub_info_t *hub = (usb_hub_info_t *) arg;
     155
     156        /* FIXME: check that we received enough bytes. */
     157        if (change_bitmap_size == 0) {
     158                goto leave;
     159        }
     160
     161        bool change;
     162        change = ((uint8_t*) change_bitmap)[0] & 1;
     163        if (change) {
     164                usb_hub_process_global_interrupt(hub);
     165        }
     166
     167        size_t port;
     168        for (port = 1; port < hub->port_count + 1; port++) {
     169                bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;
     170                if (change) {
     171                        usb_hub_process_interrupt(hub, port);
     172                }
     173        }
     174leave:
     175        /* FIXME: proper interval. */
     176        async_usleep(1000 * 1000 * 10);
     177
     178        return true;
     179}
     180
     181
     182//*********************************************
     183//
     184//  support functions
    62185//
    63186//*********************************************
     
    71194 */
    72195static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) {
    73         usb_hub_info_t * result = usb_new(usb_hub_info_t);
    74         if(!result) return NULL;
     196        usb_hub_info_t * result = malloc(sizeof(usb_hub_info_t));
     197        if (!result) return NULL;
    75198        result->usb_device = usb_dev;
    76199        result->status_change_pipe = usb_dev->pipes[0].pipe;
     
    90213 * @return error code
    91214 */
    92 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info){
     215static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) {
    93216        // get hub descriptor
    94217        usb_log_debug("creating serialized descriptor\n");
    95218        void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
    96219        usb_hub_descriptor_t * descriptor;
    97 
    98         /* this was one fix of some bug, should not be needed anymore
    99          * these lines allow to reset hub once more, it can be used as
    100          * brute-force initialization for non-removable devices
    101         int opResult = usb_request_set_configuration(&result->endpoints.control, 1);
    102         if(opResult!=EOK){
    103                 usb_log_error("could not set default configuration, errno %d",opResult);
    104                 return opResult;
    105         }
    106          */
     220        int opResult;
     221
    107222        size_t received_size;
    108         int opResult = usb_request_get_descriptor(&hub_info->usb_device->ctrl_pipe,
    109                         USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
    110                         USB_DESCTYPE_HUB,
    111                         0, 0, serialized_descriptor,
    112                         USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
    113 
    114         if (opResult != EOK) {
    115                 usb_log_error("failed when receiving hub descriptor, badcode = %d\n",
    116                                 opResult);
     223        opResult = usb_request_get_descriptor(hub_info->control_pipe,
     224            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
     225            USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
     226            USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
     227
     228        if (opResult != EOK) {
     229                usb_log_error("failed when receiving hub descriptor, "
     230                    "badcode = %d\n",
     231                    opResult);
    117232                free(serialized_descriptor);
    118233                return opResult;
     
    120235        usb_log_debug2("deserializing descriptor\n");
    121236        descriptor = usb_deserialize_hub_desriptor(serialized_descriptor);
    122         if(descriptor==NULL){
     237        if (descriptor == NULL) {
    123238                usb_log_warning("could not deserialize descriptor \n");
    124239                return opResult;
    125240        }
    126         usb_log_debug("setting port count to %d\n",descriptor->ports_count);
     241        usb_log_debug("setting port count to %d\n", descriptor->ports_count);
    127242        hub_info->port_count = descriptor->ports_count;
    128         hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1));
     243        /// \TODO this is not semantically correct
     244        hub_info->ports = malloc(
     245            sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
    129246        size_t port;
    130247        for (port = 0; port < hub_info->port_count + 1; port++) {
    131248                usb_hub_port_init(&hub_info->ports[port]);
    132249        }
    133         //handle non-removable devices
    134         usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor);
    135250        usb_log_debug2("freeing data\n");
    136251        free(serialized_descriptor);
     
    139254        return EOK;
    140255}
     256
    141257/**
    142258 * Set configuration of hub
     
    147263 * @return error code
    148264 */
    149 static int usb_hub_set_configuration(usb_hub_info_t * hub_info){
     265static int usb_hub_set_configuration(usb_hub_info_t * hub_info) {
    150266        //device descriptor
    151267        usb_standard_device_descriptor_t *std_descriptor
     
    153269        usb_log_debug("hub has %d configurations\n",
    154270            std_descriptor->configuration_count);
    155         if(std_descriptor->configuration_count<1){
     271        if (std_descriptor->configuration_count < 1) {
    156272                usb_log_error("there are no configurations available\n");
    157273                return EINVAL;
     
    173289        }
    174290        usb_log_debug("\tused configuration %d\n",
    175                         config_descriptor->configuration_number);
     291            config_descriptor->configuration_number);
    176292
    177293        return EOK;
     
    179295
    180296/**
    181  * Initialize hub device driver fibril
    182  *
    183  * Creates hub representation and fibril that periodically checks hub`s status.
    184  * Hub representation is passed to the fibril.
    185  * @param usb_dev generic usb device information
    186  * @return error code
    187  */
    188 int usb_hub_add_device(usb_device_t * usb_dev){
    189         if(!usb_dev) return EINVAL;
    190         usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);
    191         //create hc connection
    192         usb_log_debug("Initializing USB wire abstraction.\n");
    193         int opResult = usb_hc_connection_initialize_from_device(
    194                         &hub_info->connection,
    195                         hub_info->usb_device->ddf_dev);
    196         if(opResult != EOK){
    197                 usb_log_error("could not initialize connection to device, errno %d\n",
    198                                 opResult);
    199                 free(hub_info);
    200                 return opResult;
    201         }
    202        
    203         usb_pipe_start_session(hub_info->control_pipe);
    204         //set hub configuration
    205         opResult = usb_hub_set_configuration(hub_info);
    206         if(opResult!=EOK){
    207                 usb_log_error("could not set hub configuration, errno %d\n",opResult);
    208                 free(hub_info);
    209                 return opResult;
    210         }
    211         //get port count and create attached_devs
    212         opResult = usb_hub_process_hub_specific_info(hub_info);
    213         if(opResult!=EOK){
    214                 usb_log_error("could not set hub configuration, errno %d\n",opResult);
    215                 free(hub_info);
    216                 return opResult;
    217         }
    218         usb_pipe_end_session(hub_info->control_pipe);
    219 
    220 
    221         /// \TODO what is this?
    222         usb_log_debug("Creating `hub' function.\n");
    223         ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
    224                         fun_exposed, "hub");
    225         assert(hub_fun != NULL);
    226         hub_fun->ops = NULL;
    227 
    228         int rc = ddf_fun_bind(hub_fun);
    229         assert(rc == EOK);
    230         rc = ddf_fun_add_to_class(hub_fun, "hub");
    231         assert(rc == EOK);
    232 
     297 * create and start fibril with hub control loop
     298 *
     299 * Before the fibril is started, the control pipe and host controller
     300 * connection of the hub is open.
     301 *
     302 * @param hub_info hub representing structure
     303 * @return error code
     304 */
     305static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info){
    233306        /*
    234307         * The processing will require opened control pipe and connection
     
    239312         * auto destruction, this could work better.
    240313         */
    241         rc = usb_pipe_start_session(&usb_dev->ctrl_pipe);
     314        int rc = usb_pipe_start_session(hub_info->control_pipe);
    242315        if (rc != EOK) {
    243316                usb_log_error("Failed to start session on control pipe: %s.\n",
    244317                    str_error(rc));
    245                 goto leave;
     318                return rc;
    246319        }
    247320        rc = usb_hc_connection_open(&hub_info->connection);
    248321        if (rc != EOK) {
    249                 usb_pipe_end_session(&usb_dev->ctrl_pipe);
     322                usb_pipe_end_session(hub_info->control_pipe);
    250323                usb_log_error("Failed to open connection to HC: %s.\n",
    251324                    str_error(rc));
    252                 goto leave;
     325                return rc;
    253326        }
    254327
    255328        rc = usb_device_auto_poll(hub_info->usb_device, 0,
    256             hub_port_changes_callback, ((hub_info->port_count+1) / 8) + 1,
     329            hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
    257330            NULL, hub_info);
    258331        if (rc != EOK) {
     
    266339            hub_info->usb_device->ddf_dev->name, hub_info->port_count);
    267340        return EOK;
    268 
    269 leave:
    270         free(hub_info);
    271 
    272         return rc;
    273 }
    274 
    275 
    276 //*********************************************
    277 //
    278 //  hub driver code, main loop and port handling
    279 //
    280 //*********************************************
    281 
    282 /**
    283  * triggers actions to connect non0removable devices
    284  *
    285  * This will trigger operations leading to activated non-removable device.
    286  * Control pipe of the hub must be open fo communication.
    287  * @param hub hub representation
    288  * @param descriptor usb hub descriptor
    289  * @return error code
    290  */
    291 static int usb_hub_trigger_connecting_non_removable_devices(usb_hub_info_t * hub,
    292                 usb_hub_descriptor_t * descriptor)
    293 {
    294         usb_log_info("attaching non-removable devices(if any)\n");
    295         usb_device_request_setup_packet_t request;
     341}
     342
     343//*********************************************
     344//
     345//  change handling functions
     346//
     347//*********************************************
     348
     349
     350/**
     351 * process hub over current change
     352 *
     353 * This means either to power off the hub or power it on.
     354 * @param hub_info hub instance
     355 * @param status hub status bitmask
     356 * @return error code
     357 */
     358static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     359    usb_hub_status_t status) {
    296360        int opResult;
    297         size_t rcvd_size;
    298         usb_port_status_t status;
    299         uint8_t * non_removable_dev_bitmap = descriptor->devices_removable;
    300         int port;
    301         for(port=1;port<=descriptor->ports_count;++port){
    302                 bool is_non_removable =
    303                                 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2;
    304                 if(is_non_removable){
    305                         usb_log_debug("non-removable device on port %d\n",port);
    306                         usb_hub_set_port_status_request(&request, port);
    307                         opResult = usb_pipe_control_read(
    308                                         hub->control_pipe,
    309                                         &request, sizeof(usb_device_request_setup_packet_t),
    310                                         &status, 4, &rcvd_size
    311                                         );
     361        if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_OVER_CURRENT)){
     362                opResult = usb_hub_clear_feature(hub_info->control_pipe,
     363                    USB_HUB_FEATURE_HUB_LOCAL_POWER);
     364                if (opResult != EOK) {
     365                        usb_log_error("cannot power off hub: %d\n",
     366                            opResult);
     367                }
     368        } else {
     369                opResult = usb_hub_set_feature(hub_info->control_pipe,
     370                    USB_HUB_FEATURE_HUB_LOCAL_POWER);
     371                if (opResult != EOK) {
     372                        usb_log_error("cannot power on hub: %d\n",
     373                            opResult);
     374                }
     375        }
     376        return opResult;
     377}
     378
     379/**
     380 * process hub power change
     381 *
     382 * If the power has been lost, reestablish it.
     383 * If it was reestablished, re-power all ports.
     384 * @param hub_info hub instance
     385 * @param status hub status bitmask
     386 * @return error code
     387 */
     388static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
     389    usb_hub_status_t status) {
     390        int opResult;
     391        if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_LOCAL_POWER)) {
     392                //restart power on hub
     393                opResult = usb_hub_set_feature(hub_info->control_pipe,
     394                    USB_HUB_FEATURE_HUB_LOCAL_POWER);
     395                if (opResult != EOK) {
     396                        usb_log_error("cannot power on hub: %d\n",
     397                            opResult);
     398                }
     399        } else {//power reestablished on hub- restart ports
     400                size_t port;
     401                for (port = 0; port < hub_info->port_count; ++port) {
     402                        opResult = usb_hub_set_port_feature(
     403                            hub_info->control_pipe,
     404                            port, USB_HUB_FEATURE_PORT_POWER);
    312405                        if (opResult != EOK) {
    313                                 usb_log_error("could not get port status of port %d errno:%d\n",
    314                                                 port, opResult);
    315                                 return opResult;
    316                         }
    317                         //set the status change bit, so it will be noticed in driver loop
    318                         if(usb_port_dev_connected(&status)){
    319                                 usb_hub_set_disable_port_feature_request(&request, port,
    320                                                 USB_HUB_FEATURE_PORT_CONNECTION);
    321                                 opResult = usb_pipe_control_read(
    322                                                 hub->control_pipe,
    323                                                 &request, sizeof(usb_device_request_setup_packet_t),
    324                                                 &status, 4, &rcvd_size
    325                                                 );
    326                                 if (opResult != EOK) {
    327                                         usb_log_warning(
    328                                                         "could not clear port connection on port %d errno:%d\n",
    329                                                         port, opResult);
    330                                 }
    331                                 usb_log_debug("cleared port connection\n");
    332                                 usb_hub_set_enable_port_feature_request(&request, port,
    333                                                 USB_HUB_FEATURE_PORT_ENABLE);
    334                                 opResult = usb_pipe_control_read(
    335                                                 hub->control_pipe,
    336                                                 &request, sizeof(usb_device_request_setup_packet_t),
    337                                                 &status, 4, &rcvd_size
    338                                                 );
    339                                 if (opResult != EOK) {
    340                                         usb_log_warning(
    341                                                         "could not set port enabled on port %d errno:%d\n",
    342                                                         port, opResult);
    343                                 }
    344                                 usb_log_debug("port set to enabled - should lead to connection change\n");
     406                                usb_log_error("cannot power on port %d;  %d\n",
     407                                    port, opResult);
    345408                        }
    346409                }
    347410        }
    348         /// \TODO this is just a debug code
    349         for(port=1;port<=descriptor->ports_count;++port){
    350                 bool is_non_removable =
    351                                 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2;
    352                 if(is_non_removable){
    353                         usb_log_debug("port %d is non-removable\n",port);
    354                         usb_port_status_t status;
    355                         size_t rcvd_size;
    356                         usb_device_request_setup_packet_t request;
    357                         //int opResult;
    358                         usb_hub_set_port_status_request(&request, port);
    359                         //endpoint 0
    360                         opResult = usb_pipe_control_read(
    361                                         hub->control_pipe,
    362                                         &request, sizeof(usb_device_request_setup_packet_t),
    363                                         &status, 4, &rcvd_size
    364                                         );
    365                         if (opResult != EOK) {
    366                                 usb_log_error("could not get port status %d\n",opResult);
    367                         }
    368                         if (rcvd_size != sizeof (usb_port_status_t)) {
    369                                 usb_log_error("received status has incorrect size\n");
    370                         }
    371                         //something connected/disconnected
    372                         if (usb_port_connect_change(&status)) {
    373                                 usb_log_debug("some connection changed\n");
    374                         }
    375                         usb_log_debug("status: %s\n",usb_debug_str_buffer(
    376                                         (uint8_t *)&status,4,4));
    377                 }
    378         }
    379         return EOK;
    380 }
    381 
    382 
    383 /**
    384  * release default address used by given hub
    385  *
    386  * Also unsets hub->is_default_address_used. Convenience wrapper function.
    387  * @note hub->connection MUST be open for communication
    388  * @param hub hub representation
    389  * @return error code
    390  */
    391 static int usb_hub_release_default_address(usb_hub_info_t * hub){
    392         int opResult = usb_hc_release_default_address(&hub->connection);
    393         if(opResult!=EOK){
    394                 usb_log_error("could not release default address, errno %d\n",opResult);
    395                 return opResult;
    396         }
    397         hub->is_default_address_used = false;
    398         return EOK;
    399 }
    400 
    401 /**
    402  * routine called when a device on port has been removed
    403  *
    404  * If the device on port had default address, it releases default address.
    405  * Otherwise does not do anything, because DDF does not allow to remove device
    406  * from it`s device tree.
    407  * @param hub hub representation
    408  * @param port port number, starting from 1
    409  */
    410 void usb_hub_removed_device(
    411     usb_hub_info_t * hub,uint16_t port) {
    412 
    413         int opResult = usb_hub_clear_port_feature(hub->control_pipe,
    414                                 port, USB_HUB_FEATURE_C_PORT_CONNECTION);
    415         if(opResult != EOK){
    416                 usb_log_warning("could not clear port-change-connection flag\n");
    417         }
    418         /** \TODO remove device from device manager - not yet implemented in
    419          * devide manager
    420          */
    421        
    422         //close address
    423         if(hub->ports[port].attached_device.address >= 0){
    424                 /*uncomment this code to use it when DDF allows device removal
    425                 opResult = usb_hc_unregister_device(
    426                                 &hub->connection, hub->attached_devs[port].address);
    427                 if(opResult != EOK) {
    428                         dprintf(USB_LOG_LEVEL_WARNING, "could not release address of " \
    429                             "removed device: %d", opResult);
    430                 }
    431                 hub->attached_devs[port].address = 0;
    432                 hub->attached_devs[port].handle = 0;
    433                  */
    434         }else{
    435                 usb_log_warning("this is strange, disconnected device had no address\n");
    436                 //device was disconnected before it`s port was reset - return default address
    437                 usb_hub_release_default_address(hub);
    438         }
    439 }
    440 
    441 
    442 /**
    443  * Process over current condition on port.
    444  *
    445  * Turn off the power on the port.
    446  *
    447  * @param hub hub representation
    448  * @param port port number, starting from 1
    449  */
    450 void usb_hub_over_current( usb_hub_info_t * hub,
    451                 uint16_t port){
     411        return opResult;
     412}
     413
     414/**
     415 * process hub interrupts
     416 *
     417 * The change can be either in the over-current condition or
     418 * local-power lost condition.
     419 * @param hub_info hub instance
     420 */
     421static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info) {
     422        usb_log_debug("global interrupt on a hub\n");
     423        usb_pipe_t *pipe = hub_info->control_pipe;
    452424        int opResult;
    453         opResult = usb_hub_clear_port_feature(hub->control_pipe,
    454             port, USB_HUB_FEATURE_PORT_POWER);
    455         if(opResult!=EOK){
    456                 usb_log_error("cannot power off port %d;  %d\n",
    457                                 port, opResult);
    458         }
    459 }
    460 
     425
     426        usb_port_status_t status;
     427        size_t rcvd_size;
     428        usb_device_request_setup_packet_t request;
     429        //int opResult;
     430        usb_hub_set_hub_status_request(&request);
     431        //endpoint 0
     432
     433        opResult = usb_pipe_control_read(
     434            pipe,
     435            &request, sizeof (usb_device_request_setup_packet_t),
     436            &status, 4, &rcvd_size
     437            );
     438        if (opResult != EOK) {
     439                usb_log_error("could not get hub status\n");
     440                return;
     441        }
     442        if (rcvd_size != sizeof (usb_port_status_t)) {
     443                usb_log_error("received status has incorrect size\n");
     444                return;
     445        }
     446        //port reset
     447        if (
     448            usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {
     449                usb_process_hub_over_current(hub_info, status);
     450        }
     451        if (
     452            usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {
     453                usb_process_hub_power_change(hub_info, status);
     454        }
     455}
    461456
    462457/**
  • uspace/drv/usbhub/usbhub.h

    ra49e171 rdc4c19e  
    3737
    3838#include <ipc/devman.h>
    39 #include <usb/usb.h>
    4039#include <ddf/driver.h>
    4140
    42 #define NAME "usbhub"
    43 
    4441#include <usb/hub.h>
     42#include <usb/classes/hub.h>
    4543
    4644#include <usb/pipes.h>
    4745#include <usb/devdrv.h>
     46
     47#include <fibril_synch.h>
     48
     49#define NAME "usbhub"
    4850
    4951#include "ports.h"
     
    5254
    5355/** Information about attached hub. */
    54 typedef struct {
     56struct usb_hub_info_t{
    5557        /** Number of ports. */
    5658        size_t port_count;
    5759
    58         /** Ports. */
     60        /** attached device handles, for each port one */
    5961        usb_hub_port_t *ports;
    60        
     62
    6163        /** connection to hcd */
    6264        usb_hc_connection_t connection;
     
    8789        /** generic usb device data*/
    8890        usb_device_t * usb_device;
    89 } usb_hub_info_t;
     91};
    9092
    91 /**
    92  * function running the hub-controlling loop.
    93  * @param hub_info_param hub info pointer
    94  */
    95 int usb_hub_control_loop(void * hub_info_param);
    96 
    97 /**
    98  * Check changes on specified hub
    99  * @param hub_info_param pointer to usb_hub_info_t structure
    100  * @return error code if there is problem when initializing communication with
    101  * hub, EOK otherwise
    102  */
    103 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
    104 
    105 void usb_hub_removed_device(usb_hub_info_t *, uint16_t);
    106 void usb_hub_over_current(usb_hub_info_t *, uint16_t);
     93//int usb_hub_control_loop(void * hub_info_param);
    10794
    10895int usb_hub_add_device(usb_device_t * usb_dev);
     96
     97bool hub_port_changes_callback(usb_device_t *dev,
     98    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);
    10999
    110100#endif
  • uspace/drv/usbhub/usbhub_private.h

    ra49e171 rdc4c19e  
    5454//
    5555//************
    56 #define usb_new(type) (type*)malloc(sizeof(type))
    5756
    5857
    59 /**
    60  * Create hub structure instance
    61  *
    62  * Set the address and port count information most importantly.
    63  *
    64  * @param device
    65  * @param hc host controller phone
    66  * @return
    67  */
    6858usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device);
    6959
     
    110100
    111101/**
     102 * Clear feature on hub port.
     103 *
     104 * @param hc Host controller telephone
     105 * @param address Hub address
     106 * @param port_index Port
     107 * @param feature Feature selector
     108 * @return Operation result
     109 */
     110static inline int usb_hub_set_port_feature(usb_pipe_t *pipe,
     111    int port_index,
     112    usb_hub_class_feature_t feature) {
     113
     114        usb_device_request_setup_packet_t clear_request = {
     115                .request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
     116                .request = USB_DEVREQ_SET_FEATURE,
     117                .length = 0,
     118                .index = port_index
     119        };
     120        clear_request.value = feature;
     121        return usb_pipe_control_write(pipe, &clear_request,
     122            sizeof(clear_request), NULL, 0);
     123}
     124
     125
     126/**
     127 * Clear feature on hub port.
     128 *
     129 * @param pipe pipe to hub control endpoint
     130 * @param feature Feature selector
     131 * @return Operation result
     132 */
     133static inline int usb_hub_clear_feature(usb_pipe_t *pipe,
     134    usb_hub_class_feature_t feature) {
     135
     136        usb_device_request_setup_packet_t clear_request = {
     137                .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
     138                .request = USB_DEVREQ_CLEAR_FEATURE,
     139                .length = 0,
     140                .index = 0
     141        };
     142        clear_request.value = feature;
     143        return usb_pipe_control_write(pipe, &clear_request,
     144            sizeof(clear_request), NULL, 0);
     145}
     146
     147/**
     148 * Clear feature on hub port.
     149 *
     150 * @param pipe pipe to hub control endpoint
     151 * @param feature Feature selector
     152 * @return Operation result
     153 */
     154static inline int usb_hub_set_feature(usb_pipe_t *pipe,
     155    usb_hub_class_feature_t feature) {
     156
     157        usb_device_request_setup_packet_t clear_request = {
     158                .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
     159                .request = USB_DEVREQ_SET_FEATURE,
     160                .length = 0,
     161                .index = 0
     162        };
     163        clear_request.value = feature;
     164        return usb_pipe_control_write(pipe, &clear_request,
     165            sizeof(clear_request), NULL, 0);
     166}
     167
     168/**
    112169 * create uint8_t array with serialized descriptor
    113170 *
  • uspace/drv/usbhub/utils.c

    ra49e171 rdc4c19e  
    6060        size_t size = 7;
    6161        //variable size according to port count
    62         size_t var_size = descriptor->ports_count / 8 + ((descriptor->ports_count % 8 > 0) ? 1 : 0);
     62        size_t var_size = (descriptor->ports_count+7)/8;
    6363        size += 2 * var_size;
    64         uint8_t * result = (uint8_t*) malloc(size);
     64        uint8_t * result = malloc(size);
    6565        //size
    6666        result[0] = size;
     
    8484}
    8585
    86 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * serialized_descriptor) {
    87         uint8_t * sdescriptor = (uint8_t*) serialized_descriptor;
     86usb_hub_descriptor_t * usb_deserialize_hub_desriptor(
     87void * serialized_descriptor) {
     88        uint8_t * sdescriptor = serialized_descriptor;
    8889
    8990        if (sdescriptor[1] != USB_DESCTYPE_HUB) {
    90                 usb_log_warning("trying to deserialize wrong descriptor %x\n",sdescriptor[1]);
     91                usb_log_warning("trying to deserialize wrong descriptor %x\n",
     92                    sdescriptor[1]);
    9193                return NULL;
    9294        }
    9395
    94         usb_hub_descriptor_t * result = usb_new(usb_hub_descriptor_t);
     96        usb_hub_descriptor_t * result = malloc(sizeof(usb_hub_descriptor_t));
    9597       
    9698
     
    100102        result->pwr_on_2_good_time = sdescriptor[5];
    101103        result->current_requirement = sdescriptor[6];
    102         size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0)
    103                         ? 1 : 0);
     104        size_t var_size = (result->ports_count+7) / 8;
    104105        result->devices_removable = (uint8_t*) malloc(var_size);
    105106
  • uspace/drv/usbmid/main.c

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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,
     
    328324}
    329325
    330 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t ignored)
    331 {
    332         usb_address_keeping_reserve_default(&addresses);
    333         return EOK;
    334 }
    335 
    336 static int release_default_address(ddf_fun_t *fun)
    337 {
    338         usb_address_keeping_release_default(&addresses);
    339         return EOK;
    340 }
    341 
    342326static int request_address(ddf_fun_t *fun, usb_speed_t ignored,
    343327    usb_address_t *address)
     
    392376
    393377usbhc_iface_t vhc_iface = {
    394         .reserve_default_address = reserve_default_address,
    395         .release_default_address = release_default_address,
    396378        .request_address = request_address,
    397379        .bind_address = bind_address,
  • uspace/lib/drv/generic/remote_usbhc.c

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

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

    ra49e171 rdc4c19e  
    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/classes/hub.h

    ra49e171 rdc4c19e  
    4343 */
    4444typedef enum {
     45        USB_HUB_FEATURE_HUB_LOCAL_POWER = 0,
     46        USB_HUB_FEATURE_HUB_OVER_CURRENT = 1,
    4547        USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0,
    4648        USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1,
     
    5961        /* USB_HUB_FEATURE_ = , */
    6062} usb_hub_class_feature_t;
     63
    6164
    6265/** Header of standard hub descriptor without the "variadic" part. */
  • uspace/lib/usb/include/usb/devdrv.h

    ra49e171 rdc4c19e  
    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/batch.h

    ra49e171 rdc4c19e  
    9292void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
    9393void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
    94 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error);
     94void usb_transfer_batch_finish(usb_transfer_batch_t *instance);
     95
     96static inline void usb_transfer_batch_finish_error(
     97    usb_transfer_batch_t *instance, int error)
     98{
     99        assert(instance);
     100        instance->error = error;
     101        usb_transfer_batch_finish(instance);
     102}
    95103
    96104#endif
  • uspace/lib/usb/include/usb/host/device_keeper.h

    ra49e171 rdc4c19e  
    7171void usb_device_keeper_init(usb_device_keeper_t *instance);
    7272
    73 void usb_device_keeper_add_ep(
    74     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);
    75 
    7673void usb_device_keeper_reserve_default_address(
    7774    usb_device_keeper_t *instance, usb_speed_t speed);
     
    9693usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance,
    9794    usb_address_t address);
    98 
    99 void usb_device_keeper_use_control(usb_device_keeper_t *instance,
    100     usb_target_t target);
    101 
    102 void usb_device_keeper_release_control(usb_device_keeper_t *instance,
    103     usb_target_t target);
    104 
    10595#endif
    10696/**
  • uspace/lib/usb/include/usb/host/endpoint.h

    ra49e171 rdc4c19e  
    3939#include <bool.h>
    4040#include <adt/list.h>
     41#include <fibril_synch.h>
     42
    4143#include <usb/usb.h>
    4244
     
    4850        usb_speed_t speed;
    4951        size_t max_packet_size;
    50         bool active;
    5152        unsigned toggle:1;
    52         link_t same_device_eps;
     53        fibril_mutex_t guard;
     54        fibril_condvar_t avail;
     55        volatile bool active;
    5356} endpoint_t;
    5457
     
    5962void endpoint_destroy(endpoint_t *instance);
    6063
     64void endpoint_use(endpoint_t *instance);
     65
     66void endpoint_release(endpoint_t *instance);
     67
    6168int endpoint_toggle_get(endpoint_t *instance);
    6269
    6370void endpoint_toggle_set(endpoint_t *instance, int toggle);
    6471
    65 void endpoint_toggle_reset(link_t *ep);
    66 
    67 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn);
    68 
     72void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target);
    6973#endif
    7074/**
  • uspace/lib/usb/include/usb/host/usb_endpoint_manager.h

    ra49e171 rdc4c19e  
    7878    size_t *bw);
    7979
     80void usb_endpoint_manager_reset_if_need(
     81    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
    8082#endif
    8183/**
  • uspace/lib/usb/include/usb/hub.h

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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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;
     
    7979        instance->error = EOK;
    8080        instance->ep = ep;
     81        endpoint_use(instance->ep);
    8182}
    8283/*----------------------------------------------------------------------------*/
     
    8687 *
    8788 */
    88 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error)
     89void usb_transfer_batch_finish(usb_transfer_batch_t *instance)
    8990{
    9091        assert(instance);
    91         instance->error = error;
     92        assert(instance->ep);
     93        endpoint_release(instance->ep);
    9294        instance->next_step(instance);
    9395}
  • uspace/lib/usb/src/host/device_keeper.c

    ra49e171 rdc4c19e  
    5454        for (; i < USB_ADDRESS_COUNT; ++i) {
    5555                instance->devices[i].occupied = false;
    56                 instance->devices[i].control_used = 0;
    5756                instance->devices[i].handle = 0;
    58                 list_initialize(&instance->devices[i].endpoints);
     57                instance->devices[i].speed = USB_SPEED_MAX;
    5958        }
    60 }
    61 /*----------------------------------------------------------------------------*/
    62 void usb_device_keeper_add_ep(
    63     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep)
    64 {
    65         assert(instance);
    66         fibril_mutex_lock(&instance->guard);
    67         assert(instance->devices[address].occupied);
    68         list_append(&ep->same_device_eps, &instance->devices[address].endpoints);
    69         fibril_mutex_unlock(&instance->guard);
     59        // TODO: is this hack enough?
     60        // (it is needed to allow smooth registration at default address)
     61        instance->devices[0].occupied = true;
    7062}
    7163/*----------------------------------------------------------------------------*/
     
    10294}
    10395/*----------------------------------------------------------------------------*/
    104 /** Check setup packet data for signs of toggle reset.
    105  *
    106  * @param[in] instance Device keeper structure to use.
    107  * @param[in] target Device to receive setup packet.
    108  * @param[in] data Setup packet data.
    109  *
    110  * Really ugly one.
    111  */
    112 void usb_device_keeper_reset_if_need(
    113     usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data)
    114 {
    115         assert(instance);
    116         fibril_mutex_lock(&instance->guard);
    117         if (target.endpoint > 15 || target.endpoint < 0
    118             || target.address >= USB_ADDRESS_COUNT || target.address < 0
    119             || !instance->devices[target.address].occupied) {
    120                 fibril_mutex_unlock(&instance->guard);
    121                 usb_log_error("Invalid data when checking for toggle reset.\n");
    122                 return;
    123         }
    124 
    125         switch (data[1])
    126         {
    127         case 0x01: /*clear feature*/
    128                 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
    129                 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    130                         link_t *current =
    131                             instance->devices[target.address].endpoints.next;
    132                         while (current !=
    133                            &instance->devices[target.address].endpoints)
    134                         {
    135                         /* endpoint number is < 16, thus first byte is enough */
    136                                 endpoint_toggle_reset_filtered(
    137                                     current, data[4]);
    138                                 current = current->next;
    139                         }
    140                 }
    141         break;
    142 
    143         case 0x9: /* set configuration */
    144         case 0x11: /* set interface */
    145                 /* target must be device */
    146                 if ((data[0] & 0xf) == 0) {
    147                         link_t *current =
    148                             instance->devices[target.address].endpoints.next;
    149                         while (current !=
    150                            &instance->devices[target.address].endpoints)
    151                         {
    152                                 endpoint_toggle_reset(current);
    153                                 current = current->next;
    154                         }
    155                 }
    156         break;
    157         }
    158         fibril_mutex_unlock(&instance->guard);
    159 }
    16096/*----------------------------------------------------------------------------*/
    16197/** Get a free USB address
     
    264200        return instance->devices[address].speed;
    265201}
    266 /*----------------------------------------------------------------------------*/
    267 void usb_device_keeper_use_control(
    268     usb_device_keeper_t *instance, usb_target_t target)
    269 {
    270         assert(instance);
    271         const uint16_t ep = 1 << target.endpoint;
    272         fibril_mutex_lock(&instance->guard);
    273         while (instance->devices[target.address].control_used & ep) {
    274                 fibril_condvar_wait(&instance->change, &instance->guard);
    275         }
    276         instance->devices[target.address].control_used |= ep;
    277         fibril_mutex_unlock(&instance->guard);
    278 }
    279 /*----------------------------------------------------------------------------*/
    280 void usb_device_keeper_release_control(
    281     usb_device_keeper_t *instance, usb_target_t target)
    282 {
    283         assert(instance);
    284         const uint16_t ep = 1 << target.endpoint;
    285         fibril_mutex_lock(&instance->guard);
    286         assert((instance->devices[target.address].control_used & ep) != 0);
    287         instance->devices[target.address].control_used &= ~ep;
    288         fibril_mutex_unlock(&instance->guard);
    289         fibril_condvar_signal(&instance->change);
    290 }
    291202/**
    292203 * @}
  • uspace/lib/usb/src/host/endpoint.c

    ra49e171 rdc4c19e  
    3434 */
    3535
     36#include <assert.h>
    3637#include <errno.h>
    3738#include <usb/host/endpoint.h>
     
    4950        instance->max_packet_size = max_packet_size;
    5051        instance->toggle = 0;
    51         link_initialize(&instance->same_device_eps);
     52        instance->active = false;
     53        fibril_mutex_initialize(&instance->guard);
     54        fibril_condvar_initialize(&instance->avail);
    5255        return EOK;
    5356}
     
    5659{
    5760        assert(instance);
    58         list_remove(&instance->same_device_eps);
     61        assert(!instance->active);
    5962        free(instance);
     63}
     64/*----------------------------------------------------------------------------*/
     65void endpoint_use(endpoint_t *instance)
     66{
     67        assert(instance);
     68        fibril_mutex_lock(&instance->guard);
     69        while (instance->active)
     70                fibril_condvar_wait(&instance->avail, &instance->guard);
     71        instance->active = true;
     72        fibril_mutex_unlock(&instance->guard);
     73}
     74/*----------------------------------------------------------------------------*/
     75void endpoint_release(endpoint_t *instance)
     76{
     77        assert(instance);
     78        fibril_mutex_lock(&instance->guard);
     79        instance->active = false;
     80        fibril_mutex_unlock(&instance->guard);
     81        fibril_condvar_signal(&instance->avail);
    6082}
    6183/*----------------------------------------------------------------------------*/
     
    7395}
    7496/*----------------------------------------------------------------------------*/
    75 void endpoint_toggle_reset(link_t *ep)
     97void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target)
    7698{
    77         endpoint_t *instance =
    78             list_get_instance(ep, endpoint_t, same_device_eps);
    7999        assert(instance);
    80         instance->toggle = 0;
    81 }
    82 /*----------------------------------------------------------------------------*/
    83 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn)
    84 {
    85         endpoint_t *instance =
    86             list_get_instance(ep, endpoint_t, same_device_eps);
    87         assert(instance);
    88         if (instance->endpoint == epn)
     100        if (instance->address == target.address &&
     101            (instance->endpoint == target.endpoint || target.endpoint == 0))
    89102                instance->toggle = 0;
    90103}
  • uspace/lib/usb/src/host/usb_endpoint_manager.c

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

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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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

    ra49e171 rdc4c19e  
    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.