Changes in / [dc4c19e:a49e171] in mainline


Ignore:
Location:
uspace
Files:
6 deleted
54 edited

Legend:

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

    rdc4c19e ra49e171  
    5050
    5151        int rc;
    52         bool transfer_started = false;
    5352
    5453        rc = usb_device_connection_initialize(&dev->wire, hc_handle, dev_addr);
     
    7776        }
    7877
    79         rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
     78        rc = usb_pipe_start_session(&dev->ctrl_pipe);
    8079        if (rc != EOK) {
    8180                fprintf(stderr,
    82                     NAME ": failed to start transfer on control pipe: %s.\n",
     81                    NAME ": failed to start session on control pipe: %s.\n",
    8382                    str_error(rc));
    8483                goto leave;
    8584        }
    86         transfer_started = true;
    8785
    8886        rc = usb_request_get_device_descriptor(&dev->ctrl_pipe,
     
    109107
    110108leave:
    111         if (transfer_started) {
    112                 usb_pipe_end_long_transfer(&dev->ctrl_pipe);
     109        if (usb_pipe_is_session_started(&dev->ctrl_pipe)) {
     110                usb_pipe_end_session(&dev->ctrl_pipe);
    113111        }
    114112
     
    120118void destroy_device(usbinfo_device_t *dev)
    121119{
    122         usb_pipe_end_long_transfer(&dev->ctrl_pipe);
     120        usb_pipe_end_session(&dev->ctrl_pipe);
    123121        free(dev);
    124122}
  • uspace/doc/doxygroups.h

    rdc4c19e ra49e171  
    269269
    270270        /**
    271          * @defgroup drvusbohci OHCI driver
    272          * @ingroup usb
    273          * @brief Driver for OHCI host controller.
    274          */
    275 
    276         /**
    277271         * @defgroup drvusbehci EHCI driver
    278272         * @ingroup usb
     
    281275
    282276        /**
    283          * @defgroup drvusbfallback USB fallback driver
     277         * @defgroup drvusbfallback USB fallback driver.
    284278         * @ingroup usb
    285279         * @brief Fallback driver for any USB device.
  • uspace/drv/ehci-hcd/hc_iface.c

    rdc4c19e ra49e171  
    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).
    126125 * @param[in] endpoint Endpoint number.
    127126 * @param[in] transfer_type USB transfer type.
     
    132131 */
    133132static int register_endpoint(ddf_fun_t *fun,
    134     usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
     133    usb_address_t address, usb_endpoint_t endpoint,
    135134    usb_transfer_type_t transfer_type, usb_direction_t direction,
    136135    size_t max_packet_size, unsigned int interval)
     
    166165 * @param[in] fun Device function the action was invoked on.
    167166 * @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     void *data, size_t size,
     176    size_t max_packet_size, 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.
    193194 * @param[in] data Buffer where to store the data (in USB endianess,
    194195 *      allocated and deallocated by the caller).
     
    199200 */
    200201static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
    201     void *data, size_t size,
     202    size_t max_packet_size, void *data, size_t size,
    202203    usbhc_iface_transfer_in_callback_t callback, void *arg)
    203204{
     
    216217 * @param[in] fun Device function the action was invoked on.
    217218 * @param[in] target Target pipe (address and endpoint number) specification.
     219 * @param[in] max_packet_size Max packet size for the transfer.
    218220 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    219221 *      by the caller).
     
    224226 */
    225227static int bulk_out(ddf_fun_t *fun, usb_target_t target,
    226     void *data, size_t size,
     228    size_t max_packet_size, void *data, size_t size,
    227229    usbhc_iface_transfer_out_callback_t callback, void *arg)
    228230{
     
    241243 * @param[in] fun Device function the action was invoked on.
    242244 * @param[in] target Target pipe (address and endpoint number) specification.
     245 * @param[in] max_packet_size Max packet size for the transfer.
    243246 * @param[in] data Buffer where to store the data (in USB endianess,
    244247 *      allocated and deallocated by the caller).
     
    249252 */
    250253static int bulk_in(ddf_fun_t *fun, usb_target_t target,
    251     void *data, size_t size,
     254    size_t max_packet_size, void *data, size_t size,
    252255    usbhc_iface_transfer_in_callback_t callback, void *arg)
    253256{
     
    266269 * @param[in] fun Device function the action was invoked on.
    267270 * @param[in] target Target pipe (address and endpoint number) specification.
     271 * @param[in] max_packet_size Max packet size for the transfer.
    268272 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    269273 *      and deallocated by the caller).
     
    277281 */
    278282static int control_write(ddf_fun_t *fun, usb_target_t target,
     283    size_t max_packet_size,
    279284    void *setup_packet, size_t setup_packet_size,
    280285    void *data_buffer, size_t data_buffer_size,
     
    295300 * @param[in] fun Device function the action was invoked on.
    296301 * @param[in] target Target pipe (address and endpoint number) specification.
     302 * @param[in] max_packet_size Max packet size for the transfer.
    297303 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    298304 *      and deallocated by the caller).
     
    306312 */
    307313static int control_read(ddf_fun_t *fun, usb_target_t target,
     314    size_t max_packet_size,
    308315    void *setup_packet, size_t setup_packet_size,
    309316    void *data_buffer, size_t data_buffer_size,
  • uspace/drv/ohci/Makefile

    rdc4c19e ra49e171  
    3333
    3434SOURCES = \
     35        iface.c \
    3536        batch.c \
     37        main.c \
    3638        hc.c \
    37         iface.c \
    38         main.c \
    3939        ohci.c \
    40         pci.c \
    4140        root_hub.c \
    42         transfer_list.c \
    43         hw_struct/endpoint_descriptor.c \
    44         hw_struct/transfer_descriptor.c
    45 
     41        pci.c
    4642
    4743include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/ohci/batch.c

    rdc4c19e ra49e171  
    4040#include "batch.h"
    4141#include "utils/malloc32.h"
    42 #include "hw_struct/endpoint_descriptor.h"
    43 #include "hw_struct/transfer_descriptor.h"
    4442
    45 typedef struct ohci_batch {
    46         ed_t *ed;
    47         td_t *tds;
    48         size_t td_count;
    49 } ohci_batch_t;
    50 
    51 static void batch_control(usb_transfer_batch_t *instance,
    52     usb_direction_t data_dir, usb_direction_t status_dir);
    5343static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    5444static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    5545
    5646#define DEFAULT_ERROR_COUNT 3
    57 usb_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,
     47usb_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,
    5957    usbhc_iface_transfer_in_callback_t func_in,
    60     usbhc_iface_transfer_out_callback_t func_out, void *arg)
     58    usbhc_iface_transfer_out_callback_t func_out,
     59                void *arg,
     60                usb_device_keeper_t *manager
     61                )
    6162{
    6263#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
     
    7273        CHECK_NULL_DISPOSE_RETURN(instance,
    7374            "Failed to allocate batch instance.\n");
    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");
     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);
    10078
    10179        if (buffer_size > 0) {
     
    11290        }
    11391
     92
    11493        return instance;
    11594}
     
    11897{
    11998        assert(instance);
    120         ohci_batch_t *data = instance->private_data;
    121         assert(data);
    122         free32(data->ed);
    123         free32(data->tds);
     99        free32(instance->transport_buffer);
    124100        free32(instance->setup_buffer);
    125         free32(instance->transport_buffer);
    126         free(data);
    127101        free(instance);
    128 }
    129 /*----------------------------------------------------------------------------*/
    130 bool 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;
    153102}
    154103/*----------------------------------------------------------------------------*/
     
    160109            instance->buffer_size);
    161110        instance->next_step = batch_call_out_and_dispose;
    162         batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
     111        /* TODO: implement */
    163112        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    164113}
     
    168117        assert(instance);
    169118        instance->next_step = batch_call_in_and_dispose;
    170         batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
     119        /* TODO: implement */
    171120        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    172121}
     
    175124{
    176125        assert(instance);
    177         assert(instance->direction == USB_DIRECTION_IN);
     126        instance->direction = USB_DIRECTION_IN;
    178127        instance->next_step = batch_call_in_and_dispose;
    179128        /* TODO: implement */
     
    184133{
    185134        assert(instance);
    186         assert(instance->direction == USB_DIRECTION_OUT);
     135        instance->direction = USB_DIRECTION_OUT;
    187136        /* We are data out, we are supposed to provide data */
    188137        memcpy(instance->transport_buffer, instance->buffer,
     
    211160}
    212161/*----------------------------------------------------------------------------*/
    213 ed_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 /*----------------------------------------------------------------------------*/
    221 void 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 /*----------------------------------------------------------------------------*/
    270162/** Helper function calls callback and correctly disposes of batch structure.
    271163 *
  • uspace/drv/ohci/batch.h

    rdc4c19e ra49e171  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbuhcihc
     28/** @addtogroup drvusbohci
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transaction structure
     32 * @brief OHCI driver USB transaction structure
    3333 */
    34 #ifndef DRV_UHCI_BATCH_H
    35 #define DRV_UHCI_BATCH_H
     34#ifndef DRV_OHCI_BATCH_H
     35#define DRV_OHCI_BATCH_H
     36
    3637
    3738#include <usbhc_iface.h>
    3839#include <usb/usb.h>
    3940#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 
    4543usb_transfer_batch_t * batch_get(
    46     ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
    47     char *setup_buffer, size_t setup_size,
     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,
    4853    usbhc_iface_transfer_in_callback_t func_in,
    4954    usbhc_iface_transfer_out_callback_t func_out,
    50     void *arg);
     55                void *arg,
     56                usb_device_keeper_t *manager
     57                );
    5158
    5259void batch_dispose(usb_transfer_batch_t *instance);
    53 
    54 bool batch_is_complete(usb_transfer_batch_t *instance);
    5560
    5661void batch_control_write(usb_transfer_batch_t *instance);
     
    6570
    6671void batch_bulk_out(usb_transfer_batch_t *instance);
    67 
    68 ed_t * batch_ed(usb_transfer_batch_t *instance);
    6972#endif
    7073/**
  • uspace/drv/ohci/hc.c

    rdc4c19e ra49e171  
    4747static void hc_gain_control(hc_t *instance);
    4848static void hc_init_hw(hc_t *instance);
    49 static int hc_init_transfer_lists(hc_t *instance);
    50 static int hc_init_memory(hc_t *instance);
    5149/*----------------------------------------------------------------------------*/
    5250int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
     
    6159            &instance->manager, hub_address, hub_fun->handle);
    6260
    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 
    7161        char *match_str = NULL;
    72         ret = asprintf(&match_str, "usb&class=hub");
    73 //      ret = (match_str == NULL) ? ret : EOK;
     62        int ret = asprintf(&match_str, "usb&class=hub");
     63        ret = (match_str == NULL) ? ret : EOK;
    7464        if (ret < 0) {
    75                 usb_log_error(
    76                     "Failed(%d) to create root hub match-id string.\n", ret);
     65                usb_log_error("Failed to create root hub match-id string.\n");
    7766                return ret;
    7867        }
     
    10897            ret, str_error(ret));
    10998
    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 
    11899        if (!interrupts) {
    119100                instance->interrupt_emulator =
     
    122103        }
    123104
     105        hc_gain_control(instance);
     106
     107        rh_init(&instance->rh, dev, instance->registers);
     108
     109        hc_init_hw(instance);
     110
     111        /* TODO: implement */
    124112        return EOK;
    125113}
     
    129117        assert(instance);
    130118        assert(batch);
    131 
    132         /* check for root hub communication */
    133119        if (batch->target.address == instance->rh.address) {
    134120                return rh_request(&instance->rh, batch);
    135121        }
    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;
     122        /* TODO: implement */
     123        return ENOTSUP;
    157124}
    158125/*----------------------------------------------------------------------------*/
     
    160127{
    161128        assert(instance);
    162         if ((status & ~IS_SF) == 0) /* ignore sof status */
     129        if (status == 0)
    163130                return;
    164131        if (status & IS_RHSC)
     
    167134        usb_log_info("OHCI interrupt: %x.\n", status);
    168135
    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         }
     136        /* TODO: Check for further interrupt causes */
     137        /* TODO: implement */
    183138}
    184139/*----------------------------------------------------------------------------*/
     
    199154{
    200155        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 
    208156        /* Interrupt routing enabled => smm driver is active */
    209157        if (instance->registers->control & C_IR) {
    210                 usb_log_debug("SMM driver: request ownership change.\n");
     158                usb_log_info("Found SMM driver requesting ownership change.\n");
    211159                instance->registers->command_status |= CS_OCR;
    212160                while (instance->registers->control & C_IR) {
    213161                        async_usleep(1000);
    214162                }
    215                 usb_log_info("SMM driver: Ownership taken.\n");
     163                usb_log_info("Ownership taken from SMM driver.\n");
    216164                return;
    217165        }
     
    221169        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    222170        if (hc_status != C_HCFS_RESET) {
    223                 usb_log_debug("BIOS driver found.\n");
     171                usb_log_info("Found BIOS driver.\n");
    224172                if (hc_status == C_HCFS_OPERATIONAL) {
    225                         usb_log_info("BIOS driver: HC operational.\n");
     173                        usb_log_info("HC operational(BIOS).\n");
    226174                        return;
    227175                }
     
    229177                instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
    230178                async_usleep(20000);
    231                 usb_log_info("BIOS driver: HC resumed.\n");
    232179                return;
    233180        }
     
    235182        /* HC is in reset (hw startup) => no other driver
    236183         * maintain reset for at least the time specified in USB spec (50 ms)*/
    237         usb_log_info("HC found in reset.\n");
    238184        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
    239193}
    240194/*----------------------------------------------------------------------------*/
    241195void hc_init_hw(hc_t *instance)
    242196{
    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 */
     197        assert(instance);
    248198        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;
    254199        instance->registers->command_status = CS_HCR;
    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 */
     200        async_usleep(10);
    262201        instance->registers->fm_interval = fm_interval;
    263202        assert((instance->registers->command_status & CS_HCR) == 0);
    264 
    265203        /* hc is now in suspend state */
    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);
     204        /* TODO: init HCCA block */
     205        /* TODO: init queues */
     206        /* TODO: enable queues */
     207        /* TODO: enable interrupts */
     208        /* TODO: set periodic start to 90% */
    288209
    289210        instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
    290         usb_log_info("OHCI HC up and running(%x).\n",
    291             instance->registers->control);
    292 }
    293 /*----------------------------------------------------------------------------*/
    294 int hc_init_transfer_lists(hc_t *instance)
    295 {
    296         assert(instance);
    297 
    298 #define SETUP_TRANSFER_LIST(type, name) \
    299 do { \
    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 /*----------------------------------------------------------------------------*/
    333 int 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;
     211        usb_log_info("OHCI HC up and running.\n");
    370212}
    371213/**
  • uspace/drv/ohci/hc.h

    rdc4c19e ra49e171  
    4848#include "ohci_regs.h"
    4949#include "root_hub.h"
    50 #include "transfer_list.h"
    5150#include "hw_struct/hcca.h"
    5251
     
    5554        usb_address_t rh_address;
    5655        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 
    6756        ddf_fun_t *ddf_instance;
    6857        usb_device_keeper_t manager;
  • uspace/drv/ohci/hw_struct/completion_codes.h

    rdc4c19e ra49e171  
    3535#define DRV_OHCI_HW_STRUCT_COMPLETION_CODES_H
    3636
    37 #include <errno.h>
    38 
    3937#define CC_NOERROR (0x0)
    4038#define CC_CRC (0x1)
     
    5250#define CC_NOACCESS2 (0xf)
    5351
    54 inline 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 
    8852#endif
    8953/**
  • uspace/drv/ohci/hw_struct/endpoint_descriptor.h

    rdc4c19e ra49e171  
    3535#define DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H
    3636
    37 #include <assert.h>
    3837#include <stdint.h>
    39 
    40 #include <usb/host/endpoint.h>
    41 
    42 #include "utils/malloc32.h"
    43 #include "transfer_descriptor.h"
    4438
    4539#include "completion_codes.h"
     
    5044#define ED_STATUS_FA_SHIFT (0)
    5145#define ED_STATUS_EN_MASK (0xf)    /* USB endpoint address */
    52 #define ED_STATUS_EN_SHIFT (7)
     46#define ED_STATUS_EN_SHIFT (6)
    5347#define ED_STATUS_D_MASK (0x3)     /* direction */
    54 #define ED_STATUS_D_SHIFT (11)
     48#define ED_STATUS_D_SHIFT (10)
    5549#define ED_STATUS_D_IN (0x1)
    5650#define ED_STATUS_D_OUT (0x2)
    57 #define ED_STATUS_D_TRANSFER (0x3)
    5851
    59 #define ED_STATUS_S_FLAG (1 << 13) /* speed flag: 1 = low */
     52#define ED_STATUS_S_FLAG (1 << 13) /* speed flag */
    6053#define ED_STATUS_K_FLAG (1 << 14) /* skip flag (no not execute this ED) */
    6154#define ED_STATUS_F_FLAG (1 << 15) /* format: 1 = isochronous*/
     
    7871#define ED_NEXT_PTR_SHIFT (0)
    7972} __attribute__((packed)) ed_t;
    80 
    81 void ed_init(ed_t *instance, endpoint_t *ep);
    82 
    83 static 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 
    90 static 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 
    9973#endif
    10074/**
  • uspace/drv/ohci/hw_struct/transfer_descriptor.h

    rdc4c19e ra49e171  
    3535#define DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
    3636
    37 #include <bool.h>
    3837#include <stdint.h>
    39 #include "utils/malloc32.h"
    4038
    4139#include "completion_codes.h"
    42 
    43 /* OHCI TDs can handle up to 8KB buffers */
    44 #define OHCI_TD_MAX_TRANSFER (8 * 1024)
    4540
    4641typedef struct td {
     
    5752#define TD_STATUS_T_MASK (0x3)  /* data toggle 1x = use ED toggle carry */
    5853#define TD_STATUS_T_SHIFT (24)
    59 #define TD_STATUS_T_0 (0x2)
    60 #define TD_STATUS_T_1 (0x3)
    6154#define TD_STATUS_EC_MASK (0x3) /* error count */
    6255#define TD_STATUS_EC_SHIFT (26)
     
    7164        volatile uint32_t be; /* buffer end, address of the last byte */
    7265} __attribute__((packed)) td_t;
    73 
    74 void td_init(
    75     td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle);
    76 
    77 inline 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 
    83 inline 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 
    98 static 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 }
    10466#endif
    10567/**
  • uspace/drv/ohci/iface.c

    rdc4c19e ra49e171  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky, Jan Vesely
     2 * Copyright (c) 2011 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3030 */
    3131/** @file
    32  * @brief OHCI driver hc interface implementation
     32 * USB-HC interface implementation.
    3333 */
    3434#include <ddf/driver.h>
     
    3636
    3737#include <usb/debug.h>
    38 #include <usb/host/endpoint.h>
    3938
    4039#include "iface.h"
    4140#include "hc.h"
    4241
    43 static inline int setup_batch(
    44     ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
    45     void *data, size_t size, void * setup_data, size_t setup_size,
    46     usbhc_iface_transfer_in_callback_t in,
    47     usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
    48     hc_t **hc, usb_transfer_batch_t **batch)
    49 {
    50         assert(hc);
    51         assert(batch);
    52         assert(fun);
    53         *hc = fun_to_hc(fun);
    54         assert(*hc);
    55 
    56         size_t res_bw;
    57         endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
    58             target.address, target.endpoint, direction, &res_bw);
    59         if (ep == NULL) {
    60                 usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
    61                     target.address, target.endpoint, name);
    62                 return ENOENT;
    63         }
    64 
    65         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;
     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 */
     55static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
     56{
     57        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);
    8162        return EOK;
    8263}
    8364/*----------------------------------------------------------------------------*/
    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.
     65/** Release default address.
     66 *
     67 * @param[in] fun Device function the action was invoked on.
     68 * @return Error code.
     69 */
     70static 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.
    8985 * @return Error code.
    9086 */
     
    105101}
    106102/*----------------------------------------------------------------------------*/
    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.
     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.
    112108 * @return Error code.
    113109 */
    114110static int bind_address(
    115   ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
     111    ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
    116112{
    117113        assert(fun);
     
    123119}
    124120/*----------------------------------------------------------------------------*/
    125 /** Release address interface function
    126  *
    127  * @param[in] fun DDF function that was called.
     121/** Release previously requested address.
     122 *
     123 * @param[in] fun Device function the action was invoked on.
    128124 * @param[in] address USB address to be released.
    129125 * @return Error code.
     
    143139 * @param[in] fun Device function the action was invoked on.
    144140 * @param[in] address USB address of the device.
    145  * @param[in] ep_speed Endpoint speed (invalid means to use device one).
    146141 * @param[in] endpoint Endpoint number.
    147142 * @param[in] transfer_type USB transfer type.
     
    151146 * @return Error code.
    152147 */
    153 static int register_endpoint(ddf_fun_t *fun,
    154     usb_address_t address, usb_speed_t ep_speed, usb_endpoint_t endpoint,
     148static int register_endpoint(
     149    ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
    155150    usb_transfer_type_t transfer_type, usb_direction_t direction,
    156151    size_t max_packet_size, unsigned int interval)
    157152{
    158         hc_t *hc = fun_to_hc(fun);
    159         assert(hc);
    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         }
     153        assert(fun);
     154        hc_t *hc = fun_to_hc(fun);
     155        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);
    165160        const size_t size = max_packet_size;
    166         int ret;
    167 
    168161        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    169162            address, endpoint, usb_str_transfer_type(transfer_type),
    170163            usb_str_speed(speed), direction, size, max_packet_size, interval);
    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 /*----------------------------------------------------------------------------*/
     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 */
    189176static int unregister_endpoint(
    190177    ddf_fun_t *fun, usb_address_t address,
    191178    usb_endpoint_t endpoint, usb_direction_t direction)
    192179{
     180        assert(fun);
    193181        hc_t *hc = fun_to_hc(fun);
    194182        assert(hc);
     
    208196 * @param[in] fun Device function the action was invoked on.
    209197 * @param[in] target Target pipe (address and endpoint number) specification.
     198 * @param[in] max_packet_size Max packet size for the transfer.
    210199 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    211200 *      by the caller).
     
    216205 */
    217206static int interrupt_out(
    218     ddf_fun_t *fun, usb_target_t target, void *data,
     207    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
    219208    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    220209{
    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;
     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;
    227224        batch_interrupt_out(batch);
    228         ret = hc_schedule(hc, batch);
     225        const int ret = hc_schedule(hc, batch);
    229226        if (ret != EOK) {
    230227                batch_dispose(batch);
     
    242239 * @param[in] fun Device function the action was invoked on.
    243240 * @param[in] target Target pipe (address and endpoint number) specification.
     241 * @param[in] max_packet_size Max packet size for the transfer.
    244242 * @param[in] data Buffer where to store the data (in USB endianess,
    245243 *      allocated and deallocated by the caller).
     
    250248 */
    251249static int interrupt_in(
    252     ddf_fun_t *fun, usb_target_t target, void *data,
     250    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
    253251    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    254252{
    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;
     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;
    261266        batch_interrupt_in(batch);
    262         ret = hc_schedule(hc, batch);
     267        const int ret = hc_schedule(hc, batch);
    263268        if (ret != EOK) {
    264269                batch_dispose(batch);
     
    276281 * @param[in] fun Device function the action was invoked on.
    277282 * @param[in] target Target pipe (address and endpoint number) specification.
     283 * @param[in] max_packet_size Max packet size for the transfer.
    278284 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    279285 *      by the caller).
     
    284290 */
    285291static int bulk_out(
    286     ddf_fun_t *fun, usb_target_t target, void *data,
     292    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
    287293    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    288294{
    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;
     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;
    295309        batch_bulk_out(batch);
    296         ret = hc_schedule(hc, batch);
     310        const int ret = hc_schedule(hc, batch);
    297311        if (ret != EOK) {
    298312                batch_dispose(batch);
     
    310324 * @param[in] fun Device function the action was invoked on.
    311325 * @param[in] target Target pipe (address and endpoint number) specification.
     326 * @param[in] max_packet_size Max packet size for the transfer.
    312327 * @param[in] data Buffer where to store the data (in USB endianess,
    313328 *      allocated and deallocated by the caller).
     
    318333 */
    319334static int bulk_in(
    320     ddf_fun_t *fun, usb_target_t target, void *data,
     335    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
    321336    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    322337{
    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;
     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;
    329351        batch_bulk_in(batch);
    330         ret = hc_schedule(hc, batch);
     352        const int ret = hc_schedule(hc, batch);
    331353        if (ret != EOK) {
    332354                batch_dispose(batch);
     
    344366 * @param[in] fun Device function the action was invoked on.
    345367 * @param[in] target Target pipe (address and endpoint number) specification.
     368 * @param[in] max_packet_size Max packet size for the transfer.
    346369 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    347370 *      and deallocated by the caller).
     
    355378 */
    356379static int control_write(
    357     ddf_fun_t *fun, usb_target_t target,
     380    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
    358381    void *setup_data, size_t setup_size, void *data, size_t size,
    359382    usbhc_iface_transfer_out_callback_t callback, void *arg)
    360383{
    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);
     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);
    369402        batch_control_write(batch);
    370         ret = hc_schedule(hc, batch);
     403        const int ret = hc_schedule(hc, batch);
    371404        if (ret != EOK) {
    372405                batch_dispose(batch);
     
    384417 * @param[in] fun Device function the action was invoked on.
    385418 * @param[in] target Target pipe (address and endpoint number) specification.
     419 * @param[in] max_packet_size Max packet size for the transfer.
    386420 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    387421 *      and deallocated by the caller).
     
    395429 */
    396430static int control_read(
    397     ddf_fun_t *fun, usb_target_t target,
     431    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
    398432    void *setup_data, size_t setup_size, void *data, size_t size,
    399433    usbhc_iface_transfer_in_callback_t callback, void *arg)
    400434{
    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;
     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;
    408449        batch_control_read(batch);
    409         ret = hc_schedule(hc, batch);
    410         if (ret != EOK) {
    411                 batch_dispose(batch);
    412         }
    413         return ret;
    414 }
    415 /*----------------------------------------------------------------------------*/
     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. */
    416458usbhc_iface_t hc_iface = {
     459        .reserve_default_address = reserve_default_address,
     460        .release_default_address = release_default_address,
    417461        .request_address = request_address,
    418462        .bind_address = bind_address,
     
    431475        .control_read = control_read,
    432476};
     477
    433478/**
    434479 * @}
  • uspace/drv/ohci/ohci_regs.h

    rdc4c19e ra49e171  
    4141        const volatile uint32_t revision;
    4242        volatile uint32_t control;
    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)
     43#define C_CSBR_MASK (0x3)
    4844#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)
    4949
    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 */
     50#define C_HCFS_MASK (0x3)
     51#define C_HCFS_SHIFT (6)
     52#define C_HCFS_RESET (0x0)
     53#define C_HCFS_OPERATIONAL (0x1)
     54#define C_HCFS_RESUME (0x2)
     55#define C_HCFS_SUSPEND (0x3)
    5456
    55 #define C_HCFS_MASK        (0x3) /* Host controller functional state */
    56 #define C_HCFS_RESET       (0x0)
    57 #define C_HCFS_OPERATIONAL (0x1)
    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 */
     57#define C_IR (1 << 8)
     58#define C_RWC (1 << 9)
     59#define C_RWE (1 << 10)
    6560
    6661        volatile uint32_t command_status;
    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 */
     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)
    7267#define CS_SOC_SHIFT (16)
    7368
    7469        volatile uint32_t interrupt_status;
    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 */
     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)
    8378
    84         /** Interupt enable/disable, reads give the same value, writing causes
    85          * enable/disable */
    86         volatile uint32_t interrupt_enable;
     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
    8790        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) */
    9991        volatile uint32_t hcca;
    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 */
     92        volatile uint32_t period_corrent;
    10693        volatile uint32_t control_head;
    107 
    108         /** Currently executed control endpoint */
    10994        volatile uint32_t control_current;
    110 
    111         /** The first bulk endpoint */
    11295        volatile uint32_t bulk_head;
    113 
    114         /** Currently executed bulk endpoint */
    11596        volatile uint32_t bulk_current;
    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 */
     97        volatile uint32_t done_head;
    12198        volatile uint32_t fm_interval;
    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 */
     99        volatile uint32_t fm_remaining;
     100        volatile uint32_t fm_number;
    139101        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 */
    143102        volatile uint32_t ls_threshold;
    144 #define LST_LST_MASK (0x7fff)
    145 
    146         /** The first root hub control register */
    147103        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 */
    159104        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 */
    171105        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 */
    193106        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
    223107} __attribute__((packed)) ohci_regs_t;
    224108#endif
  • uspace/drv/ohci/root_hub.c

    rdc4c19e ra49e171  
    4747 *      standart device descriptor for ohci root hub
    4848 */
    49 static 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,
     49static 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,
    6465};
    6566
     
    6869 * for ohci root hubs
    6970 */
    70 static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = {
     71static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor =
     72{
    7173        /// \TODO some values are default or guessed
    72         .attributes = 1 << 7,
     74        .attributes = 1<<7,
    7375        .configuration_number = 1,
    7476        .descriptor_type = USB_DESCTYPE_CONFIGURATION,
    7577        .interface_count = 1,
    76         .length = sizeof (usb_standard_configuration_descriptor_t),
     78        .length = sizeof(usb_standard_configuration_descriptor_t),
    7779        .max_power = 100,
    7880        .str_configuration = 0,
     
    8284 * standart ohci root hub interface descriptor
    8385 */
    84 static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor = {
     86static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor =
     87{
    8588        .alternate_setting = 0,
    8689        .descriptor_type = USB_DESCTYPE_INTERFACE,
     
    9194        .interface_protocol = 0,
    9295        .interface_subclass = 0,
    93         .length = sizeof (usb_standard_interface_descriptor_t),
     96        .length = sizeof(usb_standard_interface_descriptor_t),
    9497        .str_interface = 0,
    9598};
     
    98101 * standart ohci root hub endpoint descriptor
    99102 */
    100 static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor = {
     103static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor =
     104{
    101105        .attributes = USB_TRANSFER_INTERRUPT,
    102106        .descriptor_type = USB_DESCTYPE_ENDPOINT,
    103         .endpoint_address = 1 + (1 << 7),
    104         .length = sizeof (usb_standard_endpoint_descriptor_t),
     107        .endpoint_address = 1 + (1<<7),
     108        .length = sizeof(usb_standard_endpoint_descriptor_t),
    105109        .max_packet_size = 8,
    106110        .poll_interval = 255,
     
    108112
    109113static const uint32_t hub_clear_feature_valid_mask =
    110         (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) |
    111 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
     114        (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) +
     115        (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
    112116
    113117static const uint32_t hub_clear_feature_by_writing_one_mask =
     
    115119
    116120static const uint32_t hub_set_feature_valid_mask =
    117         (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT) |
    118 (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
    119 
    120 
     121        (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
     122
     123       
    121124static const uint32_t hub_set_feature_direct_mask =
    122125        (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
    123126
    124127static const uint32_t port_set_feature_valid_mask =
    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);
     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);
    129132
    130133static const uint32_t port_clear_feature_valid_mask =
    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 
    143 static 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 
    151 static void usb_create_serialized_hub_descriptor(rh_t *instance,
    152         uint8_t ** out_result,
    153         size_t * out_size);
    154 
    155 static void rh_init_descriptors(rh_t *instance);
    156 
    157 static int process_get_port_status_request(rh_t *instance, uint16_t port,
    158         usb_transfer_batch_t * request);
    159 
    160 static int process_get_hub_status_request(rh_t *instance,
    161         usb_transfer_batch_t * request);
    162 
    163 static int process_get_status_request(rh_t *instance,
    164         usb_transfer_batch_t * request);
    165 
    166 static void create_interrupt_mask(rh_t *instance, void ** buffer,
    167         size_t * buffer_size);
    168 
    169 static int process_get_descriptor_request(rh_t *instance,
    170         usb_transfer_batch_t *request);
    171 
    172 static int process_get_configuration_request(rh_t *instance,
    173         usb_transfer_batch_t *request);
    174 
    175 static int process_hub_feature_set_request(rh_t *instance, uint16_t feature);
    176 
    177 static int process_hub_feature_clear_request(rh_t *instance,
    178         uint16_t feature);
    179 
    180 static int process_port_feature_set_request(rh_t *instance,
    181         uint16_t feature, uint16_t port);
    182 
    183 static int process_port_feature_clear_request(rh_t *instance,
    184         uint16_t feature, uint16_t port);
    185 
    186 static int process_address_set_request(rh_t *instance,
    187         uint16_t address);
    188 
    189 static int process_request_with_output(rh_t *instance,
    190         usb_transfer_batch_t *request);
    191 
    192 static int process_request_with_input(rh_t *instance,
    193         usb_transfer_batch_t *request);
    194 
    195 static int process_request_without_data(rh_t *instance,
    196         usb_transfer_batch_t *request);
    197 
    198 static 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  */
    207 int 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  */
    235 int 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 
    260 void 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 /*----------------------------------------------------------------------------*/
     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
    266147
    267148/**
     
    276157 */
    277158static void usb_create_serialized_hub_descriptor(rh_t *instance,
    278         uint8_t ** out_result,
    279         size_t * out_size) {
     159                uint8_t ** out_result,
     160                size_t * out_size) {
    280161        //base size
    281162        size_t size = 7;
    282163        //variable size according to port count
    283164        size_t var_size = instance->port_count / 8 +
    284                 ((instance->port_count % 8 > 0) ? 1 : 0);
     165                        ((instance->port_count % 8 > 0) ? 1 : 0);
    285166        size += 2 * var_size;
    286167        uint8_t * result = (uint8_t*) malloc(size);
    287         bzero(result, size);
     168        bzero(result,size);
    288169        //size
    289170        result[0] = size;
     
    293174        uint32_t hub_desc_reg = instance->registers->rh_desc_a;
    294175        result[3] =
    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);
     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);
    300181        result[4] = 0;
    301182        result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
     
    304185        int port;
    305186        for (port = 1; port <= instance->port_count; ++port) {
    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);
     187                result[7 + port/8] +=
     188                                ((instance->registers->rh_desc_b >> port)%2) << (port%8);
    310189        }
    311190        size_t i;
     
    316195        (*out_size) = size;
    317196}
    318 /*----------------------------------------------------------------------------*/
     197
    319198
    320199/** initialize hub descriptors
     
    324203 * @instance root hub instance
    325204 */
    326 static void rh_init_descriptors(rh_t *instance) {
     205static void rh_init_descriptors(rh_t *instance){
    327206        memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    328                 sizeof (ohci_rh_device_descriptor)
    329                 );
     207                sizeof(ohci_rh_device_descriptor)
     208        );
    330209        usb_standard_configuration_descriptor_t descriptor;
    331         memcpy(&descriptor, &ohci_rh_conf_descriptor,
    332                 sizeof (ohci_rh_conf_descriptor));
     210        memcpy(&descriptor,&ohci_rh_conf_descriptor,
     211                        sizeof(ohci_rh_conf_descriptor));
    333212        uint8_t * hub_descriptor;
    334213        size_t hub_desc_size;
    335214        usb_create_serialized_hub_descriptor(instance, &hub_descriptor,
    336                 &hub_desc_size);
     215                        &hub_desc_size);
    337216
    338217        descriptor.total_length =
    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 
     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       
    344223        uint8_t * full_config_descriptor =
    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 
     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       
    357236        instance->descriptors.configuration = full_config_descriptor;
    358237        instance->descriptors.configuration_size = descriptor.total_length;
    359238}
     239
     240/** Root hub initialization
     241 * @return Error code.
     242 */
     243int 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}
    360261/*----------------------------------------------------------------------------*/
    361262
     
    371272 */
    372273static int process_get_port_status_request(rh_t *instance, uint16_t port,
    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;
     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;
    377278        request->transfered_size = 4;
    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 /*----------------------------------------------------------------------------*/
     279        uint32_buffer[0] = instance->registers->rh_port_status[port -1];
     280        return EOK;
     281}
    390282
    391283/**
     
    399291 */
    400292static int process_get_hub_status_request(rh_t *instance,
    401         usb_transfer_batch_t * request) {
    402         uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
     293                usb_transfer_batch_t * request){
     294        uint32_t * uint32_buffer = (uint32_t*)request->transport_buffer;
     295        //bits, 0,1,16,17
    403296        request->transfered_size = 4;
    404         //bits, 0,1,16,17
    405         uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17);
     297        uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17);
    406298        uint32_buffer[0] = mask & instance->registers->rh_status;
    407299        return EOK;
    408 }
    409 /*----------------------------------------------------------------------------*/
     300
     301}
     302
     303
    410304
    411305/**
     
    419313 */
    420314static int process_get_status_request(rh_t *instance,
    421         usb_transfer_batch_t * request) {
     315                usb_transfer_batch_t * request)
     316{
    422317        size_t buffer_size = request->buffer_size;
    423318        usb_device_request_setup_packet_t * request_packet =
    424                 (usb_device_request_setup_packet_t*)
    425                 request->setup_buffer;
     319                        (usb_device_request_setup_packet_t*)
     320                        request->setup_buffer;
    426321
    427322        usb_hub_bm_request_type_t request_type = request_packet->request_type;
    428         if (buffer_size < 4/*request_packet->length*/) {///\TODO
     323        if(buffer_size<4/*request_packet->length*/){///\TODO
    429324                usb_log_warning("requested more data than buffer size\n");
    430325                return EINVAL;
    431326        }
    432327
    433         if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
     328        if(request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
    434329                return process_get_hub_status_request(instance, 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);
     330        if(request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
     331                return process_get_port_status_request(instance, request_packet->index,
     332                                request);
    439333        return ENOTSUP;
    440334}
    441 /*----------------------------------------------------------------------------*/
    442335
    443336/**
     
    446339 * Result contains bitmap where bit 0 indicates change on hub and
    447340 * bit i indicates change on i`th port (i>0). For more info see
    448  * Hub and Port status bitmap specification in USB specification
    449  * (chapter 11.13.4)
     341 * Hub and Port status bitmap specification in USB specification.
    450342 * @param instance root hub instance
    451343 * @param@out buffer pointer to created interrupt mas
     
    453345 */
    454346static void create_interrupt_mask(rh_t *instance, void ** buffer,
    455         size_t * buffer_size) {
     347                size_t * buffer_size){
    456348        int bit_count = instance->port_count + 1;
    457         (*buffer_size) = (bit_count / 8) + ((bit_count % 8 == 0) ? 0 : 1);
    458 
     349        (*buffer_size) = (bit_count / 8) + (bit_count%8==0)?0:1;
    459350        (*buffer) = malloc(*buffer_size);
    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) {
     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){
    465355                bitmap[0] = 1;
    466356        }
    467357        int port;
    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 
     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 
    477369/**
    478370 * create answer to a descriptor request
     
    485377 */
    486378static int process_get_descriptor_request(rh_t *instance,
    487         usb_transfer_batch_t *request) {
     379                usb_transfer_batch_t *request){
    488380        usb_device_request_setup_packet_t * setup_request =
    489                 (usb_device_request_setup_packet_t*) request->setup_buffer;
     381                        (usb_device_request_setup_packet_t*)request->setup_buffer;
    490382        size_t size;
    491383        const void * result_descriptor = NULL;
    492384        const uint16_t setup_request_value = setup_request->value_high;
    493         //(setup_request->value_low << 8);
     385                        //(setup_request->value_low << 8);
    494386        bool del = false;
    495         switch (setup_request_value) {
    496                 case USB_DESCTYPE_HUB:
    497                 {
     387        switch (setup_request_value)
     388        {
     389                case USB_DESCTYPE_HUB: {
    498390                        uint8_t * descriptor;
    499391                        usb_create_serialized_hub_descriptor(
    500392                                instance, &descriptor, &size);
    501393                        result_descriptor = descriptor;
    502                         if (result_descriptor) del = true;
     394                        if(result_descriptor) del = true;
    503395                        break;
    504396                }
    505                 case USB_DESCTYPE_DEVICE:
    506                 {
     397                case USB_DESCTYPE_DEVICE: {
    507398                        usb_log_debug("USB_DESCTYPE_DEVICE\n");
    508399                        result_descriptor = &ohci_rh_device_descriptor;
    509                         size = sizeof (ohci_rh_device_descriptor);
     400                        size = sizeof(ohci_rh_device_descriptor);
    510401                        break;
    511402                }
    512                 case USB_DESCTYPE_CONFIGURATION:
    513                 {
     403                case USB_DESCTYPE_CONFIGURATION: {
    514404                        usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
    515405                        result_descriptor = instance->descriptors.configuration;
     
    517407                        break;
    518408                }
    519                 case USB_DESCTYPE_INTERFACE:
    520                 {
     409                case USB_DESCTYPE_INTERFACE: {
    521410                        usb_log_debug("USB_DESCTYPE_INTERFACE\n");
    522411                        result_descriptor = &ohci_rh_iface_descriptor;
    523                         size = sizeof (ohci_rh_iface_descriptor);
     412                        size = sizeof(ohci_rh_iface_descriptor);
    524413                        break;
    525414                }
    526                 case USB_DESCTYPE_ENDPOINT:
    527                 {
     415                case USB_DESCTYPE_ENDPOINT: {
    528416                        usb_log_debug("USB_DESCTYPE_ENDPOINT\n");
    529417                        result_descriptor = &ohci_rh_ep_descriptor;
    530                         size = sizeof (ohci_rh_ep_descriptor);
     418                        size = sizeof(ohci_rh_ep_descriptor);
    531419                        break;
    532420                }
    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                                 );
     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                                        );
    545430                        return EINVAL;
    546431                }
    547432        }
    548         if (request->buffer_size < size) {
     433        if(request->buffer_size < size){
    549434                size = request->buffer_size;
    550435        }
    551436        request->transfered_size = size;
    552         memcpy(request->transport_buffer, result_descriptor, 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));
    553440        if (del)
    554441                free(result_descriptor);
    555442        return EOK;
    556443}
    557 /*----------------------------------------------------------------------------*/
    558444
    559445/**
     
    565451 * @return error code
    566452 */
    567 static int process_get_configuration_request(rh_t *instance,
    568         usb_transfer_batch_t *request) {
     453static int process_get_configuration_request(rh_t *instance, 
     454                usb_transfer_batch_t *request){
    569455        //set and get configuration requests do not have any meaning, only dummy
    570456        //values are returned
    571         if (request->buffer_size != 1)
     457        if(request->buffer_size != 1)
    572458                return EINVAL;
    573459        request->transport_buffer[0] = 1;
     
    575461        return EOK;
    576462}
    577 /*----------------------------------------------------------------------------*/
    578463
    579464/**
    580465 * process feature-enabling request on hub
    581  *
     466 * 
    582467 * @param instance root hub instance
    583468 * @param feature feature selector
     
    585470 */
    586471static int process_hub_feature_set_request(rh_t *instance,
    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;
     472                uint16_t feature){
     473        if(! ((1<<feature) & hub_set_feature_valid_mask))
     474                return EINVAL;
    592475        instance->registers->rh_status =
    593                 (instance->registers->rh_status | (1 << feature))
    594                 & (~hub_clear_feature_by_writing_one_mask);
    595         return EOK;
    596 }
    597 /*----------------------------------------------------------------------------*/
     476                        (instance->registers->rh_status | (1<<feature))
     477                        & (~ hub_clear_feature_by_writing_one_mask);
     478        return EOK;
     479}
    598480
    599481/**
     
    605487 */
    606488static int process_hub_feature_clear_request(rh_t *instance,
    607         uint16_t feature) {
    608         if (!((1 << feature) & hub_clear_feature_valid_mask))
     489                uint16_t feature){
     490        if(! ((1<<feature) & hub_clear_feature_valid_mask))
    609491                return EINVAL;
    610492        //is the feature cleared directly?
    611         if ((1 << feature) & hub_set_feature_direct_mask) {
     493        if ((1<<feature) & hub_set_feature_direct_mask){
    612494                instance->registers->rh_status =
    613                         (instance->registers->rh_status & (~(1 << feature)))
    614                         & (~hub_clear_feature_by_writing_one_mask);
    615         } else {//the feature is cleared by writing '1'
     495                        (instance->registers->rh_status & (~(1<<feature)))
     496                        & (~ hub_clear_feature_by_writing_one_mask);
     497        }else{//the feature is cleared by writing '1'
    616498                instance->registers->rh_status =
    617                         (instance->registers->rh_status
    618                         & (~hub_clear_feature_by_writing_one_mask))
    619                         | (1 << feature);
    620         }
    621         return EOK;
    622 }
    623 /*----------------------------------------------------------------------------*/
     499                                (instance->registers->rh_status
     500                                & (~ hub_clear_feature_by_writing_one_mask))
     501                                | (1<<feature);
     502        }
     503        return EOK;
     504}
     505
     506
    624507
    625508/**
    626509 * process feature-enabling request on hub
    627  *
     510 * 
    628511 * @param instance root hub instance
    629512 * @param feature feature selector
     
    633516 */
    634517static int process_port_feature_set_request(rh_t *instance,
    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)
     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)
    639522                return EINVAL;
    640523        instance->registers->rh_port_status[port - 1] =
    641                 (instance->registers->rh_port_status[port - 1] | (1 << feature))
    642                 & (~port_clear_feature_valid_mask);
     524                        (instance->registers->rh_port_status[port - 1] | (1<<feature))
     525                        & (~port_clear_feature_valid_mask);
    643526        /// \TODO any error?
    644527        return EOK;
    645528}
    646 /*----------------------------------------------------------------------------*/
    647529
    648530/**
     
    656538 */
    657539static int process_port_feature_clear_request(rh_t *instance,
    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)
     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)
    664546                feature = USB_HUB_FEATURE_PORT_LOW_SPEED;
    665         if (feature == USB_HUB_FEATURE_PORT_SUSPEND)
     547        if(feature == USB_HUB_FEATURE_PORT_SUSPEND)
    666548                feature = USB_HUB_FEATURE_PORT_OVER_CURRENT;
    667549        instance->registers->rh_port_status[port - 1] =
    668                 (instance->registers->rh_port_status[port - 1]
    669                 & (~port_clear_feature_valid_mask))
    670                 | (1 << feature);
     550                        (instance->registers->rh_port_status[port - 1]
     551                        & (~port_clear_feature_valid_mask))
     552                        | (1<<feature);
    671553        /// \TODO any error?
    672554        return EOK;
    673555}
    674 /*----------------------------------------------------------------------------*/
     556
    675557
    676558/**
    677559 * register address to this device
    678  *
     560 * 
    679561 * @param instance root hub instance
    680562 * @param address new address
     
    682564 */
    683565static int process_address_set_request(rh_t *instance,
    684         uint16_t address) {
     566                uint16_t address){
    685567        instance->address = address;
    686568        return EOK;
    687569}
    688 /*----------------------------------------------------------------------------*/
    689570
    690571/**
     
    698579 */
    699580static int process_request_with_output(rh_t *instance,
    700         usb_transfer_batch_t *request) {
     581                usb_transfer_batch_t *request){
    701582        usb_device_request_setup_packet_t * setup_request =
    702                 (usb_device_request_setup_packet_t*) request->setup_buffer;
    703         if (setup_request->request == USB_DEVREQ_GET_STATUS) {
     583                        (usb_device_request_setup_packet_t*)request->setup_buffer;
     584        if(setup_request->request == USB_DEVREQ_GET_STATUS){
    704585                usb_log_debug("USB_DEVREQ_GET_STATUS\n");
    705586                return process_get_status_request(instance, request);
    706587        }
    707         if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) {
     588        if(setup_request->request == USB_DEVREQ_GET_DESCRIPTOR){
    708589                usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
    709590                return process_get_descriptor_request(instance, request);
    710591        }
    711         if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) {
     592        if(setup_request->request == USB_DEVREQ_GET_CONFIGURATION){
    712593                usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
    713594                return process_get_configuration_request(instance, request);
     
    715596        return ENOTSUP;
    716597}
    717 /*----------------------------------------------------------------------------*/
    718598
    719599/**
     
    727607 */
    728608static int process_request_with_input(rh_t *instance,
    729         usb_transfer_batch_t *request) {
     609                usb_transfer_batch_t *request){
    730610        usb_device_request_setup_packet_t * setup_request =
    731                 (usb_device_request_setup_packet_t*) request->setup_buffer;
     611                        (usb_device_request_setup_packet_t*)request->setup_buffer;
    732612        request->transfered_size = 0;
    733         if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) {
     613        if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR){
    734614                return ENOTSUP;
    735615        }
    736         if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) {
     616        if(setup_request->request == USB_DEVREQ_SET_CONFIGURATION){
    737617                //set and get configuration requests do not have any meaning,
    738618                //only dummy values are returned
     
    741621        return ENOTSUP;
    742622}
    743 /*----------------------------------------------------------------------------*/
    744623
    745624/**
     
    753632 */
    754633static int process_request_without_data(rh_t *instance,
    755         usb_transfer_batch_t *request) {
     634                usb_transfer_batch_t *request){
    756635        usb_device_request_setup_packet_t * setup_request =
    757                 (usb_device_request_setup_packet_t*) request->setup_buffer;
     636                        (usb_device_request_setup_packet_t*)request->setup_buffer;
    758637        request->transfered_size = 0;
    759         if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) {
    760                 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
     638        if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE){
     639                if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){
    761640                        usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    762641                        return process_hub_feature_clear_request(instance,
    763                                 setup_request->value);
    764                 }
    765                 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
     642                                        setup_request->value);
     643                }
     644                if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
    766645                        usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    767646                        return process_port_feature_clear_request(instance,
    768                                 setup_request->value,
    769                                 setup_request->index);
     647                                        setup_request->value,
     648                                        setup_request->index);
    770649                }
    771650                usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
    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) {
     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){
    777656                        usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    778657                        return process_hub_feature_set_request(instance,
    779                                 setup_request->value);
    780                 }
    781                 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
     658                                        setup_request->value);
     659                }
     660                if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
    782661                        usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    783662                        return process_port_feature_set_request(instance,
    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) {
     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){
    792670                usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
    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);
     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);
    798674        return ENOTSUP;
    799675}
    800 /*----------------------------------------------------------------------------*/
    801676
    802677/**
     
    818693 * @return error code
    819694 */
    820 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) {
    821         if (!request->setup_buffer) {
     695static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request){
     696        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                ){
     711                        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                                        );
     729                        opResult = ENOTSUP;
     730                }
     731        }else{
    822732                usb_log_error("root hub received empty transaction?");
    823                 return EINVAL;
    824         }
     733                opResult = EINVAL;
     734        }
     735        return opResult;
     736}
     737
     738/**
     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 */
     745int rh_request(rh_t *instance, usb_transfer_batch_t *request)
     746{
     747        assert(instance);
     748        assert(request);
    825749        int opResult;
    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:
    840                         usb_log_debug("processing request with output\n");
    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                                 );
    864                         opResult = ENOTSUP;
    865         }
    866         return opResult;
    867 }
    868 
     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
     769void 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}
    869774/**
    870775 * @}
  • uspace/drv/ohci/utils/malloc32.h

    rdc4c19e ra49e171  
    3737#include <assert.h>
    3838#include <malloc.h>
    39 #include <errno.h>
    4039#include <mem.h>
    4140#include <as.h>
  • uspace/drv/uhci-hcd/batch.c

    rdc4c19e ra49e171  
    8080 * transaction and callback.
    8181 */
    82 usb_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,
     82usb_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,
    8486    usbhc_iface_transfer_in_callback_t func_in,
    85     usbhc_iface_transfer_out_callback_t func_out, void *arg)
    86 {
    87         assert(ep);
     87    usbhc_iface_transfer_out_callback_t func_out, void *arg, endpoint_t *ep
     88    )
     89{
    8890        assert(func_in == NULL || func_out == NULL);
    8991        assert(func_in != NULL || func_out != NULL);
     
    101103        CHECK_NULL_DISPOSE_RETURN(instance,
    102104            "Failed to allocate batch instance.\n");
    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);
     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);
    108109
    109110
    110111        uhci_batch_t *data = malloc(sizeof(uhci_batch_t));
    111         CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
     112        CHECK_NULL_DISPOSE_RETURN(instance,
     113            "Failed to allocate batch instance.\n");
    112114        bzero(data, sizeof(uhci_batch_t));
    113115        instance->private_data = data;
    114116
    115         data->transfers =
    116             (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
    117         if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     117        data->transfers = (buffer_size + max_packet_size - 1) / max_packet_size;
     118        if (transfer_type == USB_TRANSFER_CONTROL) {
    118119                data->transfers += 2;
    119120        }
     
    177178                            instance, i, data->tds[i].status);
    178179                        td_print_status(&data->tds[i]);
    179                         assert(instance->ep != NULL);
    180 
    181                         endpoint_toggle_set(instance->ep,
    182                             td_toggle(&data->tds[i]));
     180                        if (instance->ep != NULL)
     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

    rdc4c19e ra49e171  
    4444
    4545usb_transfer_batch_t * batch_get(
    46     ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
    47     char *setup_buffer, size_t setup_size,
     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,
    4855    usbhc_iface_transfer_in_callback_t func_in,
    4956    usbhc_iface_transfer_out_callback_t func_out,
    50     void *arg);
     57                void *arg,
     58                endpoint_t *ep
     59                );
    5160
    5261void batch_dispose(usb_transfer_batch_t *instance);
  • uspace/drv/uhci-hcd/hc.c

    rdc4c19e ra49e171  
    240240        usb_log_debug("Initialized device manager.\n");
    241241
    242         ret = usb_endpoint_manager_init(&instance->ep_manager,
    243             BANDWIDTH_AVAILABLE_USB11);
     242        ret =
     243            usb_endpoint_manager_init(&instance->ep_manager,
     244                BANDWIDTH_AVAILABLE_USB11);
    244245        assert(ret == EOK);
    245246
     
    331332            instance->transfers[batch->speed][batch->transfer_type];
    332333        assert(list);
     334        if (batch->transfer_type == USB_TRANSFER_CONTROL) {
     335                usb_device_keeper_use_control(
     336                    &instance->manager, batch->target);
     337        }
    333338        transfer_list_add_batch(list, batch);
    334339
     
    368373                        usb_transfer_batch_t *batch =
    369374                            list_get_instance(item, usb_transfer_batch_t, link);
    370                         usb_transfer_batch_finish(batch);
     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);
    371398                }
    372399        }
  • uspace/drv/uhci-hcd/iface.c

    rdc4c19e ra49e171  
    4141#include "hc.h"
    4242
    43 static inline int setup_batch(
    44     ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
    45     void *data, size_t size, void * setup_data, size_t setup_size,
    46     usbhc_iface_transfer_in_callback_t in,
    47     usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
    48     hc_t **hc, usb_transfer_batch_t **batch)
    49 {
    50         assert(hc);
    51         assert(batch);
    52         assert(fun);
    53         *hc = fun_to_hc(fun);
    54         assert(*hc);
    55 
    56         size_t res_bw;
    57         endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
    58             target.address, target.endpoint, direction, &res_bw);
    59         if (ep == NULL) {
    60                 usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
    61                     target.address, target.endpoint, name);
    62                 return ENOENT;
    63         }
    64 
    65         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;
     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 */
     49static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
     50{
     51        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)
     60                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;
     64try_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 */
     83static 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);
    8192        return EOK;
    8293}
     
    140151/*----------------------------------------------------------------------------*/
    141152static int register_endpoint(
    142     ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
    143     usb_endpoint_t endpoint,
     153    ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
    144154    usb_transfer_type_t transfer_type, usb_direction_t direction,
    145155    size_t max_packet_size, unsigned int interval)
     
    147157        hc_t *hc = fun_to_hc(fun);
    148158        assert(hc);
    149         const size_t size = max_packet_size;
     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;
    150165        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         }
     166
     167        endpoint_t *ep = malloc(sizeof(endpoint_t));
     168        if (ep == NULL)
     169                return ENOMEM;
     170        ret = endpoint_init(ep, address, endpoint, direction,
     171            transfer_type, speed, max_packet_size);
     172        if (ret != EOK) {
     173                free(ep);
     174                return ret;
     175        }
     176
    155177        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    156178            address, endpoint, usb_str_transfer_type(transfer_type),
    157179            usb_str_speed(speed), direction, size, max_packet_size, interval);
    158180
    159 
    160         endpoint_t *ep = malloc(sizeof(endpoint_t));
    161         if (ep == NULL)
    162                 return ENOMEM;
    163         ret = endpoint_init(ep, address, endpoint, direction,
    164             transfer_type, speed, max_packet_size);
    165         if (ret != EOK) {
    166                 free(ep);
    167                 return ret;
    168         }
    169 
    170181        ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    171182        if (ret != EOK) {
    172183                endpoint_destroy(ep);
     184        } else {
     185                usb_device_keeper_add_ep(&hc->manager, address, ep);
    173186        }
    174187        return ret;
     
    191204 * @param[in] fun DDF function that was called.
    192205 * @param[in] target USB device to write to.
     206 * @param[in] max_packet_size maximum size of data packet the device accepts
    193207 * @param[in] data Source of data.
    194208 * @param[in] size Size of data source.
     
    198212 */
    199213static int interrupt_out(
    200     ddf_fun_t *fun, usb_target_t target, void *data,
     214    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
    201215    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    202216{
    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;
     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;
    209251        batch_interrupt_out(batch);
    210         ret = hc_schedule(hc, batch);
     252        const int ret = hc_schedule(hc, batch);
    211253        if (ret != EOK) {
    212254                batch_dispose(batch);
     
    219261 * @param[in] fun DDF function that was called.
    220262 * @param[in] target USB device to write to.
     263 * @param[in] max_packet_size maximum size of data packet the device accepts
    221264 * @param[out] data Data destination.
    222265 * @param[in] size Size of data source.
     
    226269 */
    227270static int interrupt_in(
    228     ddf_fun_t *fun, usb_target_t target, void *data,
     271    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
    229272    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    230273{
    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;
     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;
    237309        batch_interrupt_in(batch);
    238         ret = hc_schedule(hc, batch);
     310        const int ret = hc_schedule(hc, batch);
    239311        if (ret != EOK) {
    240312                batch_dispose(batch);
     
    247319 * @param[in] fun DDF function that was called.
    248320 * @param[in] target USB device to write to.
     321 * @param[in] max_packet_size maximum size of data packet the device accepts
    249322 * @param[in] data Source of data.
    250323 * @param[in] size Size of data source.
     
    254327 */
    255328static int bulk_out(
    256     ddf_fun_t *fun, usb_target_t target, void *data,
     329    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
    257330    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    258331{
    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;
     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;
    265356        batch_bulk_out(batch);
    266         ret = hc_schedule(hc, batch);
     357        const int ret = hc_schedule(hc, batch);
    267358        if (ret != EOK) {
    268359                batch_dispose(batch);
     
    275366 * @param[in] fun DDF function that was called.
    276367 * @param[in] target USB device to write to.
     368 * @param[in] max_packet_size maximum size of data packet the device accepts
    277369 * @param[out] data Data destination.
    278370 * @param[in] size Size of data source.
     
    282374 */
    283375static int bulk_in(
    284     ddf_fun_t *fun, usb_target_t target, void *data,
     376    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
    285377    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    286378{
    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;
     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;
    293402        batch_bulk_in(batch);
    294         ret = hc_schedule(hc, batch);
     403        const int ret = hc_schedule(hc, batch);
    295404        if (ret != EOK) {
    296405                batch_dispose(batch);
     
    303412 * @param[in] fun DDF function that was called.
    304413 * @param[in] target USB device to write to.
     414 * @param[in] max_packet_size maximum size of data packet the device accepts.
    305415 * @param[in] setup_data Data to send with SETUP transfer.
    306416 * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
     
    312422 */
    313423static int control_write(
    314     ddf_fun_t *fun, usb_target_t target,
     424    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
    315425    void *setup_data, size_t setup_size, void *data, size_t size,
    316426    usbhc_iface_transfer_out_callback_t callback, void *arg)
    317427{
    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);
     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);
    326451        batch_control_write(batch);
    327         ret = hc_schedule(hc, batch);
     452        const int ret = hc_schedule(hc, batch);
    328453        if (ret != EOK) {
    329454                batch_dispose(batch);
     
    336461 * @param[in] fun DDF function that was called.
    337462 * @param[in] target USB device to write to.
     463 * @param[in] max_packet_size maximum size of data packet the device accepts.
    338464 * @param[in] setup_data Data to send with SETUP packet.
    339465 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
     
    345471 */
    346472static int control_read(
    347     ddf_fun_t *fun, usb_target_t target,
     473    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
    348474    void *setup_data, size_t setup_size, void *data, size_t size,
    349475    usbhc_iface_transfer_in_callback_t callback, void *arg)
    350476{
    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;
     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;
    358496        batch_control_read(batch);
    359         ret = hc_schedule(hc, batch);
     497        const int ret = hc_schedule(hc, batch);
    360498        if (ret != EOK) {
    361499                batch_dispose(batch);
     
    365503/*----------------------------------------------------------------------------*/
    366504usbhc_iface_t hc_iface = {
     505        .reserve_default_address = reserve_default_address,
     506        .release_default_address = release_default_address,
    367507        .request_address = request_address,
    368508        .bind_address = bind_address,
  • uspace/drv/uhci-hcd/transfer_list.c

    rdc4c19e ra49e171  
    132132}
    133133/*----------------------------------------------------------------------------*/
    134 /** Create list for finished batches.
    135  *
    136  * @param[in] instance List to use.
    137  * @param[in] done list to fill
     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.
    138142 */
    139143void transfer_list_remove_finished(transfer_list_t *instance, link_t *done)
     
    157161        }
    158162        fibril_mutex_unlock(&instance->guard);
     163
    159164}
    160165/*----------------------------------------------------------------------------*/
     
    171176                    list_get_instance(current, usb_transfer_batch_t, link);
    172177                transfer_list_remove_batch(instance, batch);
    173                 usb_transfer_batch_finish_error(batch, EIO);
     178                usb_transfer_batch_finish(batch, EIO);
    174179        }
    175180        fibril_mutex_unlock(&instance->guard);
  • uspace/drv/uhci-rhd/root_hub.h

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

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

    rdc4c19e ra49e171  
    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  */
    58 typedef uint32_t usb_hub_status_t;
    59 
    60 /**
    6151 * set values in request to be it a port status request
    6252 * @param request
     
    6454 */
    6555static inline void usb_hub_set_port_status_request(
    66         usb_device_request_setup_packet_t * request, uint16_t port
    67         ) {
     56usb_device_request_setup_packet_t * request, uint16_t port
     57){
    6858        request->index = port;
    6959        request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS;
     
    7363}
    7464
    75 /**
    76  * set values in request to be it a port status request
    77  * @param request
    78  * @param port
    79  */
    80 static 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 }
    8965
    9066/**
     
    9470 */
    9571static inline usb_device_request_setup_packet_t *
    96 usb_hub_create_port_status_request(uint16_t port) {
     72usb_hub_create_port_status_request(uint16_t port){
    9773        usb_device_request_setup_packet_t * result =
    98                 malloc(sizeof(usb_device_request_setup_packet_t));
    99         usb_hub_set_port_status_request(result, port);
     74                usb_new(usb_device_request_setup_packet_t);
     75        usb_hub_set_port_status_request(result,port);
    10076        return result;
    10177}
    10278
     79
    10380/**
    10481 * set the device request to be a port feature enable request
     
    10885 */
    10986static inline void usb_hub_set_enable_port_feature_request(
    110         usb_device_request_setup_packet_t * request, uint16_t port,
    111         uint16_t feature_selector
    112         ) {
     87usb_device_request_setup_packet_t * request, uint16_t port,
     88                uint16_t feature_selector
     89){
    11390        request->index = port;
    11491        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    125102 */
    126103static inline void usb_hub_set_disable_port_feature_request(
    127         usb_device_request_setup_packet_t * request, uint16_t port,
    128         uint16_t feature_selector
    129         ) {
     104usb_device_request_setup_packet_t * request, uint16_t port,
     105                uint16_t feature_selector
     106){
    130107        request->index = port;
    131108        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    141118 */
    142119static inline void usb_hub_set_enable_port_request(
    143         usb_device_request_setup_packet_t * request, uint16_t port
    144         ) {
     120usb_device_request_setup_packet_t * request, uint16_t port
     121){
    145122        request->index = port;
    146123        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    156133 */
    157134static inline usb_device_request_setup_packet_t *
    158 usb_hub_create_enable_port_request(uint16_t port) {
     135usb_hub_create_enable_port_request(uint16_t port){
    159136        usb_device_request_setup_packet_t * result =
    160                 malloc(sizeof(usb_device_request_setup_packet_t));
    161         usb_hub_set_enable_port_request(result, port);
     137                usb_new(usb_device_request_setup_packet_t);
     138        usb_hub_set_enable_port_request(result,port);
    162139        return result;
    163140}
     
    169146 */
    170147static inline void usb_hub_set_disable_port_request(
    171         usb_device_request_setup_packet_t * request, uint16_t port
    172         ) {
     148usb_device_request_setup_packet_t * request, uint16_t port
     149){
    173150        request->index = port;
    174151        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    184161 */
    185162static inline usb_device_request_setup_packet_t *
    186 usb_hub_create_disable_port_request(uint16_t port) {
     163usb_hub_create_disable_port_request(uint16_t port){
    187164        usb_device_request_setup_packet_t * result =
    188                 malloc(sizeof(usb_device_request_setup_packet_t));
    189         usb_hub_set_disable_port_request(result, port);
     165                usb_new(usb_device_request_setup_packet_t);
     166        usb_hub_set_disable_port_request(result,port);
    190167        return result;
    191168}
     
    197174 */
    198175static inline void usb_hub_set_reset_port_request(
    199         usb_device_request_setup_packet_t * request, uint16_t port
    200         ) {
     176usb_device_request_setup_packet_t * request, uint16_t port
     177){
    201178        request->index = port;
    202179        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    212189 */
    213190static inline usb_device_request_setup_packet_t *
    214 usb_hub_create_reset_port_request(uint16_t port) {
     191usb_hub_create_reset_port_request(uint16_t port){
    215192        usb_device_request_setup_packet_t * result =
    216                 malloc(sizeof(usb_device_request_setup_packet_t));
    217         usb_hub_set_reset_port_request(result, port);
     193                usb_new(usb_device_request_setup_packet_t);
     194        usb_hub_set_reset_port_request(result,port);
    218195        return result;
    219196}
     
    225202 */
    226203static inline void usb_hub_set_power_port_request(
    227         usb_device_request_setup_packet_t * request, uint16_t port
    228         ) {
     204usb_device_request_setup_packet_t * request, uint16_t port
     205){
    229206        request->index = port;
    230207        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    240217 */
    241218static inline void usb_hub_unset_power_port_request(
    242         usb_device_request_setup_packet_t * request, uint16_t port
    243         ) {
     219usb_device_request_setup_packet_t * request, uint16_t port
     220){
    244221        request->index = port;
    245222        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    249226}
    250227
    251 /**
    252  * get i`th bit of port status
    253  *
    254  * @param status
    255  * @param idx
    256  * @return
    257  */
    258 static 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  */
    269 static 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  */
    283 static 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  */
    294 static 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  */
    309 static 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  */
    319 static inline void usb_port_set_dev_connected(usb_port_status_t * status, bool connected) {
    320         usb_port_set_bit(status, 0, connected);
     228
     229/** get i`th bit of port status */
     230static 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 */
     236static 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
     245static inline bool usb_port_dev_connected(usb_port_status_t * status){
     246        return usb_port_get_bit(status,0);
     247}
     248
     249static inline void usb_port_set_dev_connected(usb_port_status_t * status,bool connected){
     250        usb_port_set_bit(status,0,connected);
    321251}
    322252
    323253//port enabled
    324 
    325 /**
    326  * port enabled getter for port status
    327  *
    328  * @param status
    329  * @return true if the port is enabled
    330  */
    331 static 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  */
    341 static inline void usb_port_set_enabled(usb_port_status_t * status, bool enabled) {
    342         usb_port_set_bit(status, 1, enabled);
     254static inline bool usb_port_enabled(usb_port_status_t * status){
     255        return usb_port_get_bit(status,1);
     256}
     257
     258static inline void usb_port_set_enabled(usb_port_status_t * status,bool enabled){
     259        usb_port_set_bit(status,1,enabled);
    343260}
    344261
    345262//port suspended
    346 /**
    347  * port suspended getter for port status
    348  *
    349  * @param status
    350  * @return true if port is suspended
    351  */
    352 static 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  */
    362 static inline void usb_port_set_suspended(usb_port_status_t * status, bool suspended) {
    363         usb_port_set_bit(status, 2, suspended);
     263static inline bool usb_port_suspended(usb_port_status_t * status){
     264        return usb_port_get_bit(status,2);
     265}
     266
     267static inline void usb_port_set_suspended(usb_port_status_t * status,bool suspended){
     268        usb_port_set_bit(status,2,suspended);
    364269}
    365270
    366271//over currect
    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  */
    373 static 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  */
    383 static inline void usb_port_set_over_current(usb_port_status_t * status, bool value) {
    384         usb_port_set_bit(status, 3, value);
     272static inline bool usb_port_over_current(usb_port_status_t * status){
     273        return usb_port_get_bit(status,3);
     274}
     275
     276static inline void usb_port_set_over_current(usb_port_status_t * status,bool value){
     277        usb_port_set_bit(status,3,value);
    385278}
    386279
    387280//port reset
    388 /**
    389  * port reset indicator getter for port status
    390  *
    391  * @param status
    392  * @return true if port is reset
    393  */
    394 static 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  */
    404 static inline void usb_port_set_reset(usb_port_status_t * status, bool value) {
    405         usb_port_set_bit(status, 4, value);
     281static inline bool usb_port_reset(usb_port_status_t * status){
     282        return usb_port_get_bit(status,4);
     283}
     284
     285static inline void usb_port_set_reset(usb_port_status_t * status,bool value){
     286        usb_port_set_bit(status,4,value);
    406287}
    407288
    408289//powered
    409 /**
    410  * power state getter for port status
    411  *
    412  * @param status
    413  * @return true if port is powered
    414  */
    415 static 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  */
    425 static 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
     290static inline bool usb_port_powered(usb_port_status_t * status){
     291        return usb_port_get_bit(status,8);
     292}
     293
     294static inline void usb_port_set_powered(usb_port_status_t * status,bool powered){
     295        usb_port_set_bit(status,8,powered);
     296}
    430297
    431298//low speed device attached
    432 /**
    433  * low speed device on the port indicator
    434  *
    435  * @param status
    436  * @return true if low speed device is attached
    437  */
    438 static 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  */
    448 static 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  */
    459 static 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  */
    469 static 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  */
    479 static inline usb_speed_t usb_port_speed(usb_port_status_t status) {
    480         if (usb_port_low_speed(status))
     299static inline bool usb_port_low_speed(usb_port_status_t * status){
     300        return usb_port_get_bit(status,9);
     301}
     302
     303static 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
     308static inline bool usb_port_high_speed(usb_port_status_t * status){
     309        return usb_port_get_bit(status,10);
     310}
     311
     312static 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
     316static inline usb_speed_t usb_port_speed(usb_port_status_t * status){
     317        if(usb_port_low_speed(status))
    481318                return USB_SPEED_LOW;
    482         if (usb_port_high_speed(status))
     319        if(usb_port_high_speed(status))
    483320                return USB_SPEED_HIGH;
    484321        return USB_SPEED_FULL;
    485322}
    486323
    487 #if 0
     324
    488325//connect change
    489 /**
    490  * port connect change indicator
    491  *
    492  * @param status
    493  * @return true if connection has changed
    494  */
    495 static 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  */
    504 static inline void usb_port_set_connect_change(usb_port_status_t * status, bool change) {
    505         usb_port_set_bit(status, 16, change);
     326static inline bool usb_port_connect_change(usb_port_status_t * status){
     327        return usb_port_get_bit(status,16);
     328}
     329
     330static inline void usb_port_set_connect_change(usb_port_status_t * status,bool change){
     331        usb_port_set_bit(status,16,change);
    506332}
    507333
    508334//port enable change
    509 /**
    510  * port enable change for port status
    511  *
    512  * @param status
    513  * @return true if the port has been enabled/disabled
    514  */
    515 static 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  */
    525 static inline void usb_port_set_enabled_change(usb_port_status_t * status, bool change) {
    526         usb_port_set_bit(status, 17, change);
     335static inline bool usb_port_enabled_change(usb_port_status_t * status){
     336        return usb_port_get_bit(status,17);
     337}
     338
     339static inline void usb_port_set_enabled_change(usb_port_status_t * status,bool change){
     340        usb_port_set_bit(status,17,change);
    527341}
    528342
    529343//suspend change
    530 /**
    531  * port suspend change for port status
    532  *
    533  * @param status
    534  * @return ture if suspend status has changed
    535  */
    536 static 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  */
    546 static inline void usb_port_set_suspend_change(usb_port_status_t * status, bool change) {
    547         usb_port_set_bit(status, 18, change);
     344static inline bool usb_port_suspend_change(usb_port_status_t * status){
     345        return usb_port_get_bit(status,18);
     346}
     347
     348static inline void usb_port_set_suspend_change(usb_port_status_t * status,bool change){
     349        usb_port_set_bit(status,18,change);
    548350}
    549351
    550352//over current change
    551 /**
    552  * over current change indicator
    553  *
    554  * @param status
    555  * @return true if over-current condition on port has changed
    556  */
    557 static 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  */
    567 static inline void usb_port_set_overcurrent_change(usb_port_status_t * status, bool change) {
    568         usb_port_set_bit(status, 19, change);
     353static inline bool usb_port_overcurrent_change(usb_port_status_t * status){
     354        return usb_port_get_bit(status,19);
     355}
     356
     357static inline void usb_port_set_overcurrent_change(usb_port_status_t * status,bool change){
     358        usb_port_set_bit(status,19,change);
    569359}
    570360
    571361//reset change
    572 /**
    573  * port reset change indicator
    574  * @param status
    575  * @return true if port has been reset
    576  */
    577 static 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  */
    587 static 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  */
    598 static 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  */
    608 static 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  */
    620 static 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  */
    630 static 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  */
    643 static 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  */
    653 static 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  */
    665 static 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  */
    675 static 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
     362static inline bool usb_port_reset_completed(usb_port_status_t * status){
     363        return usb_port_get_bit(status,20);
     364}
     365
     366static inline void usb_port_set_reset_completed(usb_port_status_t * status,bool completed){
     367        usb_port_set_bit(status,20,completed);
     368}
     369
    680370
    681371
  • uspace/drv/usbhub/ports.c

    rdc4c19e ra49e171  
    3333 * Hub ports functions.
    3434 */
    35 
    36 #include <bool.h>
     35#include "port_status.h"
     36#include <inttypes.h>
    3737#include <errno.h>
    3838#include <str_error.h>
    39 #include <inttypes.h>
    40 #include <fibril_synch.h>
    41 
     39#include <usb/request.h>
    4240#include <usb/debug.h>
    4341
    44 #include "ports.h"
    45 #include "usbhub.h"
    46 #include "usbhub_private.h"
    47 #include "port_status.h"
    48 
     42/** Retrieve port status.
     43 *
     44 * @param[in] ctrl_pipe Control pipe to use.
     45 * @param[in] port Port number (starting at 1).
     46 * @param[out] status Where to store the port status.
     47 * @return Error code.
     48 */
     49static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
     50    usb_port_status_t *status)
     51{
     52        size_t recv_size;
     53        usb_device_request_setup_packet_t request;
     54        usb_port_status_t status_tmp;
     55
     56        usb_hub_set_port_status_request(&request, port);
     57        int rc = usb_pipe_control_read(ctrl_pipe,
     58            &request, sizeof(usb_device_request_setup_packet_t),
     59            &status_tmp, sizeof(status_tmp), &recv_size);
     60        if (rc != EOK) {
     61                return rc;
     62        }
     63
     64        if (recv_size != sizeof (status_tmp)) {
     65                return ELIMIT;
     66        }
     67
     68        if (status != NULL) {
     69                *status = status_tmp;
     70        }
     71
     72        return EOK;
     73}
    4974
    5075/** Information for fibril for device discovery. */
     
    5580};
    5681
    57 static void usb_hub_removed_device(
    58         usb_hub_info_t * hub, uint16_t port);
    59 
    60 static void usb_hub_port_reset_completed(usb_hub_info_t * hub,
    61         uint16_t port, uint32_t status);
    62 
    63 static void usb_hub_port_over_current(usb_hub_info_t * hub,
    64         uint16_t port, uint32_t status);
    65 
    66 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
    67     usb_port_status_t *status);
    68 
    69 static int enable_port_callback(int port_no, void *arg);
    70 
    71 static int add_device_phase1_worker_fibril(void *arg);
    72 
    73 static 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  */
    83 void 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  */
    155 static 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  */
    210 static 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  */
    236 static 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 }
    255 
    256 /** Retrieve port status.
    257  *
    258  * @param[in] ctrl_pipe Control pipe to use.
    259  * @param[in] port Port number (starting at 1).
    260  * @param[out] status Where to store the port status.
    261  * @return Error code.
    262  */
    263 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
    264     usb_port_status_t *status)
    265 {
    266         size_t recv_size;
    267         usb_device_request_setup_packet_t request;
    268         usb_port_status_t status_tmp;
    269 
    270         usb_hub_set_port_status_request(&request, port);
    271         int rc = usb_pipe_control_read(ctrl_pipe,
    272             &request, sizeof(usb_device_request_setup_packet_t),
    273             &status_tmp, sizeof(status_tmp), &recv_size);
    274         if (rc != EOK) {
    275                 return rc;
    276         }
    277 
    278         if (recv_size != sizeof (status_tmp)) {
    279                 return ELIMIT;
    280         }
    281 
    282         if (status != NULL) {
    283                 *status = status_tmp;
    284         }
    285 
    286         return EOK;
    287 }
    288 
    28982/** Callback for enabling a specific port.
    29083 *
     
    29891static int enable_port_callback(int port_no, void *arg)
    29992{
    300         usb_hub_info_t *hub = arg;
     93        usb_hub_info_t *hub = (usb_hub_info_t *) arg;
    30194        int rc;
    30295        usb_device_request_setup_packet_t request;
     
    329122        }
    330123
    331         if (my_port->reset_okay) {
    332                 return EOK;
    333         } else {
    334                 return ESTALL;
    335         }
     124        return EOK;
    336125}
    337126
     
    367156        data->hub->ports[data->port].attached_device.address = new_address;
    368157
    369         usb_log_info("Detected new device on `%s' (port %zu), "
     158        usb_log_info("Detected new device on `%s' (port %zu), " \
    370159            "address %d (handle %" PRIun ").\n",
    371160            data->hub->usb_device->ddf_dev->name, data->port,
     
    377166        return EOK;
    378167}
    379 
    380168
    381169/** Start device adding when connection change is detected.
     
    388176 * @return Error code.
    389177 */
    390 static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
     178static int add_device_phase1_new_fibril(usb_hub_info_t *hub, size_t port,
    391179    usb_speed_t speed)
    392180{
     
    425213}
    426214
     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 */
     220static 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 */
     302bool 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
     321leave:
     322        /* FIXME: proper interval. */
     323        async_usleep(1000 * 1000 * 10 );
     324
     325        return true;
     326}
     327
     328
    427329/**
    428330 * @}
  • uspace/drv/usbhub/ports.h

    rdc4c19e ra49e171  
    3636#define DRV_USBHUB_PORTS_H
    3737
    38 #include <usb/devdrv.h>
     38#include <ipc/devman.h>
     39#include <usb/usb.h>
     40#include <ddf/driver.h>
     41#include <fibril_synch.h>
     42
    3943#include <usb/hub.h>
    4044
    41 typedef struct usb_hub_info_t usb_hub_info_t;
     45#include <usb/pipes.h>
     46#include <usb/devdrv.h>
    4247
    4348/** Information about single port on a hub. */
     
    5156         */
    5257        bool reset_completed;
    53         /** Whether to announce the port reset as successful. */
    54         bool reset_okay;
    5558
    5659        /** Information about attached device. */
     
    6972}
    7073
    71 
    72 void usb_hub_process_interrupt(usb_hub_info_t * hub,
    73         uint16_t port);
    74 
     74bool hub_port_changes_callback(usb_device_t *, uint8_t *, size_t, void *);
    7575
    7676
  • uspace/drv/usbhub/usbhub.c

    rdc4c19e ra49e171  
    3737#include <errno.h>
    3838#include <str_error.h>
    39 #include <inttypes.h>
    4039
    4140#include <usb_iface.h>
     
    5453#include "usb/classes/classes.h"
    5554
    56 
    57 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev);
    58 
    59 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info);
    60 
    61 static int usb_hub_set_configuration(usb_hub_info_t * hub_info);
    62 
    63 static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info);
    64 
    65 static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
    66     usb_hub_status_t status);
    67 
    68 static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
    69     usb_hub_status_t status);
    70 
    71 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info);
    72 
    73 
    74 /// \TODO malloc checking
     55static int usb_hub_trigger_connecting_non_removable_devices(
     56                usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor);
     57
    7558
    7659//*********************************************
     
    8164
    8265/**
    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  */
    90 int 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  */
    152 bool 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         }
    174 leave:
    175         /* FIXME: proper interval. */
    176         async_usleep(1000 * 1000 * 10);
    177 
    178         return true;
    179 }
    180 
    181 
    182 //*********************************************
    183 //
    184 //  support functions
    185 //
    186 //*********************************************
    187 
    188 /**
    18966 * create usb_hub_info_t structure
    19067 *
     
    19471 */
    19572static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) {
    196         usb_hub_info_t * result = malloc(sizeof(usb_hub_info_t));
    197         if (!result) return NULL;
     73        usb_hub_info_t * result = usb_new(usb_hub_info_t);
     74        if(!result) return NULL;
    19875        result->usb_device = usb_dev;
    19976        result->status_change_pipe = usb_dev->pipes[0].pipe;
     
    21390 * @return error code
    21491 */
    215 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) {
     92static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info){
    21693        // get hub descriptor
    21794        usb_log_debug("creating serialized descriptor\n");
    21895        void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
    21996        usb_hub_descriptor_t * descriptor;
    220         int opResult;
    221 
     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         */
    222107        size_t received_size;
    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);
     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);
    227113
    228114        if (opResult != EOK) {
    229                 usb_log_error("failed when receiving hub descriptor, "
    230                     "badcode = %d\n",
    231                     opResult);
     115                usb_log_error("failed when receiving hub descriptor, badcode = %d\n",
     116                                opResult);
    232117                free(serialized_descriptor);
    233118                return opResult;
     
    235120        usb_log_debug2("deserializing descriptor\n");
    236121        descriptor = usb_deserialize_hub_desriptor(serialized_descriptor);
    237         if (descriptor == NULL) {
     122        if(descriptor==NULL){
    238123                usb_log_warning("could not deserialize descriptor \n");
    239124                return opResult;
    240125        }
    241         usb_log_debug("setting port count to %d\n", descriptor->ports_count);
     126        usb_log_debug("setting port count to %d\n",descriptor->ports_count);
    242127        hub_info->port_count = descriptor->ports_count;
    243         /// \TODO this is not semantically correct
    244         hub_info->ports = malloc(
    245             sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
     128        hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1));
    246129        size_t port;
    247130        for (port = 0; port < hub_info->port_count + 1; port++) {
    248131                usb_hub_port_init(&hub_info->ports[port]);
    249132        }
     133        //handle non-removable devices
     134        usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor);
    250135        usb_log_debug2("freeing data\n");
    251136        free(serialized_descriptor);
     
    254139        return EOK;
    255140}
    256 
    257141/**
    258142 * Set configuration of hub
     
    263147 * @return error code
    264148 */
    265 static int usb_hub_set_configuration(usb_hub_info_t * hub_info) {
     149static int usb_hub_set_configuration(usb_hub_info_t * hub_info){
    266150        //device descriptor
    267151        usb_standard_device_descriptor_t *std_descriptor
     
    269153        usb_log_debug("hub has %d configurations\n",
    270154            std_descriptor->configuration_count);
    271         if (std_descriptor->configuration_count < 1) {
     155        if(std_descriptor->configuration_count<1){
    272156                usb_log_error("there are no configurations available\n");
    273157                return EINVAL;
     
    289173        }
    290174        usb_log_debug("\tused configuration %d\n",
    291             config_descriptor->configuration_number);
     175                        config_descriptor->configuration_number);
    292176
    293177        return EOK;
     
    295179
    296180/**
    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
     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
    303186 * @return error code
    304187 */
    305 static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info){
     188int 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
    306233        /*
    307234         * The processing will require opened control pipe and connection
     
    312239         * auto destruction, this could work better.
    313240         */
    314         int rc = usb_pipe_start_session(hub_info->control_pipe);
     241        rc = usb_pipe_start_session(&usb_dev->ctrl_pipe);
    315242        if (rc != EOK) {
    316243                usb_log_error("Failed to start session on control pipe: %s.\n",
    317244                    str_error(rc));
    318                 return rc;
     245                goto leave;
    319246        }
    320247        rc = usb_hc_connection_open(&hub_info->connection);
    321248        if (rc != EOK) {
    322                 usb_pipe_end_session(hub_info->control_pipe);
     249                usb_pipe_end_session(&usb_dev->ctrl_pipe);
    323250                usb_log_error("Failed to open connection to HC: %s.\n",
    324251                    str_error(rc));
    325                 return rc;
     252                goto leave;
    326253        }
    327254
    328255        rc = usb_device_auto_poll(hub_info->usb_device, 0,
    329             hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
     256            hub_port_changes_callback, ((hub_info->port_count+1) / 8) + 1,
    330257            NULL, hub_info);
    331258        if (rc != EOK) {
     
    339266            hub_info->usb_device->ddf_dev->name, hub_info->port_count);
    340267        return EOK;
    341 }
     268
     269leave:
     270        free(hub_info);
     271
     272        return rc;
     273}
     274
    342275
    343276//*********************************************
    344277//
    345 //  change handling functions
     278//  hub driver code, main loop and port handling
    346279//
    347280//*********************************************
    348281
    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
     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
    356289 * @return error code
    357290 */
    358 static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
    359     usb_hub_status_t status) {
     291static 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;
    360296        int opResult;
    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  */
    388 static 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);
     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                                        );
    405312                        if (opResult != EOK) {
    406                                 usb_log_error("cannot power on port %d;  %d\n",
    407                                     port, opResult);
     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");
    408345                        }
    409346                }
    410347        }
    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  */
    421 static 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;
     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 */
     391static 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 */
     410void 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 */
     450void usb_hub_over_current( usb_hub_info_t * hub,
     451                uint16_t port){
    424452        int opResult;
    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 }
     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
    456461
    457462/**
  • uspace/drv/usbhub/usbhub.h

    rdc4c19e ra49e171  
    3737
    3838#include <ipc/devman.h>
     39#include <usb/usb.h>
    3940#include <ddf/driver.h>
    4041
     42#define NAME "usbhub"
     43
    4144#include <usb/hub.h>
    42 #include <usb/classes/hub.h>
    4345
    4446#include <usb/pipes.h>
    4547#include <usb/devdrv.h>
    46 
    47 #include <fibril_synch.h>
    48 
    49 #define NAME "usbhub"
    5048
    5149#include "ports.h"
     
    5452
    5553/** Information about attached hub. */
    56 struct usb_hub_info_t{
     54typedef struct {
    5755        /** Number of ports. */
    5856        size_t port_count;
    5957
    60         /** attached device handles, for each port one */
     58        /** Ports. */
    6159        usb_hub_port_t *ports;
    62 
     60       
    6361        /** connection to hcd */
    6462        usb_hc_connection_t connection;
     
    8987        /** generic usb device data*/
    9088        usb_device_t * usb_device;
    91 };
     89} usb_hub_info_t;
    9290
    93 //int usb_hub_control_loop(void * hub_info_param);
     91/**
     92 * function running the hub-controlling loop.
     93 * @param hub_info_param hub info pointer
     94 */
     95int 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 */
     103int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
     104
     105void usb_hub_removed_device(usb_hub_info_t *, uint16_t);
     106void usb_hub_over_current(usb_hub_info_t *, uint16_t);
    94107
    95108int usb_hub_add_device(usb_device_t * usb_dev);
    96 
    97 bool hub_port_changes_callback(usb_device_t *dev,
    98     uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);
    99109
    100110#endif
  • uspace/drv/usbhub/usbhub_private.h

    rdc4c19e ra49e171  
    5454//
    5555//************
     56#define usb_new(type) (type*)malloc(sizeof(type))
    5657
    5758
     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 */
    5868usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device);
    5969
     
    100110
    101111/**
    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  */
    110 static 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  */
    133 static 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  */
    154 static 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 /**
    169112 * create uint8_t array with serialized descriptor
    170113 *
  • uspace/drv/usbhub/utils.c

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

    rdc4c19e ra49e171  
    5555        int rc;
    5656
    57         rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
     57        rc = usb_pipe_start_session(&dev->ctrl_pipe);
    5858        if (rc != EOK) {
    59                 usb_log_error("Failed to start transfer on control pipe: %s.\n",
     59                usb_log_error("Failed to start session on control pipe: %s.\n",
    6060                    str_error(rc));
    6161                return rc;
     
    6464        bool accept = usbmid_explore_device(dev);
    6565
    66         usb_pipe_end_long_transfer(&dev->ctrl_pipe);
     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        }
    6771
    6872        if (!accept) {
  • uspace/drv/vhc/connhost.c

    rdc4c19e ra49e171  
    257257
    258258static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
     259    size_t max_packet_size,
    259260    void *data, size_t size,
    260261    usbhc_iface_transfer_out_callback_t callback, void *arg)
     
    266267
    267268static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
     269    size_t max_packet_size,
    268270    void *data, size_t size,
    269271    usbhc_iface_transfer_in_callback_t callback, void *arg)
     
    275277
    276278static int control_write(ddf_fun_t *fun, usb_target_t target,
     279    size_t max_packet_size,
    277280    void *setup_packet, size_t setup_packet_size,
    278281    void *data, size_t data_size,
     
    292295
    293296static int control_read(ddf_fun_t *fun, usb_target_t target,
     297    size_t max_packet_size,
    294298    void *setup_packet, size_t setup_packet_size,
    295299    void *data, size_t data_size,
     
    324328}
    325329
     330static 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
     336static int release_default_address(ddf_fun_t *fun)
     337{
     338        usb_address_keeping_release_default(&addresses);
     339        return EOK;
     340}
     341
    326342static int request_address(ddf_fun_t *fun, usb_speed_t ignored,
    327343    usb_address_t *address)
     
    376392
    377393usbhc_iface_t vhc_iface = {
     394        .reserve_default_address = reserve_default_address,
     395        .release_default_address = release_default_address,
    378396        .request_address = request_address,
    379397        .bind_address = bind_address,
  • uspace/lib/drv/generic/remote_usbhc.c

    rdc4c19e ra49e171  
    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 *);
     52static void remote_usbhc_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     53static void remote_usbhc_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5254static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5355static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     
    5961/** Remote USB host controller interface operations. */
    6062static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
     63        remote_usbhc_reserve_default_address,
     64        remote_usbhc_release_default_address,
     65
    6166        remote_usbhc_request_address,
    6267        remote_usbhc_bind_address,
     
    124129}
    125130
     131void 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
     148void 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
    126163void remote_usbhc_request_address(ddf_fun_t *fun, void *iface,
    127164    ipc_callid_t callid, ipc_call_t *call)
     
    233270        }
    234271
     272        size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    235273        usb_target_t target = {
    236274                .address = DEV_IPC_GET_ARG1(*call),
     
    262300        trans->size = len;
    263301
    264         rc = transfer_func(fun, target,
     302        rc = transfer_func(fun, target, max_packet_size,
    265303            buffer, len,
    266304            callback_out, trans);
     
    288326        }
    289327
     328        size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    290329        usb_target_t target = {
    291330                .address = DEV_IPC_GET_ARG1(*call),
     
    309348        trans->size = len;
    310349
    311         int rc = transfer_func(fun, target,
     350        int rc = transfer_func(fun, target, max_packet_size,
    312351            trans->buffer, len,
    313352            callback_in, trans);
     
    375414        };
    376415        size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
     416        size_t max_packet_size = DEV_IPC_GET_ARG4(*call);
    377417
    378418        int rc;
     
    410450        trans->size = data_buffer_len;
    411451
    412         rc = usb_iface->control_write(fun, target,
     452        rc = usb_iface->control_write(fun, target, max_packet_size,
    413453            setup_packet, setup_packet_len,
    414454            data_buffer, data_buffer_len,
     
    437477                .endpoint = DEV_IPC_GET_ARG2(*call)
    438478        };
     479        size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
    439480
    440481        int rc;
     
    474515        }
    475516
    476         rc = usb_iface->control_read(fun, target,
     517        rc = usb_iface->control_read(fun, target, max_packet_size,
    477518            setup_packet, setup_packet_len,
    478519            trans->buffer, trans->size,
     
    496537        }
    497538
    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,
     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,
    526556            transfer_type, direction, max_packet_size, interval);
    527557
  • uspace/lib/drv/include/usbhc_iface.h

    rdc4c19e ra49e171  
    6666 *   - argument #1 is target address
    6767 *   - argument #2 is target endpoint
     68 *   - argument #3 is max packet size of the endpoint
    6869 * - this call is immediately followed by IPC data read (async version)
    6970 * - the call is not answered until the device returns some data (or until
     
    8485 */
    8586typedef 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
    86102        /** Asks for address assignment by host controller.
    87103         * Answer:
     
    153169        /** Register endpoint attributes at host controller.
    154170         * This is used to reserve portion of USB bandwidth.
    155          * When speed is invalid, speed of the device is used.
    156171         * Parameters:
    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
     172         * - USB address + endpoint number (ADDR * 256 + EP)
     173         * - transfer type + direction (TYPE * 256 + DIR)
     174         * - maximum packet size
     175         * - interval (in milliseconds)
    163176         * Answer:
    164177         * - EOK - reservation successful
     
    189202
    190203/** Out transfer processing function prototype. */
    191 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t,
     204typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, size_t,
    192205    void *, size_t,
    193206    usbhc_iface_transfer_out_callback_t, void *);
     
    197210
    198211/** In transfer processing function prototype. */
    199 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t,
     212typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, size_t,
    200213    void *, size_t,
    201214    usbhc_iface_transfer_in_callback_t, void *);
     
    209222        int (*release_address)(ddf_fun_t *, usb_address_t);
    210223
    211         int (*register_endpoint)(ddf_fun_t *,
    212             usb_address_t, usb_speed_t, usb_endpoint_t,
     224        int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
    213225            usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
    214226        int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
     
    222234
    223235        int (*control_write)(ddf_fun_t *, usb_target_t,
     236            size_t,
    224237            void *, size_t, void *, size_t,
    225238            usbhc_iface_transfer_out_callback_t, void *);
    226239
    227240        int (*control_read)(ddf_fun_t *, usb_target_t,
     241            size_t,
    228242            void *, size_t, void *, size_t,
    229243            usbhc_iface_transfer_in_callback_t, void *);
  • uspace/lib/usb/Makefile

    rdc4c19e ra49e171  
    4343        src/hidparser.c \
    4444        src/hub.c \
    45         src/pipepriv.c \
    4645        src/pipes.c \
    4746        src/pipesinit.c \
  • uspace/lib/usb/include/usb/classes/hub.h

    rdc4c19e ra49e171  
    4343 */
    4444typedef enum {
    45         USB_HUB_FEATURE_HUB_LOCAL_POWER = 0,
    46         USB_HUB_FEATURE_HUB_OVER_CURRENT = 1,
    4745        USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0,
    4846        USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1,
     
    6159        /* USB_HUB_FEATURE_ = , */
    6260} usb_hub_class_feature_t;
    63 
    6461
    6562/** Header of standard hub descriptor without the "variadic" part. */
  • uspace/lib/usb/include/usb/devdrv.h

    rdc4c19e ra49e171  
    169169    usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
    170170
    171 int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
    172 int 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 *);
    175 int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
    176 
    177 size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t);
    178 
    179171#endif
    180172/**
  • uspace/lib/usb/include/usb/host/batch.h

    rdc4c19e ra49e171  
    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);
    95 
    96 static 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 }
     94void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error);
    10395
    10496#endif
  • uspace/lib/usb/include/usb/host/device_keeper.h

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

    rdc4c19e ra49e171  
    3939#include <bool.h>
    4040#include <adt/list.h>
    41 #include <fibril_synch.h>
    42 
    4341#include <usb/usb.h>
    4442
     
    5048        usb_speed_t speed;
    5149        size_t max_packet_size;
     50        bool active;
    5251        unsigned toggle:1;
    53         fibril_mutex_t guard;
    54         fibril_condvar_t avail;
    55         volatile bool active;
     52        link_t same_device_eps;
    5653} endpoint_t;
    5754
     
    6259void endpoint_destroy(endpoint_t *instance);
    6360
    64 void endpoint_use(endpoint_t *instance);
    65 
    66 void endpoint_release(endpoint_t *instance);
    67 
    6861int endpoint_toggle_get(endpoint_t *instance);
    6962
    7063void endpoint_toggle_set(endpoint_t *instance, int toggle);
    7164
    72 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target);
     65void endpoint_toggle_reset(link_t *ep);
     66
     67void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn);
     68
    7369#endif
    7470/**
  • uspace/lib/usb/include/usb/host/usb_endpoint_manager.h

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

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

    rdc4c19e ra49e171  
    4242#include <ipc/devman.h>
    4343#include <ddf/driver.h>
    44 #include <fibril_synch.h>
    4544
    4645/** Abstraction of a physical connection to the device.
     
    6059 * This endpoint must be bound with existing usb_device_connection_t
    6160 * (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.
    6761 */
    6862typedef struct {
    69         /** Guard of the whole pipe. */
    70         fibril_mutex_t guard;
    71 
    7263        /** The connection used for sending the data. */
    7364        usb_device_connection_t *wire;
     
    8778        /** Phone to the host controller.
    8879         * 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].
    9380         */
    9481        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;
    10182} usb_pipe_t;
    10283
     
    153134int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    154135    size_t, uint8_t *, size_t, usb_device_connection_t *);
    155 int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t,
    156     unsigned int, usb_hc_connection_t *);
    157136int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);
    158137int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
     
    161140int usb_pipe_end_session(usb_pipe_t *);
    162141bool usb_pipe_is_session_started(usb_pipe_t *);
    163 
    164 int usb_pipe_start_long_transfer(usb_pipe_t *);
    165 void usb_pipe_end_long_transfer(usb_pipe_t *);
    166142
    167143int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *);
  • uspace/lib/usb/include/usb/usb.h

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

    rdc4c19e ra49e171  
    7272}
    7373
     74/** Log out of memory error on given device.
     75 *
     76 * @param dev Device causing the trouble.
     77 */
     78static 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
    7484/** Count number of pipes the driver expects.
    7585 *
     
    98108 */
    99109static int initialize_other_pipes(usb_endpoint_description_t **endpoints,
    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,
     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,
    106146            dev->descriptors.configuration, dev->descriptors.configuration_size,
    107             dev->interface_no, alternate_setting,
    108             &pipes, &pipes_count);
    109 
     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);
    110157        if (rc != EOK) {
    111158                usb_log_error(
    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;
     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;
    119187
    120188        return EOK;
     189
     190rollback:
     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;
    121199}
    122200
     
    161239
    162240        /*
    163          * We will do some querying of the device, it is worth to prepare
    164          * the long transfer.
     241         * For further actions, we need open session on default control pipe.
    165242         */
    166         rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
    167         if (rc != EOK) {
    168                 usb_log_error("Failed to start transfer: %s.\n",
     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",
    169246                    str_error(rc));
    170247                return rc;
    171248        }
    172249
    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",
     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",
    179265                    dev->ddf_dev->name, str_error(rc));
    180266                return rc;
    181267        }
    182268
    183 
    184269        if (driver->endpoints != NULL) {
    185                 rc = initialize_other_pipes(driver->endpoints, dev, 0);
    186         }
    187 
    188         usb_pipe_end_long_transfer(&dev->ctrl_pipe);
     270                rc = initialize_other_pipes(driver->endpoints, dev);
     271        }
     272
     273        /* No checking here. */
     274        usb_pipe_end_session(&dev->ctrl_pipe);
    189275
    190276        /* Rollback actions. */
     
    205291 * @return Number of alternate interfaces for @p interface_no interface.
    206292 */
    207 size_t usb_interface_count_alternates(uint8_t *config_descr,
    208     size_t config_descr_size, uint8_t interface_no)
     293static size_t count_alternate_interfaces(uint8_t *config_descr,
     294    size_t config_descr_size, int interface_no)
    209295{
    210296        assert(config_descr != NULL);
    211         assert(config_descr_size > 0);
    212 
    213297        usb_dp_parser_t dp_parser = {
    214298                .nesting = usb_dp_standard_descriptor_nesting
     
    259343
    260344        alternates->alternative_count
    261             = usb_interface_count_alternates(dev->descriptors.configuration,
     345            = count_alternate_interfaces(dev->descriptors.configuration,
    262346            dev->descriptors.configuration_size, dev->interface_no);
    263347
     
    373457static int destroy_current_pipes(usb_device_t *dev)
    374458{
    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 
     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);
    381491        dev->pipes = NULL;
    382492        dev->pipes_count = 0;
     
    425535
    426536        /* Create new pipes. */
    427         rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting);
     537        rc = initialize_other_pipes(endpoints, dev);
    428538
    429539        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  */
    438 int 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  */
    485 int 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          */
    574 rollback_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          */
    588 rollback_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  */
    605 int 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;
    641540}
    642541
  • uspace/lib/usb/src/devpoll.c

    rdc4c19e ra49e171  
    7777                int rc;
    7878
     79                rc = usb_pipe_start_session(pipe);
     80                if (rc != EOK) {
     81                        failed_attempts++;
     82                        continue;
     83                }
     84
    7985                size_t actual_size;
    8086                rc = usb_pipe_read(pipe, polling_data->buffer,
    8187                    polling_data->request_size, &actual_size);
    8288
     89                /* Quit the session regardless of errors. */
     90                usb_pipe_end_session(pipe);
    8391               
    8492//              if (rc == ESTALL) {
  • uspace/lib/usb/src/host/batch.c

    rdc4c19e ra49e171  
    6363        instance->transfer_type = transfer_type;
    6464        instance->speed = speed;
    65         instance->direction = ep->direction;
     65        instance->direction = USB_DIRECTION_BOTH;
    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);
    8281}
    8382/*----------------------------------------------------------------------------*/
     
    8786 *
    8887 */
    89 void usb_transfer_batch_finish(usb_transfer_batch_t *instance)
     88void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error)
    9089{
    9190        assert(instance);
    92         assert(instance->ep);
    93         endpoint_release(instance->ep);
     91        instance->error = error;
    9492        instance->next_step(instance);
    9593}
  • uspace/lib/usb/src/host/device_keeper.c

    rdc4c19e ra49e171  
    5454        for (; i < USB_ADDRESS_COUNT; ++i) {
    5555                instance->devices[i].occupied = false;
     56                instance->devices[i].control_used = 0;
    5657                instance->devices[i].handle = 0;
    57                 instance->devices[i].speed = USB_SPEED_MAX;
    58         }
    59         // TODO: is this hack enough?
    60         // (it is needed to allow smooth registration at default address)
    61         instance->devices[0].occupied = true;
     58                list_initialize(&instance->devices[i].endpoints);
     59        }
     60}
     61/*----------------------------------------------------------------------------*/
     62void 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);
    6270}
    6371/*----------------------------------------------------------------------------*/
     
    94102}
    95103/*----------------------------------------------------------------------------*/
     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 */
     112void 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}
    96160/*----------------------------------------------------------------------------*/
    97161/** Get a free USB address
     
    200264        return instance->devices[address].speed;
    201265}
     266/*----------------------------------------------------------------------------*/
     267void 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/*----------------------------------------------------------------------------*/
     280void 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}
    202291/**
    203292 * @}
  • uspace/lib/usb/src/host/endpoint.c

    rdc4c19e ra49e171  
    3434 */
    3535
    36 #include <assert.h>
    3736#include <errno.h>
    3837#include <usb/host/endpoint.h>
     
    5049        instance->max_packet_size = max_packet_size;
    5150        instance->toggle = 0;
    52         instance->active = false;
    53         fibril_mutex_initialize(&instance->guard);
    54         fibril_condvar_initialize(&instance->avail);
     51        link_initialize(&instance->same_device_eps);
    5552        return EOK;
    5653}
     
    5956{
    6057        assert(instance);
    61         assert(!instance->active);
     58        list_remove(&instance->same_device_eps);
    6259        free(instance);
    63 }
    64 /*----------------------------------------------------------------------------*/
    65 void 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 /*----------------------------------------------------------------------------*/
    75 void 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);
    8260}
    8361/*----------------------------------------------------------------------------*/
     
    9573}
    9674/*----------------------------------------------------------------------------*/
    97 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target)
     75void endpoint_toggle_reset(link_t *ep)
    9876{
     77        endpoint_t *instance =
     78            list_get_instance(ep, endpoint_t, same_device_eps);
    9979        assert(instance);
    100         if (instance->address == target.address &&
    101             (instance->endpoint == target.endpoint || target.endpoint == 0))
     80        instance->toggle = 0;
     81}
     82/*----------------------------------------------------------------------------*/
     83void 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)
    10289                instance->toggle = 0;
    10390}
  • uspace/lib/usb/src/host/usb_endpoint_manager.c

    rdc4c19e ra49e171  
    3131#include <errno.h>
    3232
    33 #include <usb/debug.h>
    3433#include <usb/host/usb_endpoint_manager.h>
    3534
     
    8180        endpoint_destroy(node->ep);
    8281        free(node);
    83 }
    84 /*----------------------------------------------------------------------------*/
    85 static 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);
    9182}
    9283/*----------------------------------------------------------------------------*/
     
    239230        return node->ep;
    240231}
    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  */
    250 void 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

    rdc4c19e ra49e171  
    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))
    4842
    4943/** Check that HC connection is alright.
     
    5953        } while (false)
    6054
     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 */
     62int 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 */
     77int 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
    6186/** Ask host controller for free address assignment.
    6287 *
     
    153178 * error codes than those listed as return codes by this function itself).
    154179 *
    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  *
    160180 * @param[in] parent Parent device (i.e. the hub device).
    161  * @param[in] connection Connection to host controller.
     181 * @param[in] connection Opened connection to host controller.
    162182 * @param[in] dev_speed New device speed.
    163183 * @param[in] enable_port Function for enabling signaling through the port the
     
    186206    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
    187207{
    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         };
     208        CHECK_CONNECTION(connection);
     209
     210        /*
     211         * Request new address.
     212         */
     213        usb_address_t dev_addr = usb_hc_request_address(connection, dev_speed);
     214        if (dev_addr < 0) {
     215                return EADDRNOTAVAIL;
     216        }
    194217
    195218        int rc;
    196219
    197         rc = usb_hc_connection_open(&hc_conn);
    198         if (rc != EOK) {
    199                 return rc;
    200         }
    201 
    202 
    203         /*
    204          * Request new address.
    205          */
    206         usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed);
    207         if (dev_addr < 0) {
    208                 usb_hc_connection_close(&hc_conn);
    209                 return EADDRNOTAVAIL;
    210         }
    211 
    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.)
     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.
    217240         */
    218241        usb_device_connection_t dev_conn;
    219242        rc = usb_device_connection_initialize_on_default_address(&dev_conn,
    220             &hc_conn);
     243            connection);
    221244        if (rc != EOK) {
    222245                rc = ENOTCONN;
    223                 goto leave_release_free_address;
     246                goto leave_release_default_address;
    224247        }
    225248
     
    229252        if (rc != EOK) {
    230253                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) {
    249                 goto leave_release_default_address;
    250         }
    251 
     254                goto leave_release_default_address;
     255        }
     256
     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;
     263                goto leave_release_default_address;
     264        }
    252265        rc = usb_pipe_probe_default_control(&ctrl_pipe);
    253266        if (rc != EOK) {
     267                rc = ENOTCONN;
     268                goto leave_release_default_address;
     269        }
     270
     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) {
    254279                rc = ESTALL;
    255                 goto leave_release_default_address;
    256         }
    257 
    258         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
    259         if (rc != EOK) {
    260                 rc = ESTALL;
    261                 goto leave_release_default_address;
    262         }
    263 
    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         }
     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
    277304
    278305        /*
     
    289316        }
    290317
     318
     319
    291320        /*
    292321         * And now inform the host controller about the handle.
     
    296325                .handle = child_handle
    297326        };
    298         rc = usb_hc_register_device(&hc_conn, &new_device);
     327        rc = usb_hc_register_device(connection, &new_device);
    299328        if (rc != EOK) {
    300329                rc = EDESTADDRREQ;
     
    320349         * Completely ignoring errors here.
    321350         */
     351
     352leave_stop_session:
     353        usb_pipe_end_session(&ctrl_pipe);
     354
     355leave_unregister_endpoint:
     356        usb_pipe_unregister(&ctrl_pipe, connection);
     357
    322358leave_release_default_address:
    323         usb_pipe_unregister(&ctrl_pipe, &hc_conn);
     359        usb_hc_release_default_address(connection);
    324360
    325361leave_release_free_address:
    326         usb_hc_unregister_device(&hc_conn, dev_addr);
    327 
    328         usb_hc_connection_close(&hc_conn);
     362        usb_hc_unregister_device(connection, dev_addr);
    329363
    330364        return rc;
  • uspace/lib/usb/src/pipes.c

    rdc4c19e ra49e171  
    4141#include <errno.h>
    4242#include <assert.h>
    43 #include "pipepriv.h"
    4443
    4544#define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
     
    242241 * necessary.
    243242 *
    244  * @deprecated
    245  * Obsoleted with introduction of usb_pipe_start_long_transfer
    246  *
    247243 * @param pipe Endpoint pipe to start the session on.
    248244 * @return Error code.
     
    250246int usb_pipe_start_session(usb_pipe_t *pipe)
    251247{
    252         usb_log_warning("usb_pipe_start_session() was deprecated.\n");
     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
    253261        return EOK;
    254262}
     
    257265/** Ends a session on the endpoint pipe.
    258266 *
    259  * @deprecated
    260  * Obsoleted with introduction of usb_pipe_end_long_transfer
    261  *
    262267 * @see usb_pipe_start_session
    263268 *
     
    267272int usb_pipe_end_session(usb_pipe_t *pipe)
    268273{
    269         usb_log_warning("usb_pipe_end_session() was deprecated.\n");
     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
    270287        return EOK;
    271288}
     
    281298bool usb_pipe_is_session_started(usb_pipe_t *pipe)
    282299{
    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  */
    299 int 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  */
    310 void usb_pipe_end_long_transfer(usb_pipe_t *pipe)
    311 {
    312         pipe_drop_ref(pipe);
     300        return (pipe->hc_phone >= 0);
    313301}
    314302
  • uspace/lib/usb/src/pipesinit.c

    rdc4c19e ra49e171  
    356356        assert(connection);
    357357
    358         fibril_mutex_initialize(&pipe->guard);
    359358        pipe->wire = connection;
    360359        pipe->hc_phone = -1;
    361         fibril_mutex_initialize(&pipe->hc_phone_mutex);
    362360        pipe->endpoint_no = endpoint_no;
    363361        pipe->transfer_type = transfer_type;
    364362        pipe->max_packet_size = max_packet_size;
    365363        pipe->direction = direction;
    366         pipe->refcount = 0;
    367364
    368365        return EOK;
     
    416413        int rc;
    417414
    418         rc = usb_pipe_start_long_transfer(pipe);
     415        TRY_LOOP(failed_attempts) {
     416                rc = usb_pipe_start_session(pipe);
     417                if (rc == EOK) {
     418                        break;
     419                }
     420        }
    419421        if (rc != EOK) {
    420422                return rc;
     
    437439                }
    438440        }
    439         usb_pipe_end_long_transfer(pipe);
     441        usb_pipe_end_session(pipe);
    440442        if (rc != EOK) {
    441443                return rc;
     
    459461    usb_hc_connection_t *hc_connection)
    460462{
    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  */
    478 int 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 {
    482463        assert(pipe);
    483464        assert(hc_connection);
     
    487468        }
    488469
    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,
     470#define _PACK(high, low) ((high) * 256 + (low))
     471
     472        return async_req_5_0(hc_connection->hc_phone,
    493473            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,
    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
     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
    500479}
    501480
  • uspace/lib/usb/src/pipesio.c

    rdc4c19e ra49e171  
    4949#include <assert.h>
    5050#include <usbhc_iface.h>
    51 #include "pipepriv.h"
    5251
    5352/** Request an in transfer, no checking of input parameters.
     
    7978        }
    8079
    81         /* Ensure serialization over the phone. */
    82         pipe_start_transaction(pipe);
    83 
    8480        /*
    8581         * Make call identifying target USB device and type of transfer.
    8682         */
    87         aid_t opening_request = async_send_3(pipe->hc_phone,
     83        aid_t opening_request = async_send_4(pipe->hc_phone,
    8884            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    8985            pipe->wire->address, pipe->endpoint_no,
     86            pipe->max_packet_size,
    9087            NULL);
    9188        if (opening_request == 0) {
    92                 pipe_end_transaction(pipe);
    9389                return ENOMEM;
    9490        }
     
    10096        aid_t data_request = async_data_read(pipe->hc_phone, buffer, size,
    10197            &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);
    10898
    10999        if (data_request == 0) {
     
    156146
    157147        if (buffer == NULL) {
    158                 return EINVAL;
     148                        return EINVAL;
    159149        }
    160150
     
    163153        }
    164154
     155        if (!usb_pipe_is_session_started(pipe)) {
     156                return EBADF;
     157        }
     158
    165159        if (pipe->direction != USB_DIRECTION_IN) {
    166160                return EBADF;
     
    171165        }
    172166
     167        size_t act_size = 0;
    173168        int rc;
    174         rc = pipe_add_ref(pipe);
    175         if (rc != EOK) {
    176                 return rc;
    177         }
    178 
    179 
    180         size_t act_size = 0;
    181169
    182170        rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);
    183 
    184         pipe_drop_ref(pipe);
    185 
    186171        if (rc != EOK) {
    187172                return rc;
     
    225210        }
    226211
    227         /* Ensure serialization over the phone. */
    228         pipe_start_transaction(pipe);
    229 
    230212        /*
    231213         * Make call identifying target USB device and type of transfer.
    232214         */
    233         aid_t opening_request = async_send_3(pipe->hc_phone,
     215        aid_t opening_request = async_send_4(pipe->hc_phone,
    234216            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    235217            pipe->wire->address, pipe->endpoint_no,
     218            pipe->max_packet_size,
    236219            NULL);
    237220        if (opening_request == 0) {
    238                 pipe_end_transaction(pipe);
    239221                return ENOMEM;
    240222        }
     
    244226         */
    245227        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 
    253228        if (rc != EOK) {
    254229                async_wait_for(opening_request, NULL);
     
    285260        }
    286261
     262        if (!usb_pipe_is_session_started(pipe)) {
     263                return EBADF;
     264        }
     265
    287266        if (pipe->direction != USB_DIRECTION_OUT) {
    288267                return EBADF;
     
    293272        }
    294273
    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);
     274        int rc = usb_pipe_write_no_check(pipe, buffer, size);
    305275
    306276        return rc;
     
    323293    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
    324294{
    325         /* Ensure serialization over the phone. */
    326         pipe_start_transaction(pipe);
    327 
    328295        /*
    329296         * Make call identifying target USB device and control transfer type.
    330297         */
    331         aid_t opening_request = async_send_3(pipe->hc_phone,
     298        aid_t opening_request = async_send_4(pipe->hc_phone,
    332299            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
    333300            pipe->wire->address, pipe->endpoint_no,
     301            pipe->max_packet_size,
    334302            NULL);
    335303        if (opening_request == 0) {
     
    343311            setup_buffer, setup_buffer_size);
    344312        if (rc != EOK) {
    345                 pipe_end_transaction(pipe);
    346313                async_wait_for(opening_request, NULL);
    347314                return rc;
     
    355322            data_buffer, data_buffer_size,
    356323            &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 
    365324        if (data_request == 0) {
    366325                async_wait_for(opening_request, NULL);
     
    420379        }
    421380
     381        if (!usb_pipe_is_session_started(pipe)) {
     382                return EBADF;
     383        }
     384
    422385        if ((pipe->direction != USB_DIRECTION_BOTH)
    423386            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    425388        }
    426389
    427         int rc;
    428 
    429         rc = pipe_add_ref(pipe);
    430         if (rc != EOK) {
    431                 return rc;
    432         }
    433 
    434390        size_t act_size = 0;
    435         rc = usb_pipe_control_read_no_check(pipe,
     391        int rc = usb_pipe_control_read_no_check(pipe,
    436392            setup_buffer, setup_buffer_size,
    437393            data_buffer, data_buffer_size, &act_size);
    438 
    439         pipe_drop_ref(pipe);
    440394
    441395        if (rc != EOK) {
     
    464418    void *data_buffer, size_t data_buffer_size)
    465419{
    466         /* Ensure serialization over the phone. */
    467         pipe_start_transaction(pipe);
    468 
    469420        /*
    470421         * Make call identifying target USB device and control transfer type.
    471422         */
    472         aid_t opening_request = async_send_4(pipe->hc_phone,
     423        aid_t opening_request = async_send_5(pipe->hc_phone,
    473424            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
    474425            pipe->wire->address, pipe->endpoint_no,
    475426            data_buffer_size,
     427            pipe->max_packet_size,
    476428            NULL);
    477429        if (opening_request == 0) {
    478                 pipe_end_transaction(pipe);
    479430                return ENOMEM;
    480431        }
     
    486437            setup_buffer, setup_buffer_size);
    487438        if (rc != EOK) {
    488                 pipe_end_transaction(pipe);
    489439                async_wait_for(opening_request, NULL);
    490440                return rc;
     
    497447                rc = async_data_write_start(pipe->hc_phone,
    498448                    data_buffer, data_buffer_size);
    499 
    500                 /* All data sent, pipe can be released. */
    501                 pipe_end_transaction(pipe);
    502 
    503449                if (rc != EOK) {
    504450                        async_wait_for(opening_request, NULL);
    505451                        return rc;
    506452                }
    507         } else {
    508                 /* No data to send, we can release the pipe for others. */
    509                 pipe_end_transaction(pipe);
    510453        }
    511454
     
    548491        }
    549492
     493        if (!usb_pipe_is_session_started(pipe)) {
     494                return EBADF;
     495        }
     496
    550497        if ((pipe->direction != USB_DIRECTION_BOTH)
    551498            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    553500        }
    554501
    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,
     502        int rc = usb_pipe_control_write_no_check(pipe,
    563503            setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
    564 
    565         pipe_drop_ref(pipe);
    566504
    567505        return rc;
  • uspace/lib/usb/src/recognise.c

    rdc4c19e ra49e171  
    404404        child->driver_data = dev_data;
    405405
     406        rc = usb_pipe_start_session(&ctrl_pipe);
     407        if (rc != EOK) {
     408                goto failure;
     409        }
     410
    406411        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);
    407417        if (rc != EOK) {
    408418                goto failure;
Note: See TracChangeset for help on using the changeset viewer.