Changeset e50cd7f in mainline for uspace/drv


Ignore:
Timestamp:
2011-04-17T19:17:55Z (15 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
63517c2, cfbbe1d3
Parents:
ef354b6 (diff), 8595577b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

new report structure fixes

Location:
uspace/drv
Files:
34 added
51 edited
2 moved

Legend:

Unmodified
Added
Removed
  • uspace/drv/ehci-hcd/hc_iface.c

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

    ref354b6 re50cd7f  
    8383static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
    8484{
    85         // TODO
     85        /* TODO */
    8686
    8787        return false;
  • uspace/drv/ohci/Makefile

    ref354b6 re50cd7f  
    3333
    3434SOURCES = \
     35        batch.c \
     36        endpoint_list.c \
     37        hc.c \
     38        hcd_endpoint.c \
    3539        iface.c \
    36         batch.c \
    3740        main.c \
    38         hc.c \
    3941        ohci.c \
     42        pci.c \
    4043        root_hub.c \
    41         pci.c
     44        hw_struct/endpoint_descriptor.c \
     45        hw_struct/transfer_descriptor.c
     46
    4247
    4348include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/ohci/batch.c

    ref354b6 re50cd7f  
    3939
    4040#include "batch.h"
     41#include "hcd_endpoint.h"
    4142#include "utils/malloc32.h"
    42 
    43 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    44 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    45 
    46 #define DEFAULT_ERROR_COUNT 3
    47 usb_transfer_batch_t * batch_get(
    48     ddf_fun_t *fun,
    49                 usb_target_t target,
    50     usb_transfer_type_t transfer_type,
    51                 size_t max_packet_size,
    52     usb_speed_t speed,
    53                 char *buffer,
    54                 size_t buffer_size,
    55                 char *setup_buffer,
    56                 size_t setup_size,
     43#include "hw_struct/endpoint_descriptor.h"
     44#include "hw_struct/transfer_descriptor.h"
     45
     46typedef struct ohci_transfer_batch {
     47        ed_t *ed;
     48        td_t **tds;
     49        size_t td_count;
     50        size_t leave_td;
     51        char *device_buffer;
     52} ohci_transfer_batch_t;
     53
     54static void ohci_transfer_batch_dispose(void *ohci_batch)
     55{
     56        ohci_transfer_batch_t *instance = ohci_batch;
     57        if (!instance)
     58                return;
     59        free32(instance->device_buffer);
     60        unsigned i = 0;
     61        if (instance->tds) {
     62                for (; i< instance->td_count; ++i) {
     63                        if (i != instance->leave_td)
     64                                free32(instance->tds[i]);
     65                }
     66                free(instance->tds);
     67        }
     68        free(instance);
     69}
     70/*----------------------------------------------------------------------------*/
     71static void batch_control(usb_transfer_batch_t *instance,
     72    usb_direction_t data_dir, usb_direction_t status_dir);
     73static void batch_data(usb_transfer_batch_t *instance);
     74/*----------------------------------------------------------------------------*/
     75usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
     76    char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
    5777    usbhc_iface_transfer_in_callback_t func_in,
    58     usbhc_iface_transfer_out_callback_t func_out,
    59                 void *arg,
    60                 usb_device_keeper_t *manager
    61                 )
     78    usbhc_iface_transfer_out_callback_t func_out, void *arg)
    6279{
    6380#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
     
    6582                usb_log_error(message); \
    6683                if (instance) { \
    67                         batch_dispose(instance); \
     84                        usb_transfer_batch_dispose(instance); \
    6885                } \
    6986                return NULL; \
     
    7390        CHECK_NULL_DISPOSE_RETURN(instance,
    7491            "Failed to allocate batch instance.\n");
    75         usb_transfer_batch_init(instance, target, transfer_type, speed,
    76             max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
    77             func_in, func_out, arg, fun, NULL, NULL);
    78 
    79         if (buffer_size > 0) {
    80                 instance->transport_buffer = malloc32(buffer_size);
    81                 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
     92        usb_transfer_batch_init(instance, ep, buffer, NULL, buffer_size,
     93            NULL, setup_size, func_in, func_out, arg, fun, NULL,
     94            ohci_transfer_batch_dispose);
     95
     96        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
     97        assert(hcd_ep);
     98
     99        ohci_transfer_batch_t *data = calloc(sizeof(ohci_transfer_batch_t), 1);
     100        CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
     101        instance->private_data = data;
     102
     103        data->td_count =
     104            ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
     105        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     106                data->td_count += 2;
     107        }
     108
     109        /* we need one extra place for td that is currently assigned to hcd_ep*/
     110        data->tds = calloc(sizeof(td_t*), data->td_count + 1);
     111        CHECK_NULL_DISPOSE_RETURN(data->tds,
     112            "Failed to allocate transfer descriptors.\n");
     113
     114        data->tds[0] = hcd_ep->td;
     115        data->leave_td = 0;
     116        unsigned i = 1;
     117        for (; i <= data->td_count; ++i) {
     118                data->tds[i] = malloc32(sizeof(td_t));
     119                CHECK_NULL_DISPOSE_RETURN(data->tds[i],
     120                    "Failed to allocate TD %d.\n", i );
     121        }
     122
     123        data->ed = hcd_ep->ed;
     124
     125        if (setup_size + buffer_size > 0) {
     126                data->device_buffer = malloc32(setup_size + buffer_size);
     127                CHECK_NULL_DISPOSE_RETURN(data->device_buffer,
    82128                    "Failed to allocate device accessible buffer.\n");
    83         }
    84 
    85         if (setup_size > 0) {
    86                 instance->setup_buffer = malloc32(setup_size);
    87                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    88                     "Failed to allocate device accessible setup buffer.\n");
     129                instance->setup_buffer = data->device_buffer;
     130                instance->data_buffer = data->device_buffer + setup_size;
    89131                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    90132        }
    91133
    92 
    93134        return instance;
    94135}
    95136/*----------------------------------------------------------------------------*/
    96 void batch_dispose(usb_transfer_batch_t *instance)
    97 {
    98         assert(instance);
    99         free32(instance->transport_buffer);
    100         free32(instance->setup_buffer);
    101         free(instance);
     137bool batch_is_complete(usb_transfer_batch_t *instance)
     138{
     139        assert(instance);
     140        ohci_transfer_batch_t *data = instance->private_data;
     141        assert(data);
     142        size_t tds = data->td_count;
     143        usb_log_debug("Batch(%p) checking %d td(s) for completion.\n",
     144            instance, tds);
     145        usb_log_debug("ED: %x:%x:%x:%x.\n",
     146            data->ed->status, data->ed->td_head, data->ed->td_tail,
     147            data->ed->next);
     148        size_t i = 0;
     149        instance->transfered_size = instance->buffer_size;
     150        for (; i < tds; ++i) {
     151                assert(data->tds[i] != NULL);
     152                usb_log_debug("TD %d: %x:%x:%x:%x.\n", i,
     153                    data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next,
     154                    data->tds[i]->be);
     155                if (!td_is_finished(data->tds[i])) {
     156                        return false;
     157                }
     158                instance->error = td_error(data->tds[i]);
     159                if (instance->error != EOK) {
     160                        usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
     161                            instance, i, data->tds[i]->status);
     162                        /* Make sure TD queue is empty (one TD),
     163                         * ED should be marked as halted */
     164                        data->ed->td_tail =
     165                            (data->ed->td_head & ED_TDTAIL_PTR_MASK);
     166                        ++i;
     167                        break;
     168                }
     169        }
     170        data->leave_td = i;
     171        assert(data->leave_td <= data->td_count);
     172        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep);
     173        assert(hcd_ep);
     174        hcd_ep->td = data->tds[i];
     175        if (i > 0)
     176                instance->transfered_size -= td_remain_size(data->tds[i - 1]);
     177
     178        /* Clear possible ED HALT */
     179        data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
     180        uint32_t pa = addr_to_phys(hcd_ep->td);
     181        assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
     182        assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
     183
     184        return true;
     185}
     186/*----------------------------------------------------------------------------*/
     187void batch_commit(usb_transfer_batch_t *instance)
     188{
     189        assert(instance);
     190        ohci_transfer_batch_t *data = instance->private_data;
     191        assert(data);
     192        ed_set_end_td(data->ed, data->tds[data->td_count]);
    102193}
    103194/*----------------------------------------------------------------------------*/
     
    106197        assert(instance);
    107198        /* We are data out, we are supposed to provide data */
    108         memcpy(instance->transport_buffer, instance->buffer,
    109             instance->buffer_size);
    110         instance->next_step = batch_call_out_and_dispose;
    111         /* TODO: implement */
     199        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     200        instance->next_step = usb_transfer_batch_call_out_and_dispose;
     201        batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
    112202        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    113203}
     
    116206{
    117207        assert(instance);
    118         instance->next_step = batch_call_in_and_dispose;
    119         /* TODO: implement */
     208        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     209        batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
    120210        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    121211}
     
    124214{
    125215        assert(instance);
    126         instance->direction = USB_DIRECTION_IN;
    127         instance->next_step = batch_call_in_and_dispose;
    128         /* TODO: implement */
     216        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     217        batch_data(instance);
    129218        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    130219}
     
    133222{
    134223        assert(instance);
    135         instance->direction = USB_DIRECTION_OUT;
    136224        /* We are data out, we are supposed to provide data */
    137         memcpy(instance->transport_buffer, instance->buffer,
    138             instance->buffer_size);
    139         instance->next_step = batch_call_out_and_dispose;
    140         /* TODO: implement */
     225        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     226        instance->next_step = usb_transfer_batch_call_out_and_dispose;
     227        batch_data(instance);
    141228        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    142229}
     
    145232{
    146233        assert(instance);
    147         instance->direction = USB_DIRECTION_IN;
    148         instance->next_step = batch_call_in_and_dispose;
    149         /* TODO: implement */
     234        instance->next_step = usb_transfer_batch_call_in_and_dispose;
     235        batch_data(instance);
    150236        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    151237}
     
    154240{
    155241        assert(instance);
    156         instance->direction = USB_DIRECTION_IN;
    157         instance->next_step = batch_call_in_and_dispose;
    158         /* TODO: implement */
    159         usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    160 }
    161 /*----------------------------------------------------------------------------*/
    162 /** Helper function calls callback and correctly disposes of batch structure.
    163  *
    164  * @param[in] instance Batch structure to use.
    165  */
    166 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    167 {
    168         assert(instance);
    169         usb_transfer_batch_call_in(instance);
    170         batch_dispose(instance);
    171 }
    172 /*----------------------------------------------------------------------------*/
    173 /** Helper function calls callback and correctly disposes of batch structure.
    174  *
    175  * @param[in] instance Batch structure to use.
    176  */
    177 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    178 {
    179         assert(instance);
    180         usb_transfer_batch_call_out(instance);
    181         batch_dispose(instance);
     242        /* We are data out, we are supposed to provide data */
     243        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
     244        instance->next_step = usb_transfer_batch_call_out_and_dispose;
     245        batch_data(instance);
     246        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
     247}
     248/*----------------------------------------------------------------------------*/
     249ed_t * batch_ed(usb_transfer_batch_t *instance)
     250{
     251        assert(instance);
     252        ohci_transfer_batch_t *data = instance->private_data;
     253        assert(data);
     254        return data->ed;
     255}
     256/*----------------------------------------------------------------------------*/
     257void batch_control(usb_transfer_batch_t *instance,
     258    usb_direction_t data_dir, usb_direction_t status_dir)
     259{
     260        assert(instance);
     261        ohci_transfer_batch_t *data = instance->private_data;
     262        assert(data);
     263        usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
     264            data->ed->status, data->ed->td_tail, data->ed->td_head,
     265            data->ed->next);
     266        int toggle = 0;
     267        /* setup stage */
     268        td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
     269                instance->setup_size, toggle);
     270        td_set_next(data->tds[0], data->tds[1]);
     271        usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status,
     272            data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be);
     273
     274        /* data stage */
     275        size_t td_current = 1;
     276        size_t remain_size = instance->buffer_size;
     277        char *buffer = instance->data_buffer;
     278        while (remain_size > 0) {
     279                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     280                    OHCI_TD_MAX_TRANSFER : remain_size;
     281                toggle = 1 - toggle;
     282
     283                td_init(data->tds[td_current], data_dir, buffer,
     284                    transfer_size, toggle);
     285                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
     286                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     287                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     288                    data->tds[td_current]->next, data->tds[td_current]->be);
     289
     290                buffer += transfer_size;
     291                remain_size -= transfer_size;
     292                assert(td_current < data->td_count - 1);
     293                ++td_current;
     294        }
     295
     296        /* status stage */
     297        assert(td_current == data->td_count - 1);
     298        td_init(data->tds[td_current], status_dir, NULL, 0, 1);
     299        td_set_next(data->tds[td_current], data->tds[td_current + 1]);
     300        usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
     301            data->tds[td_current]->status, data->tds[td_current]->cbp,
     302            data->tds[td_current]->next, data->tds[td_current]->be);
     303}
     304/*----------------------------------------------------------------------------*/
     305void batch_data(usb_transfer_batch_t *instance)
     306{
     307        assert(instance);
     308        ohci_transfer_batch_t *data = instance->private_data;
     309        assert(data);
     310        usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
     311            data->ed->status, data->ed->td_tail, data->ed->td_head,
     312            data->ed->next);
     313
     314        size_t td_current = 0;
     315        size_t remain_size = instance->buffer_size;
     316        char *buffer = instance->data_buffer;
     317        while (remain_size > 0) {
     318                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     319                    OHCI_TD_MAX_TRANSFER : remain_size;
     320
     321                td_init(data->tds[td_current], instance->ep->direction,
     322                    buffer, transfer_size, -1);
     323                td_set_next(data->tds[td_current], data->tds[td_current + 1]);
     324                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     325                    data->tds[td_current]->status, data->tds[td_current]->cbp,
     326                    data->tds[td_current]->next, data->tds[td_current]->be);
     327
     328                buffer += transfer_size;
     329                remain_size -= transfer_size;
     330                assert(td_current < data->td_count);
     331                ++td_current;
     332        }
    182333}
    183334/**
  • uspace/drv/ohci/batch.h

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

    ref354b6 re50cd7f  
    4343
    4444#include "hc.h"
     45#include "hcd_endpoint.h"
    4546
    4647static int interrupt_emulator(hc_t *instance);
    4748static void hc_gain_control(hc_t *instance);
    4849static void hc_init_hw(hc_t *instance);
     50static int hc_init_transfer_lists(hc_t *instance);
     51static int hc_init_memory(hc_t *instance);
    4952/*----------------------------------------------------------------------------*/
    5053int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
     
    5255        assert(instance);
    5356        assert(hub_fun);
     57
     58        int ret;
    5459
    5560        usb_address_t hub_address =
    5661            device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
     62        if (hub_address <= 0) {
     63                usb_log_error("Failed to get OHCI root hub address.\n");
     64                return hub_address;
     65        }
    5766        instance->rh.address = hub_address;
    5867        usb_device_keeper_bind(
    5968            &instance->manager, hub_address, hub_fun->handle);
    6069
     70        ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
     71            USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
     72        if (ret != EOK) {
     73                usb_log_error("Failed to add OHCI rh endpoint 0.\n");
     74                usb_device_keeper_release(&instance->manager, hub_address);
     75                return ret;
     76        }
     77
    6178        char *match_str = NULL;
    62         int ret = asprintf(&match_str, "usb&class=hub");
    63         ret = (match_str == NULL) ? ret : EOK;
     79        /* DDF needs heap allocated string */
     80        ret = asprintf(&match_str, "usb&class=hub");
    6481        if (ret < 0) {
    65                 usb_log_error("Failed to create root hub match-id string.\n");
     82                usb_log_error(
     83                    "Failed(%d) to create root hub match-id string.\n", ret);
     84                usb_device_keeper_release(&instance->manager, hub_address);
    6685                return ret;
    6786        }
     
    6988        ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
    7089        if (ret != EOK) {
    71                 usb_log_error("Failed add create root hub match-id.\n");
     90                usb_log_error("Failed add root hub match-id.\n");
    7291        }
    7392        return ret;
     
    90109            ret, str_error(ret));
    91110
    92         instance->ddf_instance = fun;
    93111        usb_device_keeper_init(&instance->manager);
    94112        ret = usb_endpoint_manager_init(&instance->ep_manager,
     
    97115            ret, str_error(ret));
    98116
     117        hc_gain_control(instance);
     118        ret = hc_init_memory(instance);
     119        CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures:%s.\n",
     120            ret, str_error(ret));
     121        hc_init_hw(instance);
     122        fibril_mutex_initialize(&instance->guard);
     123
     124        rh_init(&instance->rh, instance->registers);
     125
    99126        if (!interrupts) {
    100127                instance->interrupt_emulator =
     
    103130        }
    104131
    105         hc_gain_control(instance);
    106 
    107         rh_init(&instance->rh, dev, instance->registers);
    108 
    109         hc_init_hw(instance);
    110 
    111         /* TODO: implement */
    112         return EOK;
     132        list_initialize(&instance->pending_batches);
     133#undef CHECK_RET_RETURN
     134        return EOK;
     135}
     136/*----------------------------------------------------------------------------*/
     137int hc_add_endpoint(
     138    hc_t *instance, usb_address_t address, usb_endpoint_t endpoint,
     139    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
     140    size_t mps, size_t size, unsigned interval)
     141{
     142        endpoint_t *ep = malloc(sizeof(endpoint_t));
     143        if (ep == NULL)
     144                return ENOMEM;
     145        int ret =
     146            endpoint_init(ep, address, endpoint, direction, type, speed, mps);
     147        if (ret != EOK) {
     148                free(ep);
     149                return ret;
     150        }
     151
     152        hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
     153        if (hcd_ep == NULL) {
     154                endpoint_destroy(ep);
     155                return ENOMEM;
     156        }
     157
     158        ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
     159        if (ret != EOK) {
     160                hcd_endpoint_clear(ep);
     161                endpoint_destroy(ep);
     162                return ret;
     163        }
     164
     165        /* Enqueue hcd_ep */
     166        switch (ep->transfer_type) {
     167        case USB_TRANSFER_CONTROL:
     168                instance->registers->control &= ~C_CLE;
     169                endpoint_list_add_ep(
     170                    &instance->lists[ep->transfer_type], hcd_ep);
     171                instance->registers->control_current = 0;
     172                instance->registers->control |= C_CLE;
     173                break;
     174        case USB_TRANSFER_BULK:
     175                instance->registers->control &= ~C_BLE;
     176                endpoint_list_add_ep(
     177                    &instance->lists[ep->transfer_type], hcd_ep);
     178                instance->registers->control |= C_BLE;
     179                break;
     180        case USB_TRANSFER_ISOCHRONOUS:
     181        case USB_TRANSFER_INTERRUPT:
     182                instance->registers->control &= (~C_PLE & ~C_IE);
     183                endpoint_list_add_ep(
     184                    &instance->lists[ep->transfer_type], hcd_ep);
     185                instance->registers->control |= C_PLE | C_IE;
     186                break;
     187        default:
     188                break;
     189        }
     190
     191        return EOK;
     192}
     193/*----------------------------------------------------------------------------*/
     194int hc_remove_endpoint(hc_t *instance, usb_address_t address,
     195    usb_endpoint_t endpoint, usb_direction_t direction)
     196{
     197        assert(instance);
     198        fibril_mutex_lock(&instance->guard);
     199        endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
     200            address, endpoint, direction, NULL);
     201        if (ep == NULL) {
     202                usb_log_error("Endpoint unregister failed: No such EP.\n");
     203                fibril_mutex_unlock(&instance->guard);
     204                return ENOENT;
     205        }
     206
     207        hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
     208        if (hcd_ep) {
     209                /* Dequeue hcd_ep */
     210                switch (ep->transfer_type) {
     211                case USB_TRANSFER_CONTROL:
     212                        instance->registers->control &= ~C_CLE;
     213                        endpoint_list_remove_ep(
     214                            &instance->lists[ep->transfer_type], hcd_ep);
     215                        instance->registers->control_current = 0;
     216                        instance->registers->control |= C_CLE;
     217                        break;
     218                case USB_TRANSFER_BULK:
     219                        instance->registers->control &= ~C_BLE;
     220                        endpoint_list_remove_ep(
     221                            &instance->lists[ep->transfer_type], hcd_ep);
     222                        instance->registers->control |= C_BLE;
     223                        break;
     224                case USB_TRANSFER_ISOCHRONOUS:
     225                case USB_TRANSFER_INTERRUPT:
     226                        instance->registers->control &= (~C_PLE & ~C_IE);
     227                        endpoint_list_remove_ep(
     228                            &instance->lists[ep->transfer_type], hcd_ep);
     229                        instance->registers->control |= C_PLE | C_IE;
     230                        break;
     231                default:
     232                        break;
     233                }
     234                hcd_endpoint_clear(ep);
     235        } else {
     236                usb_log_warning("Endpoint without hcd equivalent structure.\n");
     237        }
     238        int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,
     239            address, endpoint, direction);
     240        fibril_mutex_unlock(&instance->guard);
     241        return ret;
     242}
     243/*----------------------------------------------------------------------------*/
     244endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
     245    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
     246{
     247        assert(instance);
     248        fibril_mutex_lock(&instance->guard);
     249        endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
     250            address, endpoint, direction, bw);
     251        fibril_mutex_unlock(&instance->guard);
     252        return ep;
    113253}
    114254/*----------------------------------------------------------------------------*/
     
    117257        assert(instance);
    118258        assert(batch);
    119         if (batch->target.address == instance->rh.address) {
     259        assert(batch->ep);
     260
     261        /* check for root hub communication */
     262        if (batch->ep->address == instance->rh.address) {
    120263                return rh_request(&instance->rh, batch);
    121264        }
    122         /* TODO: implement */
    123         return ENOTSUP;
     265
     266        fibril_mutex_lock(&instance->guard);
     267        list_append(&batch->link, &instance->pending_batches);
     268        batch_commit(batch);
     269        switch (batch->ep->transfer_type) {
     270        case USB_TRANSFER_CONTROL:
     271                instance->registers->command_status |= CS_CLF;
     272                break;
     273        case USB_TRANSFER_BULK:
     274                instance->registers->command_status |= CS_BLF;
     275                break;
     276        default:
     277                break;
     278        }
     279
     280        fibril_mutex_unlock(&instance->guard);
     281        return EOK;
    124282}
    125283/*----------------------------------------------------------------------------*/
     
    127285{
    128286        assert(instance);
    129         if (status == 0)
     287        if ((status & ~IS_SF) == 0) /* ignore sof status */
    130288                return;
    131289        if (status & IS_RHSC)
    132290                rh_interrupt(&instance->rh);
    133291
    134         usb_log_info("OHCI interrupt: %x.\n", status);
    135 
    136         /* TODO: Check for further interrupt causes */
    137         /* TODO: implement */
     292        usb_log_debug("OHCI interrupt: %x.\n", status);
     293
     294        if (status & IS_WDH) {
     295                fibril_mutex_lock(&instance->guard);
     296                usb_log_debug2("HCCA: %p-%p(%p).\n", instance->hcca,
     297                    instance->registers->hcca, addr_to_phys(instance->hcca));
     298                usb_log_debug2("Periodic current: %p.\n",
     299                    instance->registers->periodic_current);
     300
     301                link_t *current = instance->pending_batches.next;
     302                while (current != &instance->pending_batches) {
     303                        link_t *next = current->next;
     304                        usb_transfer_batch_t *batch =
     305                            usb_transfer_batch_from_link(current);
     306
     307                        if (batch_is_complete(batch)) {
     308                                list_remove(current);
     309                                usb_transfer_batch_finish(batch);
     310                        }
     311                        current = next;
     312                }
     313                fibril_mutex_unlock(&instance->guard);
     314        }
    138315}
    139316/*----------------------------------------------------------------------------*/
     
    146323                instance->registers->interrupt_status = status;
    147324                hc_interrupt(instance, status);
    148                 async_usleep(1000);
     325                async_usleep(50000);
    149326        }
    150327        return EOK;
     
    154331{
    155332        assert(instance);
     333        /* Turn off legacy emulation */
     334        volatile uint32_t *ohci_emulation_reg =
     335            (uint32_t*)((char*)instance->registers + 0x100);
     336        usb_log_debug("OHCI legacy register %p: %x.\n",
     337                ohci_emulation_reg, *ohci_emulation_reg);
     338        *ohci_emulation_reg = 0;
     339
    156340        /* Interrupt routing enabled => smm driver is active */
    157341        if (instance->registers->control & C_IR) {
    158                 usb_log_info("Found SMM driver requesting ownership change.\n");
     342                usb_log_debug("SMM driver: request ownership change.\n");
    159343                instance->registers->command_status |= CS_OCR;
    160344                while (instance->registers->control & C_IR) {
    161345                        async_usleep(1000);
    162346                }
    163                 usb_log_info("Ownership taken from SMM driver.\n");
     347                usb_log_info("SMM driver: Ownership taken.\n");
    164348                return;
    165349        }
     
    169353        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    170354        if (hc_status != C_HCFS_RESET) {
    171                 usb_log_info("Found BIOS driver.\n");
     355                usb_log_debug("BIOS driver found.\n");
    172356                if (hc_status == C_HCFS_OPERATIONAL) {
    173                         usb_log_info("HC operational(BIOS).\n");
     357                        usb_log_info("BIOS driver: HC operational.\n");
    174358                        return;
    175359                }
     
    177361                instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
    178362                async_usleep(20000);
     363                usb_log_info("BIOS driver: HC resumed.\n");
    179364                return;
    180365        }
     
    182367        /* HC is in reset (hw startup) => no other driver
    183368         * maintain reset for at least the time specified in USB spec (50 ms)*/
     369        usb_log_info("HC found in reset.\n");
    184370        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 
    193371}
    194372/*----------------------------------------------------------------------------*/
    195373void hc_init_hw(hc_t *instance)
    196374{
    197         assert(instance);
     375        /* OHCI guide page 42 */
     376        assert(instance);
     377        usb_log_debug2("Started hc initialization routine.\n");
     378
     379        /* Save contents of fm_interval register */
    198380        const uint32_t fm_interval = instance->registers->fm_interval;
     381        usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
     382
     383        /* Reset hc */
     384        usb_log_debug2("HC reset.\n");
     385        size_t time = 0;
    199386        instance->registers->command_status = CS_HCR;
    200         async_usleep(10);
     387        while (instance->registers->command_status & CS_HCR) {
     388                async_usleep(10);
     389                time += 10;
     390        }
     391        usb_log_debug2("HC reset complete in %zu us.\n", time);
     392
     393        /* Restore fm_interval */
    201394        instance->registers->fm_interval = fm_interval;
    202395        assert((instance->registers->command_status & CS_HCR) == 0);
     396
    203397        /* hc is now in suspend state */
    204         /* TODO: init HCCA block */
    205         /* TODO: init queues */
    206         /* TODO: enable queues */
    207         /* TODO: enable interrupts */
    208         /* TODO: set periodic start to 90% */
     398        usb_log_debug2("HC should be in suspend state(%x).\n",
     399            instance->registers->control);
     400
     401        /* Use HCCA */
     402        instance->registers->hcca = addr_to_phys(instance->hcca);
     403
     404        /* Use queues */
     405        instance->registers->bulk_head =
     406            instance->lists[USB_TRANSFER_BULK].list_head_pa;
     407        usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
     408            instance->lists[USB_TRANSFER_BULK].list_head,
     409            instance->lists[USB_TRANSFER_BULK].list_head_pa);
     410
     411        instance->registers->control_head =
     412            instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
     413        usb_log_debug2("Control HEAD set to: %p(%p).\n",
     414            instance->lists[USB_TRANSFER_CONTROL].list_head,
     415            instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
     416
     417        /* Enable queues */
     418        instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
     419        usb_log_debug2("All queues enabled(%x).\n",
     420            instance->registers->control);
     421
     422        /* Disable interrupts */
     423        instance->registers->interrupt_disable = I_SF | I_OC;
     424        usb_log_debug2("Disabling interrupts: %x.\n",
     425            instance->registers->interrupt_disable);
     426        instance->registers->interrupt_disable = I_MI;
     427        usb_log_debug2("Enabled interrupts: %x.\n",
     428            instance->registers->interrupt_enable);
     429
     430        /* Set periodic start to 90% */
     431        uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
     432        instance->registers->periodic_start = (frame_length / 10) * 9;
     433        usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
     434            instance->registers->periodic_start,
     435            instance->registers->periodic_start, frame_length);
    209436
    210437        instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
    211         usb_log_info("OHCI HC up and running.\n");
     438        usb_log_info("OHCI HC up and running(%x).\n",
     439            instance->registers->control);
     440}
     441/*----------------------------------------------------------------------------*/
     442int hc_init_transfer_lists(hc_t *instance)
     443{
     444        assert(instance);
     445
     446#define SETUP_ENDPOINT_LIST(type) \
     447do { \
     448        const char *name = usb_str_transfer_type(type); \
     449        int ret = endpoint_list_init(&instance->lists[type], name); \
     450        if (ret != EOK) { \
     451                usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
     452                    ret, name); \
     453                endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \
     454                endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
     455                endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
     456                endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \
     457        } \
     458} while (0)
     459
     460        SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS);
     461        SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT);
     462        SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL);
     463        SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK);
     464#undef SETUP_ENDPOINT_LIST
     465        endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT],
     466            &instance->lists[USB_TRANSFER_ISOCHRONOUS]);
     467
     468        return EOK;
     469}
     470/*----------------------------------------------------------------------------*/
     471int hc_init_memory(hc_t *instance)
     472{
     473        assert(instance);
     474        /* Init queues */
     475        hc_init_transfer_lists(instance);
     476
     477        /*Init HCCA */
     478        instance->hcca = malloc32(sizeof(hcca_t));
     479        if (instance->hcca == NULL)
     480                return ENOMEM;
     481        bzero(instance->hcca, sizeof(hcca_t));
     482        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
     483
     484        unsigned i = 0;
     485        for (; i < 32; ++i) {
     486                instance->hcca->int_ep[i] =
     487                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
     488        }
     489        usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
     490            instance->lists[USB_TRANSFER_INTERRUPT].list_head,
     491            instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
     492
     493        return EOK;
    212494}
    213495/**
  • uspace/drv/ohci/hc.h

    ref354b6 re50cd7f  
    4848#include "ohci_regs.h"
    4949#include "root_hub.h"
     50#include "endpoint_list.h"
    5051#include "hw_struct/hcca.h"
    5152
    5253typedef struct hc {
    5354        ohci_regs_t *registers;
     55        hcca_t *hcca;
     56
    5457        usb_address_t rh_address;
    5558        rh_t rh;
    56         ddf_fun_t *ddf_instance;
     59
     60        endpoint_list_t lists[4];
     61        link_t pending_batches;
     62
    5763        usb_device_keeper_t manager;
    5864        usb_endpoint_manager_t ep_manager;
    5965        fid_t interrupt_emulator;
     66        fibril_mutex_t guard;
    6067} hc_t;
    6168
     
    6572     uintptr_t regs, size_t reg_size, bool interrupts);
    6673
    67 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
    68 
    69 void hc_interrupt(hc_t *instance, uint32_t status);
    70 
    7174/** Safely dispose host controller internal structures
    7275 *
     
    7477 */
    7578static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
     79
     80int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep,
     81    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
     82    size_t max_packet_size, size_t size, unsigned interval);
     83
     84int hc_remove_endpoint(hc_t *instance, usb_address_t address,
     85    usb_endpoint_t endpoint, usb_direction_t direction);
     86
     87endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
     88    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw);
     89
     90int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
     91
     92void hc_interrupt(hc_t *instance, uint32_t status);
    7693
    7794/** Get and cast pointer to the driver data
  • uspace/drv/ohci/hcd_endpoint.h

    ref354b6 re50cd7f  
    11/*
    2  * Copyright (c) 2007 Jan Hudecek
    3  * Copyright (c) 2008 Martin Decky
     2 * Copyright (c) 2011 Jan Vesely
    43 * All rights reserved.
    54 *
     
    2726 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2827 */
    29 
    30 /** @addtogroup genericproc
     28/** @addtogroup drvusbohci
    3129 * @{
    3230 */
    33 /** @file tasklet.h
    34  * @brief Tasklets declarations
     31/** @file
     32 * @brief OHCI driver
    3533 */
     34#ifndef DRV_OHCI_HCD_ENDPOINT_H
     35#define DRV_OHCI_HCD_ENDPOINT_H
    3636
    37 #ifndef KERN_TASKLET_H_
    38 #define KERN_TASKLET_H_
    39 
     37#include <assert.h>
    4038#include <adt/list.h>
    4139
    42 /** Tasklet callback type */
    43 typedef void (* tasklet_callback_t)(void *arg);
     40#include <usb/host/endpoint.h>
    4441
    45 /** Tasklet state */
    46 typedef enum {
    47         NotActive,
    48         Scheduled,
    49         InProgress,
    50         Disabled
    51 } tasklet_state_t;
     42#include "hw_struct/endpoint_descriptor.h"
     43#include "hw_struct/transfer_descriptor.h"
    5244
    53 /** Structure describing a tasklet */
    54 typedef struct tasklet_descriptor {
     45typedef struct hcd_endpoint {
     46        ed_t *ed;
     47        td_t *td;
    5548        link_t link;
    56        
    57         /** Callback to call */
    58         tasklet_callback_t callback;
    59        
    60         /** Argument passed to the callback */
    61         void *arg;
    62        
    63         /** State of the tasklet */
    64         tasklet_state_t state;
    65 } tasklet_descriptor_t;
     49} hcd_endpoint_t;
    6650
     51hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep);
    6752
    68 extern void tasklet_init(void);
     53hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep);
    6954
     55void hcd_endpoint_clear(endpoint_t *ep);
    7056#endif
    71 
    72 /** @}
     57/**
     58 * @}
    7359 */
  • uspace/drv/ohci/hw_struct/completion_codes.h

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

    ref354b6 re50cd7f  
    3535#define DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H
    3636
     37#include <assert.h>
    3738#include <stdint.h>
     39
     40#include <usb/host/endpoint.h>
     41
     42#include "utils/malloc32.h"
     43#include "transfer_descriptor.h"
    3844
    3945#include "completion_codes.h"
     
    4450#define ED_STATUS_FA_SHIFT (0)
    4551#define ED_STATUS_EN_MASK (0xf)    /* USB endpoint address */
    46 #define ED_STATUS_EN_SHIFT (6)
     52#define ED_STATUS_EN_SHIFT (7)
    4753#define ED_STATUS_D_MASK (0x3)     /* direction */
    48 #define ED_STATUS_D_SHIFT (10)
    49 #define ED_STATUS_D_IN (0x1)
    50 #define ED_STATUS_D_OUT (0x2)
     54#define ED_STATUS_D_SHIFT (11)
     55#define ED_STATUS_D_OUT (0x1)
     56#define ED_STATUS_D_IN (0x2)
     57#define ED_STATUS_D_TRANSFER (0x3)
    5158
    52 #define ED_STATUS_S_FLAG (1 << 13) /* speed flag */
     59#define ED_STATUS_S_FLAG (1 << 13) /* speed flag: 1 = low */
    5360#define ED_STATUS_K_FLAG (1 << 14) /* skip flag (no not execute this ED) */
    5461#define ED_STATUS_F_FLAG (1 << 15) /* format: 1 = isochronous*/
     
    6673#define ED_TDHEAD_ZERO_SHIFT (2)
    6774#define ED_TDHEAD_TOGGLE_CARRY (0x2)
     75#define ED_TDHEAD_HALTED_FLAG (0x1)
    6876
    6977        volatile uint32_t next;
     
    7179#define ED_NEXT_PTR_SHIFT (0)
    7280} __attribute__((packed)) ed_t;
     81
     82void ed_init(ed_t *instance, endpoint_t *ep);
     83
     84static inline void ed_set_td(ed_t *instance, td_t *td)
     85{
     86        assert(instance);
     87        uintptr_t pa = addr_to_phys(td);
     88        instance->td_head =
     89            ((pa & ED_TDHEAD_PTR_MASK)
     90            | (instance->td_head & ~ED_TDHEAD_PTR_MASK));
     91        instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
     92}
     93
     94static inline void ed_set_end_td(ed_t *instance, td_t *td)
     95{
     96        assert(instance);
     97        uintptr_t pa = addr_to_phys(td);
     98        instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
     99}
     100
     101static inline void ed_append_ed(ed_t *instance, ed_t *next)
     102{
     103        assert(instance);
     104        assert(next);
     105        uint32_t pa = addr_to_phys(next);
     106        assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa);
     107        instance->next = pa;
     108}
     109
     110static inline int ed_toggle_get(ed_t *instance)
     111{
     112        assert(instance);
     113        return (instance->td_head & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0;
     114}
     115
     116static inline void ed_toggle_set(ed_t *instance, int toggle)
     117{
     118        assert(instance);
     119        assert(toggle == 0 || toggle == 1);
     120        if (toggle == 1) {
     121                instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
     122        } else {
     123                /* clear halted flag when reseting toggle */
     124                instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY;
     125                instance->td_head &= ~ED_TDHEAD_HALTED_FLAG;
     126        }
     127}
    73128#endif
    74129/**
  • uspace/drv/ohci/hw_struct/hcca.h

    ref354b6 re50cd7f  
    4343        uint32_t done_head;
    4444        uint32_t reserved[29];
    45 } __attribute__((packed)) hcca_t;
     45} __attribute__((packed, aligned)) hcca_t;
    4646
    4747#endif
  • uspace/drv/ohci/hw_struct/transfer_descriptor.h

    ref354b6 re50cd7f  
    3535#define DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
    3636
     37#include <bool.h>
    3738#include <stdint.h>
     39#include "utils/malloc32.h"
    3840
    3941#include "completion_codes.h"
     42
     43/* OHCI TDs can handle up to 8KB buffers */
     44#define OHCI_TD_MAX_TRANSFER (8 * 1024)
    4045
    4146typedef struct td {
     
    4550#define TD_STATUS_DP_SHIFT (19)
    4651#define TD_STATUS_DP_SETUP (0x0)
    47 #define TD_STATUS_DP_IN (0x1)
    48 #define TD_STATUS_DP_OUT (0x2)
     52#define TD_STATUS_DP_OUT (0x1)
     53#define TD_STATUS_DP_IN (0x2)
    4954#define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int */
    5055#define TD_STATUS_DI_SHIFT (21)
     
    5257#define TD_STATUS_T_MASK (0x3)  /* data toggle 1x = use ED toggle carry */
    5358#define TD_STATUS_T_SHIFT (24)
     59#define TD_STATUS_T_0 (0x2)
     60#define TD_STATUS_T_1 (0x3)
     61#define TD_STATUS_T_ED (0)
    5462#define TD_STATUS_EC_MASK (0x3) /* error count */
    5563#define TD_STATUS_EC_SHIFT (26)
     
    6472        volatile uint32_t be; /* buffer end, address of the last byte */
    6573} __attribute__((packed)) td_t;
     74
     75void td_init(
     76    td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle);
     77
     78inline static void td_set_next(td_t *instance, td_t *next)
     79{
     80        assert(instance);
     81        instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK;
     82}
     83
     84inline static bool td_is_finished(td_t *instance)
     85{
     86        assert(instance);
     87        int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
     88        /* something went wrong, error code is set */
     89        if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) {
     90                return true;
     91        }
     92        /* everything done */
     93        if (cc == CC_NOERROR && instance->cbp == 0) {
     94                return true;
     95        }
     96        return false;
     97}
     98
     99static inline int td_error(td_t *instance)
     100{
     101        assert(instance);
     102        int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
     103        return cc_to_rc(cc);
     104}
     105
     106static inline size_t td_remain_size(td_t *instance)
     107{
     108        assert(instance);
     109        if (instance->cbp == 0)
     110                return 0;
     111        return instance->be - instance->cbp + 1;
     112}
    66113#endif
    67114/**
  • uspace/drv/ohci/iface.c

    ref354b6 re50cd7f  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky
     2 * Copyright (c) 2011 Vojtech Horky, Jan Vesely
    33 * All rights reserved.
    44 *
     
    3030 */
    3131/** @file
    32  * USB-HC interface implementation.
     32 * @brief OHCI driver hc interface implementation
    3333 */
    3434#include <ddf/driver.h>
     
    3636
    3737#include <usb/debug.h>
     38#include <usb/host/endpoint.h>
    3839
    3940#include "iface.h"
    4041#include "hc.h"
    4142
    42 #define UNSUPPORTED(methodname) \
    43         usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \
    44             methodname, __FILE__, __LINE__)
    45 
    46 /** Reserve default address.
    47  *
    48  * This function may block the caller.
    49  *
    50  * @param[in] fun Device function the action was invoked on.
    51  * @param[in] speed Speed of the device for which the default address is
    52  *      reserved.
    53  * @return Error code.
    54  */
    55 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    56 {
     43static inline int setup_batch(
     44    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
     45    void *data, size_t size, void * setup_data, size_t setup_size,
     46    usbhc_iface_transfer_in_callback_t in,
     47    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
     48    hc_t **hc, usb_transfer_batch_t **batch)
     49{
     50        assert(hc);
     51        assert(batch);
    5752        assert(fun);
    58         hc_t *hc = fun_to_hc(fun);
    59         assert(hc);
    60         usb_log_debug("Default address request with speed %d.\n", speed);
    61         usb_device_keeper_reserve_default_address(&hc->manager, speed);
     53        *hc = fun_to_hc(fun);
     54        assert(*hc);
     55
     56        size_t res_bw;
     57        endpoint_t *ep = hc_get_endpoint(*hc,
     58            target.address, target.endpoint, direction, &res_bw);
     59        if (ep == NULL) {
     60                usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
     61                    target.address, target.endpoint, name);
     62                return ENOENT;
     63        }
     64
     65        usb_log_debug("%s %d:%d %zu(%zu).\n",
     66            name, target.address, target.endpoint, size, ep->max_packet_size);
     67
     68        const size_t bw = bandwidth_count_usb11(
     69            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     70        if (res_bw < bw) {
     71                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
     72                    "but only %zu is reserved.\n",
     73                    target.address, target.endpoint, name, bw, res_bw);
     74                return ENOSPC;
     75        }
     76
     77        *batch = batch_get(
     78            fun, ep, data, size, setup_data, setup_size, in, out, arg);
     79        if (!*batch)
     80                return ENOMEM;
    6281        return EOK;
    6382}
    6483/*----------------------------------------------------------------------------*/
    65 /** Release default address.
    66  *
    67  * @param[in] fun Device function the action was invoked on.
    68  * @return Error code.
    69  */
    70 static int release_default_address(ddf_fun_t *fun)
    71 {
    72         assert(fun);
    73         hc_t *hc = fun_to_hc(fun);
    74         assert(hc);
    75         usb_log_debug("Default address release.\n");
    76         usb_device_keeper_release_default_address(&hc->manager);
    77         return EOK;
    78 }
    79 /*----------------------------------------------------------------------------*/
    80 /** Found free USB address.
    81  *
    82  * @param[in] fun Device function the action was invoked on.
    83  * @param[in] speed Speed of the device that will get this address.
    84  * @param[out] address Non-null pointer where to store the free address.
     84/** Request address interface function
     85 *
     86 * @param[in] fun DDF function that was called.
     87 * @param[in] speed Speed to associate with the new default address.
     88 * @param[out] address Place to write a new address.
    8589 * @return Error code.
    8690 */
     
    101105}
    102106/*----------------------------------------------------------------------------*/
    103 /** Bind USB address with device devman handle.
    104  *
    105  * @param[in] fun Device function the action was invoked on.
    106  * @param[in] address USB address of the device.
    107  * @param[in] handle Devman handle of the device.
     107/** Bind address interface function
     108 *
     109 * @param[in] fun DDF function that was called.
     110 * @param[in] address Address of the device
     111 * @param[in] handle Devman handle of the device driver.
    108112 * @return Error code.
    109113 */
    110114static int bind_address(
    111     ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
     115  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
    112116{
    113117        assert(fun);
     
    119123}
    120124/*----------------------------------------------------------------------------*/
    121 /** Release previously requested address.
    122  *
    123  * @param[in] fun Device function the action was invoked on.
     125/** Release address interface function
     126 *
     127 * @param[in] fun DDF function that was called.
    124128 * @param[in] address USB address to be released.
    125129 * @return Error code.
     
    139143 * @param[in] fun Device function the action was invoked on.
    140144 * @param[in] address USB address of the device.
     145 * @param[in] ep_speed Endpoint speed (invalid means to use device one).
    141146 * @param[in] endpoint Endpoint number.
    142147 * @param[in] transfer_type USB transfer type.
     
    146151 * @return Error code.
    147152 */
    148 static int register_endpoint(
    149     ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
     153static int register_endpoint(ddf_fun_t *fun,
     154    usb_address_t address, usb_speed_t ep_speed, usb_endpoint_t endpoint,
    150155    usb_transfer_type_t transfer_type, usb_direction_t direction,
    151156    size_t max_packet_size, unsigned int interval)
    152157{
    153         assert(fun);
    154158        hc_t *hc = fun_to_hc(fun);
    155159        assert(hc);
    156         if (address == hc->rh.address)
    157                 return EOK;
    158         const usb_speed_t speed =
    159                 usb_device_keeper_get_speed(&hc->manager, address);
     160
     161        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
     162        if (speed >= USB_SPEED_MAX) {
     163                speed = ep_speed;
     164        }
    160165        const size_t size = max_packet_size;
     166
    161167        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    162168            address, endpoint, usb_str_transfer_type(transfer_type),
    163169            usb_str_speed(speed), direction, size, max_packet_size, interval);
    164         // TODO use real endpoint here!
    165         return usb_endpoint_manager_register_ep(&hc->ep_manager,NULL, 0);
    166 }
    167 /*----------------------------------------------------------------------------*/
    168 /** Unregister endpoint (free some bandwidth reservation).
    169  *
    170  * @param[in] fun Device function the action was invoked on.
    171  * @param[in] address USB address of the device.
    172  * @param[in] endpoint Endpoint number.
    173  * @param[in] direction Endpoint data direction.
    174  * @return Error code.
    175  */
     170
     171        return hc_add_endpoint(hc, address, endpoint, speed, transfer_type,
     172            direction, max_packet_size, size, interval);
     173}
     174/*----------------------------------------------------------------------------*/
    176175static int unregister_endpoint(
    177176    ddf_fun_t *fun, usb_address_t address,
    178177    usb_endpoint_t endpoint, usb_direction_t direction)
    179178{
    180         assert(fun);
    181179        hc_t *hc = fun_to_hc(fun);
    182180        assert(hc);
    183181        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    184182            address, endpoint, direction);
    185         return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    186             endpoint, direction);
     183        return hc_remove_endpoint(hc, address, endpoint, direction);
    187184}
    188185/*----------------------------------------------------------------------------*/
     
    196193 * @param[in] fun Device function the action was invoked on.
    197194 * @param[in] target Target pipe (address and endpoint number) specification.
    198  * @param[in] max_packet_size Max packet size for the transfer.
    199195 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    200196 *      by the caller).
     
    205201 */
    206202static int interrupt_out(
    207     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     203    ddf_fun_t *fun, usb_target_t target, void *data,
    208204    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    209205{
    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;
     206        usb_transfer_batch_t *batch = NULL;
     207        hc_t *hc = NULL;
     208        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     209            NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
     210        if (ret != EOK)
     211                return ret;
    224212        batch_interrupt_out(batch);
    225         const int ret = hc_schedule(hc, batch);
    226         if (ret != EOK) {
    227                 batch_dispose(batch);
     213        ret = hc_schedule(hc, batch);
     214        if (ret != EOK) {
     215                usb_transfer_batch_dispose(batch);
    228216        }
    229217        return ret;
     
    239227 * @param[in] fun Device function the action was invoked on.
    240228 * @param[in] target Target pipe (address and endpoint number) specification.
    241  * @param[in] max_packet_size Max packet size for the transfer.
    242229 * @param[in] data Buffer where to store the data (in USB endianess,
    243230 *      allocated and deallocated by the caller).
     
    248235 */
    249236static int interrupt_in(
    250     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     237    ddf_fun_t *fun, usb_target_t target, void *data,
    251238    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    252239{
    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;
     240        usb_transfer_batch_t *batch = NULL;
     241        hc_t *hc = NULL;
     242        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     243            NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
     244        if (ret != EOK)
     245                return ret;
    266246        batch_interrupt_in(batch);
    267         const int ret = hc_schedule(hc, batch);
    268         if (ret != EOK) {
    269                 batch_dispose(batch);
     247        ret = hc_schedule(hc, batch);
     248        if (ret != EOK) {
     249                usb_transfer_batch_dispose(batch);
    270250        }
    271251        return ret;
     
    281261 * @param[in] fun Device function the action was invoked on.
    282262 * @param[in] target Target pipe (address and endpoint number) specification.
    283  * @param[in] max_packet_size Max packet size for the transfer.
    284263 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
    285264 *      by the caller).
     
    290269 */
    291270static int bulk_out(
    292     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     271    ddf_fun_t *fun, usb_target_t target, void *data,
    293272    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    294273{
    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;
     274        usb_transfer_batch_t *batch = NULL;
     275        hc_t *hc = NULL;
     276        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     277            NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
     278        if (ret != EOK)
     279                return ret;
    309280        batch_bulk_out(batch);
    310         const int ret = hc_schedule(hc, batch);
    311         if (ret != EOK) {
    312                 batch_dispose(batch);
     281        ret = hc_schedule(hc, batch);
     282        if (ret != EOK) {
     283                usb_transfer_batch_dispose(batch);
    313284        }
    314285        return ret;
     
    324295 * @param[in] fun Device function the action was invoked on.
    325296 * @param[in] target Target pipe (address and endpoint number) specification.
    326  * @param[in] max_packet_size Max packet size for the transfer.
    327297 * @param[in] data Buffer where to store the data (in USB endianess,
    328298 *      allocated and deallocated by the caller).
     
    333303 */
    334304static int bulk_in(
    335     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     305    ddf_fun_t *fun, usb_target_t target, void *data,
    336306    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    337307{
    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;
     308        usb_transfer_batch_t *batch = NULL;
     309        hc_t *hc = NULL;
     310        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     311            NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
     312        if (ret != EOK)
     313                return ret;
    351314        batch_bulk_in(batch);
    352         const int ret = hc_schedule(hc, batch);
    353         if (ret != EOK) {
    354                 batch_dispose(batch);
     315        ret = hc_schedule(hc, batch);
     316        if (ret != EOK) {
     317                usb_transfer_batch_dispose(batch);
    355318        }
    356319        return ret;
     
    366329 * @param[in] fun Device function the action was invoked on.
    367330 * @param[in] target Target pipe (address and endpoint number) specification.
    368  * @param[in] max_packet_size Max packet size for the transfer.
    369331 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    370332 *      and deallocated by the caller).
    371  * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
     333 * @param[in] setup_size Size of @p setup_packet buffer in bytes.
    372334 * @param[in] data_buffer Data buffer (in USB endianess, allocated and
    373335 *      deallocated by the caller).
    374  * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
     336 * @param[in] size Size of @p data_buffer buffer in bytes.
    375337 * @param[in] callback Callback to be issued once the transfer is complete.
    376338 * @param[in] arg Pass-through argument to the callback.
     
    378340 */
    379341static int control_write(
    380     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     342    ddf_fun_t *fun, usb_target_t target,
    381343    void *setup_data, size_t setup_size, void *data, size_t size,
    382344    usbhc_iface_transfer_out_callback_t callback, void *arg)
    383345{
    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);
     346        usb_transfer_batch_t *batch = NULL;
     347        hc_t *hc = NULL;
     348        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     349            setup_data, setup_size, NULL, callback, arg, "Control WRITE",
     350            &hc, &batch);
     351        if (ret != EOK)
     352                return ret;
     353        usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
    402354        batch_control_write(batch);
    403         const int ret = hc_schedule(hc, batch);
    404         if (ret != EOK) {
    405                 batch_dispose(batch);
     355        ret = hc_schedule(hc, batch);
     356        if (ret != EOK) {
     357                usb_transfer_batch_dispose(batch);
    406358        }
    407359        return ret;
     
    417369 * @param[in] fun Device function the action was invoked on.
    418370 * @param[in] target Target pipe (address and endpoint number) specification.
    419  * @param[in] max_packet_size Max packet size for the transfer.
    420371 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
    421372 *      and deallocated by the caller).
    422  * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
     373 * @param[in] setup_size Size of @p setup_packet buffer in bytes.
    423374 * @param[in] data_buffer Buffer where to store the data (in USB endianess,
    424375 *      allocated and deallocated by the caller).
    425  * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
     376 * @param[in] size Size of @p data_buffer buffer in bytes.
    426377 * @param[in] callback Callback to be issued once the transfer is complete.
    427378 * @param[in] arg Pass-through argument to the callback.
     
    429380 */
    430381static int control_read(
    431     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     382    ddf_fun_t *fun, usb_target_t target,
    432383    void *setup_data, size_t setup_size, void *data, size_t size,
    433384    usbhc_iface_transfer_in_callback_t callback, void *arg)
    434385{
    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;
     386        usb_transfer_batch_t *batch = NULL;
     387        hc_t *hc = NULL;
     388        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     389            setup_data, setup_size, callback, NULL, arg, "Control READ",
     390            &hc, &batch);
     391        if (ret != EOK)
     392                return ret;
    449393        batch_control_read(batch);
    450         const int ret = hc_schedule(hc, batch);
    451         if (ret != EOK) {
    452                 batch_dispose(batch);
    453         }
    454         return ret;
    455 }
    456 /*----------------------------------------------------------------------------*/
    457 /** Host controller interface implementation for OHCI. */
     394        ret = hc_schedule(hc, batch);
     395        if (ret != EOK) {
     396                usb_transfer_batch_dispose(batch);
     397        }
     398        return ret;
     399}
     400/*----------------------------------------------------------------------------*/
    458401usbhc_iface_t hc_iface = {
    459         .reserve_default_address = reserve_default_address,
    460         .release_default_address = release_default_address,
    461402        .request_address = request_address,
    462403        .bind_address = bind_address,
     
    475416        .control_read = control_read,
    476417};
    477 
    478418/**
    479419 * @}
  • uspace/drv/ohci/ohci.ma

    ref354b6 re50cd7f  
    1110 pci/ven=106b&dev=003f
     210 pci/ven=10de&dev=0aa5
     310 pci/ven=10de&dev=0aa5
  • uspace/drv/ohci/ohci_regs.h

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

    ref354b6 re50cd7f  
    4747 *      standart device descriptor for ohci root hub
    4848 */
    49 static const usb_standard_device_descriptor_t ohci_rh_device_descriptor =
    50 {
    51                 .configuration_count = 1,
    52                 .descriptor_type = USB_DESCTYPE_DEVICE,
    53                 .device_class = USB_CLASS_HUB,
    54                 .device_protocol = 0,
    55                 .device_subclass = 0,
    56                 .device_version = 0,
    57                 .length = sizeof(usb_standard_device_descriptor_t),
    58                 /// \TODO this value is guessed
    59                 .max_packet_size = 8,
    60                 .vendor_id = 0x16db,
    61                 .product_id = 0x0001,
    62                 /// \TODO these values migt be different
    63                 .str_serial_number = 0,
    64                 .usb_spec_version = 0x110,
     49static const usb_standard_device_descriptor_t ohci_rh_device_descriptor = {
     50        .configuration_count = 1,
     51        .descriptor_type = USB_DESCTYPE_DEVICE,
     52        .device_class = USB_CLASS_HUB,
     53        .device_protocol = 0,
     54        .device_subclass = 0,
     55        .device_version = 0,
     56        .length = sizeof (usb_standard_device_descriptor_t),
     57        /// \TODO this value is guessed
     58        .max_packet_size = 8,
     59        .vendor_id = 0x16db,
     60        .product_id = 0x0001,
     61        /// \TODO these values migt be different
     62        .str_serial_number = 0,
     63        .usb_spec_version = 0x110,
    6564};
    6665
     
    6968 * for ohci root hubs
    7069 */
    71 static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor =
    72 {
     70static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = {
    7371        /// \TODO some values are default or guessed
    74         .attributes = 1<<7,
     72        .attributes = 1 << 7,
    7573        .configuration_number = 1,
    7674        .descriptor_type = USB_DESCTYPE_CONFIGURATION,
    7775        .interface_count = 1,
    78         .length = sizeof(usb_standard_configuration_descriptor_t),
     76        .length = sizeof (usb_standard_configuration_descriptor_t),
    7977        .max_power = 100,
    8078        .str_configuration = 0,
     
    8482 * standart ohci root hub interface descriptor
    8583 */
    86 static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor =
    87 {
     84static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor = {
    8885        .alternate_setting = 0,
    8986        .descriptor_type = USB_DESCTYPE_INTERFACE,
     
    9491        .interface_protocol = 0,
    9592        .interface_subclass = 0,
    96         .length = sizeof(usb_standard_interface_descriptor_t),
     93        .length = sizeof (usb_standard_interface_descriptor_t),
    9794        .str_interface = 0,
    9895};
     
    10198 * standart ohci root hub endpoint descriptor
    10299 */
    103 static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor =
    104 {
     100static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor = {
    105101        .attributes = USB_TRANSFER_INTERRUPT,
    106102        .descriptor_type = USB_DESCTYPE_ENDPOINT,
    107         .endpoint_address = 1 + (1<<7),
    108         .length = sizeof(usb_standard_endpoint_descriptor_t),
     103        .endpoint_address = 1 + (1 << 7),
     104        .length = sizeof (usb_standard_endpoint_descriptor_t),
    109105        .max_packet_size = 8,
    110106        .poll_interval = 255,
     
    112108
    113109static const uint32_t hub_clear_feature_valid_mask =
    114         (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) +
    115         (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
     110        (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) |
     111(1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
    116112
    117113static const uint32_t hub_clear_feature_by_writing_one_mask =
     
    119115
    120116static const uint32_t hub_set_feature_valid_mask =
    121         (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
    122 
    123        
     117        (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT) |
     118(1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
     119
     120
    124121static const uint32_t hub_set_feature_direct_mask =
    125122        (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
    126123
    127124static const uint32_t port_set_feature_valid_mask =
    128         (1 << USB_HUB_FEATURE_PORT_ENABLE) +
    129         (1 << USB_HUB_FEATURE_PORT_SUSPEND) +
    130         (1 << USB_HUB_FEATURE_PORT_RESET) +
    131         (1 << USB_HUB_FEATURE_PORT_POWER);
     125        (1 << USB_HUB_FEATURE_PORT_ENABLE) |
     126(1 << USB_HUB_FEATURE_PORT_SUSPEND) |
     127(1 << USB_HUB_FEATURE_PORT_RESET) |
     128(1 << USB_HUB_FEATURE_PORT_POWER);
    132129
    133130static const uint32_t port_clear_feature_valid_mask =
    134         (1 << USB_HUB_FEATURE_PORT_CONNECTION) +
    135         (1 << USB_HUB_FEATURE_PORT_SUSPEND) +
    136         (1 << USB_HUB_FEATURE_PORT_OVER_CURRENT) +
    137         (1 << USB_HUB_FEATURE_PORT_POWER) +
    138         (1 << USB_HUB_FEATURE_C_PORT_CONNECTION) +
    139         (1 << USB_HUB_FEATURE_C_PORT_ENABLE) +
    140         (1 << USB_HUB_FEATURE_C_PORT_SUSPEND) +
    141         (1 << USB_HUB_FEATURE_C_PORT_OVER_CURRENT) +
    142         (1 << USB_HUB_FEATURE_C_PORT_RESET);
    143 //note that USB_HUB_FEATURE_PORT_POWER bit is translated into USB_HUB_FEATURE_PORT_LOW_SPEED
    144 
    145 
    146 
     131        (1 << USB_HUB_FEATURE_PORT_CONNECTION) |
     132(1 << USB_HUB_FEATURE_PORT_SUSPEND) |
     133(1 << USB_HUB_FEATURE_PORT_OVER_CURRENT) |
     134(1 << USB_HUB_FEATURE_PORT_POWER) |
     135(1 << USB_HUB_FEATURE_C_PORT_CONNECTION) |
     136(1 << USB_HUB_FEATURE_C_PORT_ENABLE) |
     137(1 << USB_HUB_FEATURE_C_PORT_SUSPEND) |
     138(1 << USB_HUB_FEATURE_C_PORT_OVER_CURRENT) |
     139(1 << USB_HUB_FEATURE_C_PORT_RESET);
     140//note that USB_HUB_FEATURE_PORT_POWER bit is translated into
     141//USB_HUB_FEATURE_PORT_LOW_SPEED
     142
     143static const uint32_t port_status_change_mask =
     144(1<< USB_HUB_FEATURE_C_PORT_CONNECTION) |
     145(1<< USB_HUB_FEATURE_C_PORT_ENABLE) |
     146(1<< USB_HUB_FEATURE_C_PORT_OVER_CURRENT) |
     147(1<< USB_HUB_FEATURE_C_PORT_RESET) |
     148(1<< USB_HUB_FEATURE_C_PORT_SUSPEND);
     149
     150
     151static void usb_create_serialized_hub_descriptor(rh_t *instance,
     152        uint8_t ** out_result,
     153        size_t * out_size);
     154
     155static void rh_init_descriptors(rh_t *instance);
     156
     157static int process_get_port_status_request(rh_t *instance, uint16_t port,
     158        usb_transfer_batch_t * request);
     159
     160static int process_get_hub_status_request(rh_t *instance,
     161        usb_transfer_batch_t * request);
     162
     163static int process_get_status_request(rh_t *instance,
     164        usb_transfer_batch_t * request);
     165
     166static void create_interrupt_mask(rh_t *instance, void ** buffer,
     167        size_t * buffer_size);
     168
     169static int process_get_descriptor_request(rh_t *instance,
     170        usb_transfer_batch_t *request);
     171
     172static int process_get_configuration_request(rh_t *instance,
     173        usb_transfer_batch_t *request);
     174
     175static int process_hub_feature_set_request(rh_t *instance, uint16_t feature);
     176
     177static int process_hub_feature_clear_request(rh_t *instance,
     178        uint16_t feature);
     179
     180static int process_port_feature_set_request(rh_t *instance,
     181        uint16_t feature, uint16_t port);
     182
     183static int process_port_feature_clear_request(rh_t *instance,
     184        uint16_t feature, uint16_t port);
     185
     186static int process_address_set_request(rh_t *instance,
     187        uint16_t address);
     188
     189static int process_request_with_output(rh_t *instance,
     190        usb_transfer_batch_t *request);
     191
     192static int process_request_with_input(rh_t *instance,
     193        usb_transfer_batch_t *request);
     194
     195static int process_request_without_data(rh_t *instance,
     196        usb_transfer_batch_t *request);
     197
     198static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
     199
     200static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
     201    void * change_buffer, size_t buffe_size);
     202
     203static bool is_zeros(void * buffer, size_t size);
     204
     205
     206
     207/** Root hub initialization
     208 * @return Error code.
     209 */
     210int rh_init(rh_t *instance, ohci_regs_t *regs) {
     211        assert(instance);
     212        instance->registers = regs;
     213        instance->port_count =
     214            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
     215        rh_init_descriptors(instance);
     216        // set port power mode to no-power-switching
     217        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
     218        instance->unfinished_interrupt_transfer = NULL;
     219        usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
     220        return EOK;
     221}
     222/*----------------------------------------------------------------------------*/
     223
     224/**
     225 * process root hub request
     226 *
     227 * @param instance root hub instance
     228 * @param request structure containing both request and response information
     229 * @return error code
     230 */
     231int rh_request(rh_t *instance, usb_transfer_batch_t *request) {
     232        assert(instance);
     233        assert(request);
     234        int opResult;
     235        if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
     236                usb_log_info("Root hub got CONTROL packet\n");
     237                opResult = process_ctrl_request(instance, request);
     238                usb_transfer_batch_finish_error(request, opResult);
     239        } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
     240                usb_log_info("Root hub got INTERRUPT packet\n");
     241                void * buffer;
     242                size_t buffer_size;
     243                create_interrupt_mask(instance, &buffer,
     244                        &buffer_size);
     245                if(is_zeros(buffer,buffer_size)){
     246                        usb_log_debug("no changes..");
     247                        instance->unfinished_interrupt_transfer=
     248                            request;
     249                        //will be finished later
     250                }else{
     251                        usb_log_debug("processing changes..");
     252                        process_interrupt(instance, request,
     253                            buffer, buffer_size);
     254                }
     255                free(buffer);
     256                opResult = EOK;
     257        } else {
     258                opResult = EINVAL;
     259                usb_transfer_batch_finish_error(request, opResult);
     260        }
     261        return EOK;
     262}
     263
     264/*----------------------------------------------------------------------------*/
     265
     266
     267void rh_interrupt(rh_t *instance) {
     268        //usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
     269        //      "interrupts, am I?\n");
     270        if(!instance->unfinished_interrupt_transfer){
     271                return;
     272        }
     273        size_t size;
     274        void * buffer;
     275        create_interrupt_mask(instance, &buffer,
     276                        &size);
     277        process_interrupt(instance,instance->unfinished_interrupt_transfer,
     278            buffer,size);
     279        free(buffer);
     280}
     281/*----------------------------------------------------------------------------*/
    147282
    148283/**
     
    157292 */
    158293static void usb_create_serialized_hub_descriptor(rh_t *instance,
    159                 uint8_t ** out_result,
    160                 size_t * out_size) {
     294        uint8_t ** out_result,
     295        size_t * out_size) {
    161296        //base size
    162297        size_t size = 7;
    163298        //variable size according to port count
    164299        size_t var_size = instance->port_count / 8 +
    165                         ((instance->port_count % 8 > 0) ? 1 : 0);
     300                ((instance->port_count % 8 > 0) ? 1 : 0);
    166301        size += 2 * var_size;
    167302        uint8_t * result = (uint8_t*) malloc(size);
    168         bzero(result,size);
     303        bzero(result, size);
    169304        //size
    170305        result[0] = size;
     
    174309        uint32_t hub_desc_reg = instance->registers->rh_desc_a;
    175310        result[3] =
    176                         ((hub_desc_reg >> 8) %2) +
    177                         (((hub_desc_reg >> 9) %2) << 1) +
    178                         (((hub_desc_reg >> 10) %2) << 2) +
    179                         (((hub_desc_reg >> 11) %2) << 3) +
    180                         (((hub_desc_reg >> 12) %2) << 4);
     311                ((hub_desc_reg >> 8) % 2) +
     312                (((hub_desc_reg >> 9) % 2) << 1) +
     313                (((hub_desc_reg >> 10) % 2) << 2) +
     314                (((hub_desc_reg >> 11) % 2) << 3) +
     315                (((hub_desc_reg >> 12) % 2) << 4);
    181316        result[4] = 0;
    182317        result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
     
    185320        int port;
    186321        for (port = 1; port <= instance->port_count; ++port) {
    187                 result[7 + port/8] +=
    188                                 ((instance->registers->rh_desc_b >> port)%2) << (port%8);
     322                uint8_t is_non_removable =
     323                        instance->registers->rh_desc_b >> port % 2;
     324                result[7 + port / 8] +=
     325                        is_non_removable << (port % 8);
    189326        }
    190327        size_t i;
     
    195332        (*out_size) = size;
    196333}
    197 
     334/*----------------------------------------------------------------------------*/
    198335
    199336/** initialize hub descriptors
     
    203340 * @instance root hub instance
    204341 */
    205 static void rh_init_descriptors(rh_t *instance){
     342static void rh_init_descriptors(rh_t *instance) {
    206343        memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    207                 sizeof(ohci_rh_device_descriptor)
    208         );
     344                sizeof (ohci_rh_device_descriptor)
     345                );
    209346        usb_standard_configuration_descriptor_t descriptor;
    210         memcpy(&descriptor,&ohci_rh_conf_descriptor,
    211                         sizeof(ohci_rh_conf_descriptor));
     347        memcpy(&descriptor, &ohci_rh_conf_descriptor,
     348                sizeof (ohci_rh_conf_descriptor));
    212349        uint8_t * hub_descriptor;
    213350        size_t hub_desc_size;
    214351        usb_create_serialized_hub_descriptor(instance, &hub_descriptor,
    215                         &hub_desc_size);
     352                &hub_desc_size);
    216353
    217354        descriptor.total_length =
    218                         sizeof(usb_standard_configuration_descriptor_t)+
    219                         sizeof(usb_standard_endpoint_descriptor_t)+
    220                         sizeof(usb_standard_interface_descriptor_t)+
    221                         hub_desc_size;
    222        
     355                sizeof (usb_standard_configuration_descriptor_t) +
     356                sizeof (usb_standard_endpoint_descriptor_t) +
     357                sizeof (usb_standard_interface_descriptor_t) +
     358                hub_desc_size;
     359
    223360        uint8_t * full_config_descriptor =
    224                         (uint8_t*) malloc(descriptor.total_length);
    225         memcpy(full_config_descriptor, &descriptor, sizeof(descriptor));
    226         memcpy(full_config_descriptor + sizeof(descriptor),
    227                         &ohci_rh_iface_descriptor, sizeof(ohci_rh_iface_descriptor));
    228         memcpy(full_config_descriptor + sizeof(descriptor) +
    229                                 sizeof(ohci_rh_iface_descriptor),
    230                         &ohci_rh_ep_descriptor, sizeof(ohci_rh_ep_descriptor));
    231         memcpy(full_config_descriptor + sizeof(descriptor) +
    232                                 sizeof(ohci_rh_iface_descriptor) +
    233                                 sizeof(ohci_rh_ep_descriptor),
    234                         hub_descriptor, hub_desc_size);
    235        
     361                (uint8_t*) malloc(descriptor.total_length);
     362        memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
     363        memcpy(full_config_descriptor + sizeof (descriptor),
     364                &ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor));
     365        memcpy(full_config_descriptor + sizeof (descriptor) +
     366                sizeof (ohci_rh_iface_descriptor),
     367                &ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor));
     368        memcpy(full_config_descriptor + sizeof (descriptor) +
     369                sizeof (ohci_rh_iface_descriptor) +
     370                sizeof (ohci_rh_ep_descriptor),
     371                hub_descriptor, hub_desc_size);
     372
    236373        instance->descriptors.configuration = full_config_descriptor;
    237374        instance->descriptors.configuration_size = descriptor.total_length;
    238375}
    239 
    240 /** Root hub initialization
    241  * @return Error code.
    242  */
    243 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs)
    244 {
    245         assert(instance);
    246         instance->address = -1;
    247         instance->registers = regs;
    248         instance->device = dev;
    249         instance->port_count = instance->registers->rh_desc_a & 0xff;
    250         rh_init_descriptors(instance);
    251         /// \TODO set port power mode
    252 
    253 
    254         usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
    255 
    256         //start generic usb hub driver
    257        
    258         /* TODO: implement */
    259         return EOK;
    260 }
    261376/*----------------------------------------------------------------------------*/
    262377
     
    272387 */
    273388static int process_get_port_status_request(rh_t *instance, uint16_t port,
    274                 usb_transfer_batch_t * request){
    275         if(port<1 || port>instance->port_count)
    276                 return EINVAL;
    277         uint32_t * uint32_buffer = (uint32_t*)request->transport_buffer;
     389        usb_transfer_batch_t * request) {
     390        if (port < 1 || port > instance->port_count)
     391                return EINVAL;
     392        uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
    278393        request->transfered_size = 4;
    279         uint32_buffer[0] = instance->registers->rh_port_status[port -1];
    280         return EOK;
    281 }
     394        uint32_buffer[0] = instance->registers->rh_port_status[port - 1];
     395#if 0
     396        int i;
     397        for (i = 0; i < instance->port_count; ++i) {
     398                usb_log_debug("port status %d,x%x\n",
     399                        instance->registers->rh_port_status[i],
     400                        instance->registers->rh_port_status[i]);
     401        }
     402#endif
     403        return EOK;
     404}
     405/*----------------------------------------------------------------------------*/
    282406
    283407/**
     
    291415 */
    292416static int process_get_hub_status_request(rh_t *instance,
    293                 usb_transfer_batch_t * request){
    294         uint32_t * uint32_buffer = (uint32_t*)request->transport_buffer;
     417        usb_transfer_batch_t * request) {
     418        uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
     419        request->transfered_size = 4;
    295420        //bits, 0,1,16,17
    296         request->transfered_size = 4;
    297         uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17);
     421        uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17);
    298422        uint32_buffer[0] = mask & instance->registers->rh_status;
    299423        return EOK;
    300 
    301 }
    302 
    303 
     424}
     425/*----------------------------------------------------------------------------*/
    304426
    305427/**
     
    313435 */
    314436static int process_get_status_request(rh_t *instance,
    315                 usb_transfer_batch_t * request)
    316 {
     437        usb_transfer_batch_t * request) {
    317438        size_t buffer_size = request->buffer_size;
    318439        usb_device_request_setup_packet_t * request_packet =
    319                         (usb_device_request_setup_packet_t*)
    320                         request->setup_buffer;
     440                (usb_device_request_setup_packet_t*)
     441                request->setup_buffer;
    321442
    322443        usb_hub_bm_request_type_t request_type = request_packet->request_type;
    323         if(buffer_size<4/*request_packet->length*/){///\TODO
     444        if (buffer_size < 4/*request_packet->length*/) {///\TODO
    324445                usb_log_warning("requested more data than buffer size\n");
    325446                return EINVAL;
    326447        }
    327448
    328         if(request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
     449        if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
    329450                return process_get_hub_status_request(instance, request);
    330         if(request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
    331                 return process_get_port_status_request(instance, request_packet->index,
    332                                 request);
     451        if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
     452                return process_get_port_status_request(instance,
     453                request_packet->index,
     454                request);
    333455        return ENOTSUP;
    334456}
     457/*----------------------------------------------------------------------------*/
    335458
    336459/**
     
    339462 * Result contains bitmap where bit 0 indicates change on hub and
    340463 * bit i indicates change on i`th port (i>0). For more info see
    341  * Hub and Port status bitmap specification in USB specification.
     464 * Hub and Port status bitmap specification in USB specification
     465 * (chapter 11.13.4)
    342466 * @param instance root hub instance
    343467 * @param@out buffer pointer to created interrupt mas
     
    345469 */
    346470static void create_interrupt_mask(rh_t *instance, void ** buffer,
    347                 size_t * buffer_size){
     471        size_t * buffer_size) {
    348472        int bit_count = instance->port_count + 1;
    349         (*buffer_size) = (bit_count / 8) + (bit_count%8==0)?0:1;
     473        (*buffer_size) = (bit_count / 8) + ((bit_count % 8 == 0) ? 0 : 1);
     474
    350475        (*buffer) = malloc(*buffer_size);
    351         uint8_t * bitmap = (uint8_t*)(*buffer);
    352         uint32_t mask = (1<<16) + (1<<17);
    353         bzero(bitmap,(*buffer_size));
    354         if(instance->registers->rh_status & mask){
     476        uint8_t * bitmap = (uint8_t*) (*buffer);
     477        uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
     478                | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
     479        bzero(bitmap, (*buffer_size));
     480        if (instance->registers->rh_status & mask) {
    355481                bitmap[0] = 1;
    356482        }
    357483        int port;
    358         mask = 0;
    359         int i;
    360         for(i=16;i<=20;++i)
    361                 mask += 1<<i;
    362         for(port = 1; port<=instance->port_count;++port){
    363                 if(mask & instance->registers->rh_port_status[port-1]){
    364                         bitmap[(port+1)/8] += 1<<(port%8);
    365                 }
    366         }
    367 }
    368  
     484        mask = port_status_change_mask;
     485        for (port = 1; port <= instance->port_count; ++port) {
     486                if (mask & instance->registers->rh_port_status[port - 1]) {
     487                        bitmap[(port) / 8] += 1 << (port % 8);
     488                }
     489        }
     490}
     491/*----------------------------------------------------------------------------*/
     492
    369493/**
    370494 * create answer to a descriptor request
     
    377501 */
    378502static int process_get_descriptor_request(rh_t *instance,
    379                 usb_transfer_batch_t *request){
     503        usb_transfer_batch_t *request) {
    380504        usb_device_request_setup_packet_t * setup_request =
    381                         (usb_device_request_setup_packet_t*)request->setup_buffer;
     505                (usb_device_request_setup_packet_t*) request->setup_buffer;
    382506        size_t size;
    383507        const void * result_descriptor = NULL;
    384508        const uint16_t setup_request_value = setup_request->value_high;
    385                         //(setup_request->value_low << 8);
     509        //(setup_request->value_low << 8);
    386510        bool del = false;
    387         switch (setup_request_value)
    388         {
    389                 case USB_DESCTYPE_HUB: {
     511        switch (setup_request_value) {
     512                case USB_DESCTYPE_HUB:
     513                {
    390514                        uint8_t * descriptor;
    391515                        usb_create_serialized_hub_descriptor(
    392516                                instance, &descriptor, &size);
    393517                        result_descriptor = descriptor;
    394                         if(result_descriptor) del = true;
     518                        if (result_descriptor) del = true;
    395519                        break;
    396520                }
    397                 case USB_DESCTYPE_DEVICE: {
     521                case USB_DESCTYPE_DEVICE:
     522                {
    398523                        usb_log_debug("USB_DESCTYPE_DEVICE\n");
    399524                        result_descriptor = &ohci_rh_device_descriptor;
    400                         size = sizeof(ohci_rh_device_descriptor);
     525                        size = sizeof (ohci_rh_device_descriptor);
    401526                        break;
    402527                }
    403                 case USB_DESCTYPE_CONFIGURATION: {
     528                case USB_DESCTYPE_CONFIGURATION:
     529                {
    404530                        usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
    405531                        result_descriptor = instance->descriptors.configuration;
     
    407533                        break;
    408534                }
    409                 case USB_DESCTYPE_INTERFACE: {
     535                case USB_DESCTYPE_INTERFACE:
     536                {
    410537                        usb_log_debug("USB_DESCTYPE_INTERFACE\n");
    411538                        result_descriptor = &ohci_rh_iface_descriptor;
    412                         size = sizeof(ohci_rh_iface_descriptor);
     539                        size = sizeof (ohci_rh_iface_descriptor);
    413540                        break;
    414541                }
    415                 case USB_DESCTYPE_ENDPOINT: {
     542                case USB_DESCTYPE_ENDPOINT:
     543                {
    416544                        usb_log_debug("USB_DESCTYPE_ENDPOINT\n");
    417545                        result_descriptor = &ohci_rh_ep_descriptor;
    418                         size = sizeof(ohci_rh_ep_descriptor);
     546                        size = sizeof (ohci_rh_ep_descriptor);
    419547                        break;
    420548                }
    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                                         );
     549                default:
     550                {
     551                        usb_log_debug("USB_DESCTYPE_EINVAL %d \n",
     552                                setup_request->value);
     553                        usb_log_debug("\ttype %d\n\trequest %d\n\tvalue "
     554                                "%d\n\tindex %d\n\tlen %d\n ",
     555                                setup_request->request_type,
     556                                setup_request->request,
     557                                setup_request_value,
     558                                setup_request->index,
     559                                setup_request->length
     560                                );
    430561                        return EINVAL;
    431562                }
    432563        }
    433         if(request->buffer_size < size){
     564        if (request->buffer_size < size) {
    434565                size = request->buffer_size;
    435566        }
    436567        request->transfered_size = size;
    437         memcpy(request->transport_buffer,result_descriptor,size);
    438         usb_log_debug("sent desctiptor: %s\n",
    439                         usb_debug_str_buffer((uint8_t*)request->transport_buffer,size,size));
     568        memcpy(request->data_buffer, result_descriptor, size);
    440569        if (del)
    441570                free(result_descriptor);
    442571        return EOK;
    443572}
     573/*----------------------------------------------------------------------------*/
    444574
    445575/**
     
    451581 * @return error code
    452582 */
    453 static int process_get_configuration_request(rh_t *instance, 
    454                 usb_transfer_batch_t *request){
     583static int process_get_configuration_request(rh_t *instance,
     584        usb_transfer_batch_t *request) {
    455585        //set and get configuration requests do not have any meaning, only dummy
    456586        //values are returned
    457         if(request->buffer_size != 1)
    458                 return EINVAL;
    459         request->transport_buffer[0] = 1;
     587        if (request->buffer_size != 1)
     588                return EINVAL;
     589        request->data_buffer[0] = 1;
    460590        request->transfered_size = 1;
    461591        return EOK;
    462592}
     593/*----------------------------------------------------------------------------*/
    463594
    464595/**
    465596 * process feature-enabling request on hub
    466  * 
     597 *
    467598 * @param instance root hub instance
    468599 * @param feature feature selector
     
    470601 */
    471602static int process_hub_feature_set_request(rh_t *instance,
    472                 uint16_t feature){
    473         if(! ((1<<feature) & hub_set_feature_valid_mask))
    474                 return EINVAL;
     603        uint16_t feature) {
     604        if (!((1 << feature) & hub_set_feature_valid_mask))
     605                return EINVAL;
     606        if(feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
     607                feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;
    475608        instance->registers->rh_status =
    476                         (instance->registers->rh_status | (1<<feature))
    477                         & (~ hub_clear_feature_by_writing_one_mask);
    478         return EOK;
    479 }
     609                (instance->registers->rh_status | (1 << feature))
     610                & (~hub_clear_feature_by_writing_one_mask);
     611        return EOK;
     612}
     613/*----------------------------------------------------------------------------*/
    480614
    481615/**
     
    487621 */
    488622static int process_hub_feature_clear_request(rh_t *instance,
    489                 uint16_t feature){
    490         if(! ((1<<feature) & hub_clear_feature_valid_mask))
     623        uint16_t feature) {
     624        if (!((1 << feature) & hub_clear_feature_valid_mask))
    491625                return EINVAL;
    492626        //is the feature cleared directly?
    493         if ((1<<feature) & hub_set_feature_direct_mask){
     627        if ((1 << feature) & hub_set_feature_direct_mask) {
    494628                instance->registers->rh_status =
    495                         (instance->registers->rh_status & (~(1<<feature)))
    496                         & (~ hub_clear_feature_by_writing_one_mask);
    497         }else{//the feature is cleared by writing '1'
     629                        (instance->registers->rh_status & (~(1 << feature)))
     630                        & (~hub_clear_feature_by_writing_one_mask);
     631        } else {//the feature is cleared by writing '1'
    498632                instance->registers->rh_status =
    499                                 (instance->registers->rh_status
    500                                 & (~ hub_clear_feature_by_writing_one_mask))
    501                                 | (1<<feature);
    502         }
    503         return EOK;
    504 }
    505 
    506 
     633                        (instance->registers->rh_status
     634                        & (~hub_clear_feature_by_writing_one_mask))
     635                        | (1 << feature);
     636        }
     637        return EOK;
     638}
     639/*----------------------------------------------------------------------------*/
    507640
    508641/**
    509642 * process feature-enabling request on hub
    510  * 
     643 *
    511644 * @param instance root hub instance
    512645 * @param feature feature selector
     
    516649 */
    517650static int process_port_feature_set_request(rh_t *instance,
    518                 uint16_t feature, uint16_t port){
    519         if(!((1<<feature) & port_set_feature_valid_mask))
    520                 return EINVAL;
    521         if(port<1 || port>instance->port_count)
     651        uint16_t feature, uint16_t port) {
     652        if (!((1 << feature) & port_set_feature_valid_mask))
     653                return EINVAL;
     654        if (port < 1 || port > instance->port_count)
    522655                return EINVAL;
    523656        instance->registers->rh_port_status[port - 1] =
    524                         (instance->registers->rh_port_status[port - 1] | (1<<feature))
    525                         & (~port_clear_feature_valid_mask);
     657                (instance->registers->rh_port_status[port - 1] | (1 << feature))
     658                & (~port_clear_feature_valid_mask);
    526659        /// \TODO any error?
    527660        return EOK;
    528661}
     662/*----------------------------------------------------------------------------*/
    529663
    530664/**
     
    538672 */
    539673static int process_port_feature_clear_request(rh_t *instance,
    540                 uint16_t feature, uint16_t port){
    541         if(!((1<<feature) & port_clear_feature_valid_mask))
    542                 return EINVAL;
    543         if(port<1 || port>instance->port_count)
    544                 return EINVAL;
    545         if(feature == USB_HUB_FEATURE_PORT_POWER)
     674        uint16_t feature, uint16_t port) {
     675        if (!((1 << feature) & port_clear_feature_valid_mask))
     676                return EINVAL;
     677        if (port < 1 || port > instance->port_count)
     678                return EINVAL;
     679        if (feature == USB_HUB_FEATURE_PORT_POWER)
    546680                feature = USB_HUB_FEATURE_PORT_LOW_SPEED;
    547         if(feature == USB_HUB_FEATURE_PORT_SUSPEND)
     681        if (feature == USB_HUB_FEATURE_PORT_SUSPEND)
    548682                feature = USB_HUB_FEATURE_PORT_OVER_CURRENT;
    549683        instance->registers->rh_port_status[port - 1] =
    550                         (instance->registers->rh_port_status[port - 1]
    551                         & (~port_clear_feature_valid_mask))
    552                         | (1<<feature);
     684                (instance->registers->rh_port_status[port - 1]
     685                & (~port_clear_feature_valid_mask))
     686                | (1 << feature);
    553687        /// \TODO any error?
    554688        return EOK;
    555689}
    556 
     690/*----------------------------------------------------------------------------*/
    557691
    558692/**
    559693 * register address to this device
    560  * 
     694 *
    561695 * @param instance root hub instance
    562696 * @param address new address
     
    564698 */
    565699static int process_address_set_request(rh_t *instance,
    566                 uint16_t address){
     700        uint16_t address) {
    567701        instance->address = address;
    568702        return EOK;
    569703}
     704/*----------------------------------------------------------------------------*/
    570705
    571706/**
     
    579714 */
    580715static int process_request_with_output(rh_t *instance,
    581                 usb_transfer_batch_t *request){
     716        usb_transfer_batch_t *request) {
    582717        usb_device_request_setup_packet_t * setup_request =
    583                         (usb_device_request_setup_packet_t*)request->setup_buffer;
    584         if(setup_request->request == USB_DEVREQ_GET_STATUS){
     718                (usb_device_request_setup_packet_t*) request->setup_buffer;
     719        if (setup_request->request == USB_DEVREQ_GET_STATUS) {
    585720                usb_log_debug("USB_DEVREQ_GET_STATUS\n");
    586721                return process_get_status_request(instance, request);
    587722        }
    588         if(setup_request->request == USB_DEVREQ_GET_DESCRIPTOR){
     723        if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) {
    589724                usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
    590725                return process_get_descriptor_request(instance, request);
    591726        }
    592         if(setup_request->request == USB_DEVREQ_GET_CONFIGURATION){
     727        if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) {
    593728                usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
    594729                return process_get_configuration_request(instance, request);
     
    596731        return ENOTSUP;
    597732}
     733/*----------------------------------------------------------------------------*/
    598734
    599735/**
     
    607743 */
    608744static int process_request_with_input(rh_t *instance,
    609                 usb_transfer_batch_t *request){
     745        usb_transfer_batch_t *request) {
    610746        usb_device_request_setup_packet_t * setup_request =
    611                         (usb_device_request_setup_packet_t*)request->setup_buffer;
     747                (usb_device_request_setup_packet_t*) request->setup_buffer;
    612748        request->transfered_size = 0;
    613         if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR){
     749        if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) {
    614750                return ENOTSUP;
    615751        }
    616         if(setup_request->request == USB_DEVREQ_SET_CONFIGURATION){
     752        if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) {
    617753                //set and get configuration requests do not have any meaning,
    618754                //only dummy values are returned
     
    621757        return ENOTSUP;
    622758}
     759/*----------------------------------------------------------------------------*/
    623760
    624761/**
     
    632769 */
    633770static int process_request_without_data(rh_t *instance,
    634                 usb_transfer_batch_t *request){
     771        usb_transfer_batch_t *request) {
    635772        usb_device_request_setup_packet_t * setup_request =
    636                         (usb_device_request_setup_packet_t*)request->setup_buffer;
     773                (usb_device_request_setup_packet_t*) request->setup_buffer;
    637774        request->transfered_size = 0;
    638         if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE){
    639                 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){
     775        if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) {
     776                if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
    640777                        usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    641778                        return process_hub_feature_clear_request(instance,
    642                                         setup_request->value);
    643                 }
    644                 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
     779                                setup_request->value);
     780                }
     781                if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
    645782                        usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    646783                        return process_port_feature_clear_request(instance,
    647                                         setup_request->value,
    648                                         setup_request->index);
     784                                setup_request->value,
     785                                setup_request->index);
    649786                }
    650787                usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
    651                                 setup_request->request_type);
    652                 return EINVAL;
    653         }
    654         if(setup_request->request == USB_DEVREQ_SET_FEATURE){
    655                 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){
     788                        setup_request->request_type);
     789                return EINVAL;
     790        }
     791        if (setup_request->request == USB_DEVREQ_SET_FEATURE) {
     792                if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
    656793                        usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
    657794                        return process_hub_feature_set_request(instance,
    658                                         setup_request->value);
    659                 }
    660                 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
     795                                setup_request->value);
     796                }
     797                if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
    661798                        usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
    662799                        return process_port_feature_set_request(instance,
    663                                         setup_request->value,
    664                                         setup_request->index);
    665                 }
    666                 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",setup_request->request_type);
    667                 return EINVAL;
    668         }
    669         if(setup_request->request == USB_DEVREQ_SET_ADDRESS){
     800                                setup_request->value,
     801                                setup_request->index);
     802                }
     803                usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
     804                        setup_request->request_type);
     805                return EINVAL;
     806        }
     807        if (setup_request->request == USB_DEVREQ_SET_ADDRESS) {
    670808                usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
    671                 return process_address_set_request(instance, setup_request->value);
    672         }
    673         usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",setup_request->request_type);
     809                return process_address_set_request(instance,
     810                        setup_request->value);
     811        }
     812        usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",
     813                setup_request->request_type);
    674814        return ENOTSUP;
    675815}
     816/*----------------------------------------------------------------------------*/
    676817
    677818/**
     
    693834 * @return error code
    694835 */
    695 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request){
     836static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) {
     837        if (!request->setup_buffer) {
     838                usb_log_error("root hub received empty transaction?");
     839                return EINVAL;
     840        }
    696841        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                 ){
     842        if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) {
     843                usb_log_error("setup packet too small\n");
     844                return EINVAL;
     845        }
     846        usb_log_info("CTRL packet: %s.\n",
     847                usb_debug_str_buffer(
     848                (const uint8_t *) request->setup_buffer, 8, 8));
     849        usb_device_request_setup_packet_t * setup_request =
     850                (usb_device_request_setup_packet_t*)
     851                request->setup_buffer;
     852        switch (setup_request->request) {
     853                case USB_DEVREQ_GET_STATUS:
     854                case USB_DEVREQ_GET_DESCRIPTOR:
     855                case USB_DEVREQ_GET_CONFIGURATION:
    711856                        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                                         );
     857                        opResult = process_request_with_output(
     858                                instance, request);
     859                        break;
     860                case USB_DEVREQ_CLEAR_FEATURE:
     861                case USB_DEVREQ_SET_FEATURE:
     862                case USB_DEVREQ_SET_ADDRESS:
     863                        usb_log_debug("processing request without "
     864                                "additional data\n");
     865                        opResult = process_request_without_data(
     866                                instance, request);
     867                        break;
     868                case USB_DEVREQ_SET_DESCRIPTOR:
     869                case USB_DEVREQ_SET_CONFIGURATION:
     870                        usb_log_debug("processing request with "
     871                                "input\n");
     872                        opResult = process_request_with_input(
     873                                instance, request);
     874                        break;
     875                default:
     876                        usb_log_warning("received unsuported request: "
     877                                "%d\n",
     878                                setup_request->request
     879                                );
    729880                        opResult = ENOTSUP;
    730                 }
    731         }else{
    732                 usb_log_error("root hub received empty transaction?");
    733                 opResult = EINVAL;
    734881        }
    735882        return opResult;
    736883}
    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  */
    745 int rh_request(rh_t *instance, usb_transfer_batch_t *request)
    746 {
    747         assert(instance);
    748         assert(request);
    749         int opResult;
    750         if(request->transfer_type == USB_TRANSFER_CONTROL){
    751                 usb_log_info("Root hub got CONTROL packet\n");
    752                 opResult = process_ctrl_request(instance,request);
    753         }else if(request->transfer_type == USB_TRANSFER_INTERRUPT){
    754                 usb_log_info("Root hub got INTERRUPT packet\n");
    755                 void * buffer;
    756                 create_interrupt_mask(instance, &buffer,
    757                         &(request->transfered_size));
    758                 memcpy(request->transport_buffer,buffer, request->transfered_size);
    759                 opResult = EOK;
    760         }else{
    761                 opResult = EINVAL;
    762         }
    763         usb_transfer_batch_finish(request, opResult);
    764         return EOK;
    765 }
    766 /*----------------------------------------------------------------------------*/
    767 
    768 
    769 void rh_interrupt(rh_t *instance)
    770 {
    771         usb_log_info("Whoa whoa wait, I`m not supposed to receive any interrupts, am I?\n");
    772         /* TODO: implement? */
    773 }
     884/*----------------------------------------------------------------------------*/
     885
     886/**
     887 * process hanging interrupt request
     888 *
     889 * If an interrupt transfer has been received and there was no change,
     890 * the driver stores the transfer information and waits for change to occcur.
     891 * This routine is called when that happens and it finalizes the interrupt
     892 * transfer.
     893 *
     894 * @param instance hub instance
     895 * @param request batch request to be processed
     896 * @param change_buffer chages on hub
     897 * @param buffer_size size of change buffer
     898 *
     899 * @return
     900 */
     901static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
     902    void * change_buffer, size_t buffe_size){
     903        create_interrupt_mask(instance, &change_buffer,
     904            &(request->transfered_size));
     905        memcpy(request->data_buffer, change_buffer,request->transfered_size);
     906        instance->unfinished_interrupt_transfer = NULL;
     907        usb_transfer_batch_finish_error(request, EOK);
     908        return EOK;
     909}
     910
     911/*----------------------------------------------------------------------------*/
     912
     913/**
     914 * return whether the buffer is full of zeros
     915 *
     916 * Convenience function.
     917 * @param buffer
     918 * @param size
     919 * @return
     920 */
     921static bool is_zeros(void * buffer, size_t size){
     922        if(!buffer) return true;
     923        if(!size) return true;
     924        size_t i;
     925        for(i=0;i<size;++i){
     926                if(((char*)buffer)[i])
     927                        return false;
     928        }
     929        return true;
     930}
     931
    774932/**
    775933 * @}
  • uspace/drv/ohci/root_hub.h

    ref354b6 re50cd7f  
    5050        /** usb address of the root hub */
    5151        usb_address_t address;
    52         /** ddf device information */
    53         ddf_dev_t *device;
    5452        /** hub port count */
    5553        int port_count;
    5654        /** hubs descriptors */
    5755        usb_device_descriptors_t descriptors;
     56        /** interrupt transfer waiting for an actual interrupt to occur */
     57        usb_transfer_batch_t * unfinished_interrupt_transfer;
    5858} rh_t;
    5959
    60 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs);
     60int rh_init(rh_t *instance, ohci_regs_t *regs);
    6161
    6262int rh_request(rh_t *instance, usb_transfer_batch_t *request);
  • uspace/drv/ohci/utils/malloc32.h

    ref354b6 re50cd7f  
    3737#include <assert.h>
    3838#include <malloc.h>
     39#include <errno.h>
    3940#include <mem.h>
    4041#include <as.h>
    4142
    42 #define UHCI_STRCUTURES_ALIGNMENT 16
    4343#define UHCI_REQUIRED_PAGE_SIZE 4096
    4444
     
    6464 */
    6565static inline void * malloc32(size_t size)
    66         { return memalign(UHCI_STRCUTURES_ALIGNMENT, size); }
     66        { return memalign(size, size); }
    6767/*----------------------------------------------------------------------------*/
    6868/** Physical mallocator simulator
  • uspace/drv/uhci-hcd/batch.c

    ref354b6 re50cd7f  
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transaction structure
     32 * @brief UHCI driver USB transfer structure
    3333 */
    3434#include <errno.h>
     
    4545#define DEFAULT_ERROR_COUNT 3
    4646
    47 typedef struct uhci_batch {
     47typedef struct uhci_transfer_batch {
    4848        qh_t *qh;
    4949        td_t *tds;
    50         size_t transfers;
    51 } uhci_batch_t;
     50        void *device_buffer;
     51        size_t td_count;
     52} uhci_transfer_batch_t;
     53/*----------------------------------------------------------------------------*/
     54static void uhci_transfer_batch_dispose(void *uhci_batch)
     55{
     56        uhci_transfer_batch_t *instance = uhci_batch;
     57        assert(instance);
     58        free32(instance->device_buffer);
     59        free(instance);
     60}
     61/*----------------------------------------------------------------------------*/
    5262
    5363static void batch_control(usb_transfer_batch_t *instance,
    5464    usb_packet_id data_stage, usb_packet_id status_stage);
    5565static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
    56 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    57 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    58 
    5966
    6067/** Allocate memory and initialize internal data structure.
    6168 *
    6269 * @param[in] fun DDF function to pass to callback.
    63  * @param[in] target Device and endpoint target of the transaction.
    64  * @param[in] transfer_type Interrupt, Control or Bulk.
    65  * @param[in] max_packet_size maximum allowed size of data transfers.
    66  * @param[in] speed Speed of the transaction.
     70 * @param[in] ep Communication target
    6771 * @param[in] buffer Data source/destination.
    6872 * @param[in] size Size of the buffer.
    6973 * @param[in] setup_buffer Setup data source (if not NULL)
    7074 * @param[in] setup_size Size of setup_buffer (should be always 8)
    71  * @param[in] func_in function to call on inbound transaction completion
    72  * @param[in] func_out function to call on outbound transaction completion
     75 * @param[in] func_in function to call on inbound transfer completion
     76 * @param[in] func_out function to call on outbound transfer completion
    7377 * @param[in] arg additional parameter to func_in or func_out
    74  * @param[in] ep Pointer to endpoint toggle management structure.
    75  * @return Valid pointer if all substructures were successfully created,
     78 * @return Valid pointer if all structures were successfully created,
    7679 * NULL otherwise.
    7780 *
    78  * Determines the number of needed transfers (TDs). Prepares a transport buffer
    79  * (that is accessible by the hardware). Initializes parameters needed for the
    80  * transaction and callback.
    81  */
    82 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    83     usb_transfer_type_t transfer_type, size_t max_packet_size,
    84     usb_speed_t speed, char *buffer, size_t buffer_size,
    85     char* setup_buffer, size_t setup_size,
     81 * Determines the number of needed transfer descriptors (TDs).
     82 * Prepares a transport buffer (that is accessible by the hardware).
     83 * Initializes parameters needed for the transfer and callback.
     84 */
     85usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
     86    char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size,
    8687    usbhc_iface_transfer_in_callback_t func_in,
    87     usbhc_iface_transfer_out_callback_t func_out, void *arg, endpoint_t *ep
    88     )
    89 {
     88    usbhc_iface_transfer_out_callback_t func_out, void *arg)
     89{
     90        assert(ep);
    9091        assert(func_in == NULL || func_out == NULL);
    9192        assert(func_in != NULL || func_out != NULL);
     
    9495        if (ptr == NULL) { \
    9596                usb_log_error(message); \
    96                 if (instance) { \
    97                         batch_dispose(instance); \
     97                if (uhci_data) { \
     98                        uhci_transfer_batch_dispose(uhci_data); \
    9899                } \
    99100                return NULL; \
    100101        } else (void)0
    101102
     103        uhci_transfer_batch_t *uhci_data =
     104            malloc(sizeof(uhci_transfer_batch_t));
     105        CHECK_NULL_DISPOSE_RETURN(uhci_data,
     106            "Failed to allocate UHCI batch.\n");
     107        bzero(uhci_data, sizeof(uhci_transfer_batch_t));
     108
     109        uhci_data->td_count =
     110            (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
     111        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     112                uhci_data->td_count += 2;
     113        }
     114
     115        assert((sizeof(td_t) % 16) == 0);
     116        const size_t total_size = (sizeof(td_t) * uhci_data->td_count)
     117            + sizeof(qh_t) + setup_size + buffer_size;
     118        uhci_data->device_buffer = malloc32(total_size);
     119        CHECK_NULL_DISPOSE_RETURN(uhci_data->device_buffer,
     120            "Failed to allocate UHCI buffer.\n");
     121        bzero(uhci_data->device_buffer, total_size);
     122
     123        uhci_data->tds = uhci_data->device_buffer;
     124        uhci_data->qh =
     125            (uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count));
     126
     127        qh_init(uhci_data->qh);
     128        qh_set_element_td(uhci_data->qh, uhci_data->tds);
     129
    102130        usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
    103131        CHECK_NULL_DISPOSE_RETURN(instance,
    104132            "Failed to allocate batch instance.\n");
    105         usb_transfer_batch_init(instance, target,
    106             transfer_type, speed, max_packet_size,
    107             buffer, NULL, buffer_size, NULL, setup_size, func_in,
    108             func_out, arg, fun, ep, NULL);
    109 
    110 
    111         uhci_batch_t *data = malloc(sizeof(uhci_batch_t));
    112         CHECK_NULL_DISPOSE_RETURN(instance,
    113             "Failed to allocate batch instance.\n");
    114         bzero(data, sizeof(uhci_batch_t));
    115         instance->private_data = data;
    116 
    117         data->transfers = (buffer_size + max_packet_size - 1) / max_packet_size;
    118         if (transfer_type == USB_TRANSFER_CONTROL) {
    119                 data->transfers += 2;
    120         }
    121 
    122         data->tds = malloc32(sizeof(td_t) * data->transfers);
    123         CHECK_NULL_DISPOSE_RETURN(
    124             data->tds, "Failed to allocate transfer descriptors.\n");
    125         bzero(data->tds, sizeof(td_t) * data->transfers);
    126 
    127         data->qh = malloc32(sizeof(qh_t));
    128         CHECK_NULL_DISPOSE_RETURN(data->qh,
    129             "Failed to allocate batch queue head.\n");
    130         qh_init(data->qh);
    131         qh_set_element_td(data->qh, addr_to_phys(data->tds));
    132 
    133         if (buffer_size > 0) {
    134                 instance->transport_buffer = malloc32(buffer_size);
    135                 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
    136                     "Failed to allocate device accessible buffer.\n");
    137         }
    138 
    139         if (setup_size > 0) {
    140                 instance->setup_buffer = malloc32(setup_size);
    141                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    142                     "Failed to allocate device accessible setup buffer.\n");
    143                 memcpy(instance->setup_buffer, setup_buffer, setup_size);
    144         }
    145 
     133        void *setup =
     134            uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count)
     135            + sizeof(qh_t);
     136        void *data_buffer = setup + setup_size;
     137        usb_target_t target =
     138            { .address = ep->address, .endpoint = ep->endpoint };
     139        usb_transfer_batch_init(instance, ep, buffer, data_buffer, buffer_size,
     140            setup, setup_size, func_in, func_out, arg, fun,
     141            uhci_data, uhci_transfer_batch_dispose);
     142
     143        memcpy(instance->setup_buffer, setup_buffer, setup_size);
    146144        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    147145            instance, target.address, target.endpoint);
     
    155153 *
    156154 * Walk all TDs. Stop with false if there is an active one (it is to be
    157  * processed). Stop with true if an error is found. Return true if the last TS
     155 * processed). Stop with true if an error is found. Return true if the last TD
    158156 * is reached.
    159157 */
     
    161159{
    162160        assert(instance);
    163         uhci_batch_t *data = instance->private_data;
     161        uhci_transfer_batch_t *data = instance->private_data;
    164162        assert(data);
    165163
    166164        usb_log_debug2("Batch(%p) checking %d transfer(s) for completion.\n",
    167             instance, data->transfers);
     165            instance, data->td_count);
    168166        instance->transfered_size = 0;
    169167        size_t i = 0;
    170         for (;i < data->transfers; ++i) {
     168        for (;i < data->td_count; ++i) {
    171169                if (td_is_active(&data->tds[i])) {
    172170                        return false;
     
    178176                            instance, i, data->tds[i].status);
    179177                        td_print_status(&data->tds[i]);
    180                         if (instance->ep != NULL)
    181                                 endpoint_toggle_set(instance->ep,
    182                                     td_toggle(&data->tds[i]));
     178
     179                        assert(instance->ep != NULL);
     180                        endpoint_toggle_set(instance->ep,
     181                            td_toggle(&data->tds[i]));
    183182                        if (i > 0)
    184183                                goto substract_ret;
     
    195194}
    196195/*----------------------------------------------------------------------------*/
    197 /** Prepares control write transaction.
    198  *
    199  * @param[in] instance Batch structure to use.
    200  *
    201  * Uses genercir control function with pids OUT and IN.
     196/** Prepares control write transfer.
     197 *
     198 * @param[in] instance Batch structure to use.
     199 *
     200 * Uses generic control function with pids OUT and IN.
    202201 */
    203202void batch_control_write(usb_transfer_batch_t *instance)
     
    205204        assert(instance);
    206205        /* We are data out, we are supposed to provide data */
    207         memcpy(instance->transport_buffer, instance->buffer,
    208             instance->buffer_size);
     206        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    209207        batch_control(instance, USB_PID_OUT, USB_PID_IN);
    210         instance->next_step = batch_call_out_and_dispose;
     208        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    211209        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    212210}
    213211/*----------------------------------------------------------------------------*/
    214 /** Prepares control read transaction.
     212/** Prepares control read transfer.
    215213 *
    216214 * @param[in] instance Batch structure to use.
     
    222220        assert(instance);
    223221        batch_control(instance, USB_PID_IN, USB_PID_OUT);
    224         instance->next_step = batch_call_in_and_dispose;
     222        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    225223        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    226224}
    227225/*----------------------------------------------------------------------------*/
    228 /** Prepare interrupt in transaction.
    229  *
    230  * @param[in] instance Batch structure to use.
    231  *
    232  * Data transaction with PID_IN.
     226/** Prepare interrupt in transfer.
     227 *
     228 * @param[in] instance Batch structure to use.
     229 *
     230 * Data transfer with PID_IN.
    233231 */
    234232void batch_interrupt_in(usb_transfer_batch_t *instance)
    235233{
    236234        assert(instance);
    237         instance->direction = USB_DIRECTION_IN;
    238235        batch_data(instance, USB_PID_IN);
    239         instance->next_step = batch_call_in_and_dispose;
     236        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    240237        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    241238}
    242239/*----------------------------------------------------------------------------*/
    243 /** Prepare interrupt out transaction.
    244  *
    245  * @param[in] instance Batch structure to use.
    246  *
    247  * Data transaction with PID_OUT.
     240/** Prepare interrupt out transfer.
     241 *
     242 * @param[in] instance Batch structure to use.
     243 *
     244 * Data transfer with PID_OUT.
    248245 */
    249246void batch_interrupt_out(usb_transfer_batch_t *instance)
    250247{
    251248        assert(instance);
    252         instance->direction = USB_DIRECTION_OUT;
    253249        /* We are data out, we are supposed to provide data */
    254         memcpy(instance->transport_buffer, instance->buffer,
    255             instance->buffer_size);
     250        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    256251        batch_data(instance, USB_PID_OUT);
    257         instance->next_step = batch_call_out_and_dispose;
     252        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    258253        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    259254}
    260255/*----------------------------------------------------------------------------*/
    261 /** Prepare bulk in transaction.
    262  *
    263  * @param[in] instance Batch structure to use.
    264  *
    265  * Data transaction with PID_IN.
     256/** Prepare bulk in transfer.
     257 *
     258 * @param[in] instance Batch structure to use.
     259 *
     260 * Data transfer with PID_IN.
    266261 */
    267262void batch_bulk_in(usb_transfer_batch_t *instance)
     
    269264        assert(instance);
    270265        batch_data(instance, USB_PID_IN);
    271         instance->direction = USB_DIRECTION_IN;
    272         instance->next_step = batch_call_in_and_dispose;
     266        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    273267        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    274268}
    275269/*----------------------------------------------------------------------------*/
    276 /** Prepare bulk out transaction.
    277  *
    278  * @param[in] instance Batch structure to use.
    279  *
    280  * Data transaction with PID_OUT.
     270/** Prepare bulk out transfer.
     271 *
     272 * @param[in] instance Batch structure to use.
     273 *
     274 * Data transfer with PID_OUT.
    281275 */
    282276void batch_bulk_out(usb_transfer_batch_t *instance)
    283277{
    284278        assert(instance);
    285         instance->direction = USB_DIRECTION_OUT;
    286279        /* We are data out, we are supposed to provide data */
    287         memcpy(instance->transport_buffer, instance->buffer,
    288             instance->buffer_size);
     280        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    289281        batch_data(instance, USB_PID_OUT);
    290         instance->next_step = batch_call_out_and_dispose;
     282        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    291283        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
    292284}
    293285/*----------------------------------------------------------------------------*/
    294 /** Prepare generic data transaction
    295  *
    296  * @param[in] instance Batch structure to use.
    297  * @param[in] pid Pid to use for data transfers.
    298  *
    299  * Packets with alternating toggle bit and supplied pid value.
     286/** Prepare generic data transfer
     287 *
     288 * @param[in] instance Batch structure to use.
     289 * @param[in] pid Pid to use for data transactions.
     290 *
     291 * Transactions with alternating toggle bit and supplied pid value.
    300292 * The last transfer is marked with IOC flag.
    301293 */
     
    303295{
    304296        assert(instance);
    305         uhci_batch_t *data = instance->private_data;
     297        uhci_transfer_batch_t *data = instance->private_data;
    306298        assert(data);
    307299
    308         const bool low_speed = instance->speed == USB_SPEED_LOW;
     300        const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
    309301        int toggle = endpoint_toggle_get(instance->ep);
    310302        assert(toggle == 0 || toggle == 1);
    311303
    312         size_t transfer = 0;
     304        size_t td = 0;
    313305        size_t remain_size = instance->buffer_size;
     306        char *buffer = instance->data_buffer;
    314307        while (remain_size > 0) {
    315                 char *trans_data =
    316                     instance->transport_buffer + instance->buffer_size
    317                     - remain_size;
    318 
    319308                const size_t packet_size =
    320                     (instance->max_packet_size > remain_size) ?
    321                     remain_size : instance->max_packet_size;
    322 
    323                 td_t *next_transfer = (transfer + 1 < data->transfers)
    324                     ? &data->tds[transfer + 1] : NULL;
    325 
    326                 assert(transfer < data->transfers);
     309                    (instance->ep->max_packet_size > remain_size) ?
     310                    remain_size : instance->ep->max_packet_size;
     311
     312                td_t *next_td = (td + 1 < data->td_count)
     313                    ? &data->tds[td + 1] : NULL;
     314
     315
     316                usb_target_t target =
     317                    { instance->ep->address, instance->ep->endpoint };
     318
     319                assert(td < data->td_count);
     320                td_init(
     321                    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
     322                    toggle, false, low_speed, target, pid, buffer, next_td);
     323
     324                ++td;
     325                toggle = 1 - toggle;
     326                buffer += packet_size;
    327327                assert(packet_size <= remain_size);
    328 
    329                 td_init(
    330                     &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
    331                     toggle, false, low_speed, instance->target, pid, trans_data,
    332                     next_transfer);
    333 
    334 
    335                 toggle = 1 - toggle;
    336328                remain_size -= packet_size;
    337                 ++transfer;
    338329        }
    339         td_set_ioc(&data->tds[transfer - 1]);
     330        td_set_ioc(&data->tds[td - 1]);
    340331        endpoint_toggle_set(instance->ep, toggle);
    341332}
    342333/*----------------------------------------------------------------------------*/
    343 /** Prepare generic control transaction
    344  *
    345  * @param[in] instance Batch structure to use.
    346  * @param[in] data_stage Pid to use for data transfers.
    347  * @param[in] status_stage Pid to use for data transfers.
     334/** Prepare generic control transfer
     335 *
     336 * @param[in] instance Batch structure to use.
     337 * @param[in] data_stage Pid to use for data tds.
     338 * @param[in] status_stage Pid to use for data tds.
    348339 *
    349340 * Setup stage with toggle 0 and USB_PID_SETUP.
     
    356347{
    357348        assert(instance);
    358         uhci_batch_t *data = instance->private_data;
     349        uhci_transfer_batch_t *data = instance->private_data;
    359350        assert(data);
    360         assert(data->transfers >= 2);
    361 
    362         const bool low_speed = instance->speed == USB_SPEED_LOW;
    363         int toggle = 0;
     351        assert(data->td_count >= 2);
     352
     353        const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
     354        const usb_target_t target =
     355            { instance->ep->address, instance->ep->endpoint };
     356
    364357        /* setup stage */
    365358        td_init(
    366             data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, toggle, false,
    367             low_speed, instance->target, USB_PID_SETUP, instance->setup_buffer,
     359            data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, 0, false,
     360            low_speed, target, USB_PID_SETUP, instance->setup_buffer,
    368361            &data->tds[1]);
    369362
    370363        /* data stage */
    371         size_t transfer = 1;
     364        size_t td = 1;
     365        unsigned toggle = 1;
    372366        size_t remain_size = instance->buffer_size;
     367        char *buffer = instance->data_buffer;
    373368        while (remain_size > 0) {
    374                 char *control_data =
    375                     instance->transport_buffer + instance->buffer_size
    376                     - remain_size;
    377 
     369                const size_t packet_size =
     370                    (instance->ep->max_packet_size > remain_size) ?
     371                    remain_size : instance->ep->max_packet_size;
     372
     373                td_init(
     374                    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
     375                    toggle, false, low_speed, target, data_stage,
     376                    buffer, &data->tds[td + 1]);
     377
     378                ++td;
    378379                toggle = 1 - toggle;
    379 
    380                 const size_t packet_size =
    381                     (instance->max_packet_size > remain_size) ?
    382                     remain_size : instance->max_packet_size;
    383 
    384                 td_init(
    385                     &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
    386                     toggle, false, low_speed, instance->target, data_stage,
    387                     control_data, &data->tds[transfer + 1]);
    388 
    389                 ++transfer;
    390                 assert(transfer < data->transfers);
     380                buffer += packet_size;
     381                assert(td < data->td_count);
    391382                assert(packet_size <= remain_size);
    392383                remain_size -= packet_size;
     
    394385
    395386        /* status stage */
    396         assert(transfer == data->transfers - 1);
     387        assert(td == data->td_count - 1);
    397388
    398389        td_init(
    399             &data->tds[transfer], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
    400             instance->target, status_stage, NULL, NULL);
    401         td_set_ioc(&data->tds[transfer]);
     390            &data->tds[td], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
     391            target, status_stage, NULL, NULL);
     392        td_set_ioc(&data->tds[td]);
    402393
    403394        usb_log_debug2("Control last TD status: %x.\n",
    404             data->tds[transfer].status);
    405 }
    406 /*----------------------------------------------------------------------------*/
     395            data->tds[td].status);
     396}
     397/*----------------------------------------------------------------------------*/
     398/** Provides access to QH data structure.
     399 * @param[in] instance Batch pointer to use.
     400 * @return Pointer to the QH used by the batch.
     401 */
    407402qh_t * batch_qh(usb_transfer_batch_t *instance)
    408403{
    409404        assert(instance);
    410         uhci_batch_t *data = instance->private_data;
     405        uhci_transfer_batch_t *data = instance->private_data;
    411406        assert(data);
    412407        return data->qh;
    413408}
    414 /*----------------------------------------------------------------------------*/
    415 /** Helper function calls callback and correctly disposes of batch structure.
    416  *
    417  * @param[in] instance Batch structure to use.
    418  */
    419 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    420 {
    421         assert(instance);
    422         usb_transfer_batch_call_in(instance);
    423         batch_dispose(instance);
    424 }
    425 /*----------------------------------------------------------------------------*/
    426 /** Helper function calls callback and correctly disposes of batch structure.
    427  *
    428  * @param[in] instance Batch structure to use.
    429  */
    430 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    431 {
    432         assert(instance);
    433         usb_transfer_batch_call_out(instance);
    434         batch_dispose(instance);
    435 }
    436 /*----------------------------------------------------------------------------*/
    437 /** Correctly dispose all used data structures.
    438  *
    439  * @param[in] instance Batch structure to use.
    440  */
    441 void batch_dispose(usb_transfer_batch_t *instance)
    442 {
    443         assert(instance);
    444         uhci_batch_t *data = instance->private_data;
    445         assert(data);
    446         usb_log_debug("Batch(%p) disposing.\n", instance);
    447         /* free32 is NULL safe */
    448         free32(data->tds);
    449         free32(data->qh);
    450         free32(instance->setup_buffer);
    451         free32(instance->transport_buffer);
    452         free(data);
    453         free(instance);
    454 }
    455409/**
    456410 * @}
  • uspace/drv/uhci-hcd/batch.h

    ref354b6 re50cd7f  
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transaction structure
     32 * @brief UHCI driver USB tranfer helper functions
    3333 */
    3434#ifndef DRV_UHCI_BATCH_H
     
    4444
    4545usb_transfer_batch_t * batch_get(
    46     ddf_fun_t *fun,
    47                 usb_target_t target,
    48     usb_transfer_type_t transfer_type,
    49                 size_t max_packet_size,
    50     usb_speed_t speed,
    51                 char *buffer,
    52                 size_t size,
    53                 char *setup_buffer,
    54                 size_t setup_size,
     46    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
     47    char *setup_buffer, size_t setup_size,
    5548    usbhc_iface_transfer_in_callback_t func_in,
    5649    usbhc_iface_transfer_out_callback_t func_out,
    57                 void *arg,
    58                 endpoint_t *ep
    59                 );
     50    void *arg);
    6051
    6152void batch_dispose(usb_transfer_batch_t *instance);
  • uspace/drv/uhci-hcd/hc.c

    ref354b6 re50cd7f  
    6666static int hc_interrupt_emulator(void *arg);
    6767static int hc_debug_checker(void *arg);
    68 #if 0
    69 static bool usb_is_allowed(
    70     bool low_speed, usb_transfer_type_t transfer, size_t size);
    71 #endif
    7268/*----------------------------------------------------------------------------*/
    7369/** Initialize UHCI hcd driver structure
     
    8985        int ret;
    9086
    91 #define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
     87#define CHECK_RET_RETURN(ret, message...) \
    9288        if (ret != EOK) { \
    9389                usb_log_error(message); \
    94                 if (instance->ddf_instance) \
    95                         ddf_fun_destroy(instance->ddf_instance); \
    9690                return ret; \
    9791        } else (void) 0
     
    9993        instance->hw_interrupts = interrupts;
    10094        instance->hw_failures = 0;
    101 
    102         /* Setup UHCI function. */
    103         instance->ddf_instance = fun;
    10495
    10596        /* allow access to hc control registers */
    10697        regs_t *io;
    10798        ret = pio_enable(regs, reg_size, (void**)&io);
    108         CHECK_RET_DEST_FUN_RETURN(ret,
     99        CHECK_RET_RETURN(ret,
    109100            "Failed(%d) to gain access to registers at %p: %s.\n",
    110             ret, str_error(ret), io);
     101            ret, io, str_error(ret));
    111102        instance->registers = io;
    112103        usb_log_debug("Device registers at %p(%u) accessible.\n",
     
    114105
    115106        ret = hc_init_mem_structures(instance);
    116         CHECK_RET_DEST_FUN_RETURN(ret,
    117             "Failed to initialize UHCI memory structures.\n");
     107        CHECK_RET_RETURN(ret,
     108            "Failed(%d) to initialize UHCI memory structures: %s.\n",
     109            ret, str_error(ret));
    118110
    119111        hc_init_hw(instance);
    120112        if (!interrupts) {
    121                 instance->cleaner =
     113                instance->interrupt_emulator =
    122114                    fibril_create(hc_interrupt_emulator, instance);
    123                 fibril_add_ready(instance->cleaner);
    124         } else {
    125                 /* TODO: enable interrupts here */
    126         }
    127 
    128         instance->debug_checker =
    129             fibril_create(hc_debug_checker, instance);
    130 //      fibril_add_ready(instance->debug_checker);
     115                fibril_add_ready(instance->interrupt_emulator);
     116        }
     117        (void)hc_debug_checker;
    131118
    132119        return EOK;
     
    228215        /* Set all frames to point to the first queue head */
    229216        const uint32_t queue =
    230           instance->transfers_interrupt.queue_head_pa
    231           | LINK_POINTER_QUEUE_HEAD_FLAG;
     217            LINK_POINTER_QH(addr_to_phys(
     218                instance->transfers_interrupt.queue_head));
    232219
    233220        unsigned i = 0;
     
    236223        }
    237224
    238         /* Init device keeper*/
     225        /* Init device keeper */
    239226        usb_device_keeper_init(&instance->manager);
    240227        usb_log_debug("Initialized device manager.\n");
    241228
    242         ret =
    243             usb_endpoint_manager_init(&instance->ep_manager,
    244                 BANDWIDTH_AVAILABLE_USB11);
     229        ret = usb_endpoint_manager_init(&instance->ep_manager,
     230            BANDWIDTH_AVAILABLE_USB11);
    245231        assert(ret == EOK);
    246232
     
    261247{
    262248        assert(instance);
    263 #define CHECK_RET_CLEAR_RETURN(ret, message...) \
     249#define SETUP_TRANSFER_LIST(type, name) \
     250do { \
     251        int ret = transfer_list_init(&instance->transfers_##type, name); \
    264252        if (ret != EOK) { \
    265                 usb_log_error(message); \
     253                usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \
     254                    ret, name, str_error(ret)); \
    266255                transfer_list_fini(&instance->transfers_bulk_full); \
    267256                transfer_list_fini(&instance->transfers_control_full); \
     
    269258                transfer_list_fini(&instance->transfers_interrupt); \
    270259                return ret; \
    271         } else (void) 0
    272 
    273         /* initialize TODO: check errors */
    274         int ret;
    275         ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
    276         CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
    277 
    278         ret = transfer_list_init(
    279             &instance->transfers_control_full, "CONTROL_FULL");
    280         CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
    281 
    282         ret = transfer_list_init(
    283             &instance->transfers_control_slow, "CONTROL_SLOW");
    284         CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
    285 
    286         ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
    287         CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
    288 
     260        } \
     261} while (0)
     262
     263        SETUP_TRANSFER_LIST(bulk_full, "BULK FULL");
     264        SETUP_TRANSFER_LIST(control_full, "CONTROL FULL");
     265        SETUP_TRANSFER_LIST(control_slow, "CONTROL LOW");
     266        SETUP_TRANSFER_LIST(interrupt, "INTERRUPT");
     267#undef SETUP_TRANSFER_LIST
     268        /* Connect lists into one schedule */
    289269        transfer_list_set_next(&instance->transfers_control_full,
    290270                &instance->transfers_bulk_full);
     
    330310
    331311        transfer_list_t *list =
    332             instance->transfers[batch->speed][batch->transfer_type];
     312            instance->transfers[batch->ep->speed][batch->ep->transfer_type];
    333313        assert(list);
    334         if (batch->transfer_type == USB_TRANSFER_CONTROL) {
    335                 usb_device_keeper_use_control(
    336                     &instance->manager, batch->target);
    337         }
    338314        transfer_list_add_batch(list, batch);
    339315
     
    355331        assert(instance);
    356332//      status |= 1; //Uncomment to work around qemu hang
    357         /* TODO: Resume interrupts are not supported */
    358333        /* Lower 2 bits are transaction error and transaction complete */
    359         if (status & 0x3) {
     334        if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
    360335                LIST_INITIALIZE(done);
    361336                transfer_list_remove_finished(
     
    373348                        usb_transfer_batch_t *batch =
    374349                            list_get_instance(item, usb_transfer_batch_t, link);
    375                         switch (batch->transfer_type)
    376                         {
    377                         case USB_TRANSFER_CONTROL:
    378                                 usb_device_keeper_release_control(
    379                                     &instance->manager, batch->target);
    380                                 break;
    381                         case USB_TRANSFER_INTERRUPT:
    382                         case USB_TRANSFER_ISOCHRONOUS: {
    383 /*
    384                                 int ret = bandwidth_free(&instance->bandwidth,
    385                                     batch->target.address,
    386                                     batch->target.endpoint,
    387                                     batch->direction);
    388                                 if (ret != EOK)
    389                                         usb_log_warning("Failed(%d) to free "
    390                                             "reserved bw: %s.\n", ret,
    391                                             str_error(ret));
    392 */
    393                                 }
    394                         default:
    395                                 break;
    396                         }
    397                         batch->next_step(batch);
    398                 }
    399         }
    400         /* bits 4 and 5 indicate hc error */
    401         if (status & 0x18) {
     350                        usb_transfer_batch_finish(batch);
     351                }
     352        }
     353        /* Resume interrupts are not supported */
     354
     355        /* Bits 4 and 5 indicate hc error */
     356        if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
    402357                usb_log_error("UHCI hardware failure!.\n");
    403358                ++instance->hw_failures;
     
    429384
    430385        while (1) {
    431                 /* read and ack interrupts */
     386                /* Readd and clear status register */
    432387                uint16_t status = pio_read_16(&instance->registers->usbsts);
    433                 pio_write_16(&instance->registers->usbsts, 0x1f);
     388                pio_write_16(&instance->registers->usbsts, status);
    434389                if (status != 0)
    435390                        usb_log_debug2("UHCI status: %x.\n", status);
    436391                hc_interrupt(instance, status);
    437                 async_usleep(UHCI_CLEANER_TIMEOUT);
     392                async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
    438393        }
    439394        return EOK;
     
    506461#undef QH
    507462}
    508 /*----------------------------------------------------------------------------*/
    509 /** Check transfers for USB validity
    510  *
    511  * @param[in] low_speed Transfer speed.
    512  * @param[in] transfer Transer type
    513  * @param[in] size Size of data packets
    514  * @return True if transaction is allowed by USB specs, false otherwise
    515  */
    516 #if 0
    517 bool usb_is_allowed(
    518     bool low_speed, usb_transfer_type_t transfer, size_t size)
    519 {
    520         /* see USB specification chapter 5.5-5.8 for magic numbers used here */
    521         switch(transfer)
    522         {
    523         case USB_TRANSFER_ISOCHRONOUS:
    524                 return (!low_speed && size < 1024);
    525         case USB_TRANSFER_INTERRUPT:
    526                 return size <= (low_speed ? 8 : 64);
    527         case USB_TRANSFER_CONTROL: /* device specifies its own max size */
    528                 return (size <= (low_speed ? 8 : 64));
    529         case USB_TRANSFER_BULK: /* device specifies its own max size */
    530                 return (!low_speed && size <= 64);
    531         }
    532         return false;
    533 }
    534 #endif
    535463/**
    536464 * @}
  • uspace/drv/uhci-hcd/hc.h

    ref354b6 re50cd7f  
    4848#include "transfer_list.h"
    4949
     50/** UHCI I/O registers layout */
    5051typedef struct uhci_regs {
     52        /** Command register, controls HC behaviour */
    5153        uint16_t usbcmd;
    5254#define UHCI_CMD_MAX_PACKET (1 << 7)
     
    5961#define UHCI_CMD_RUN_STOP  (1 << 0)
    6062
     63        /** Status register, 1 means interrupt is asserted (if enabled) */
    6164        uint16_t usbsts;
    6265#define UHCI_STATUS_HALTED (1 << 5)
     
    6770#define UHCI_STATUS_INTERRUPT (1 << 0)
    6871
     72        /** Interrupt enabled registers */
    6973        uint16_t usbintr;
    7074#define UHCI_INTR_SHORT_PACKET (1 << 3)
     
    7377#define UHCI_INTR_CRC (1 << 0)
    7478
     79        /** Register stores frame number used in SOF packet */
    7580        uint16_t frnum;
     81
     82        /** Pointer(physical) to the Frame List */
    7683        uint32_t flbaseadd;
     84
     85        /** SOF modification to match external timers */
    7786        uint8_t sofmod;
    7887} regs_t;
    7988
    8089#define UHCI_FRAME_LIST_COUNT 1024
    81 #define UHCI_CLEANER_TIMEOUT 10000
     90#define UHCI_INT_EMULATOR_TIMEOUT 10000
    8291#define UHCI_DEBUGER_TIMEOUT 5000000
    8392#define UHCI_ALLOWED_HW_FAIL 5
    8493
     94/* Main HC driver structure */
    8595typedef struct hc {
     96        /** USB bus driver, devices and addresses */
    8697        usb_device_keeper_t manager;
     98        /** USB bus driver, endpoints */
    8799        usb_endpoint_manager_t ep_manager;
    88100
     101        /** Addresses of I/O registers */
    89102        regs_t *registers;
    90103
     104        /** Frame List contains 1024 link pointers */
    91105        link_pointer_t *frame_list;
    92106
     107        /** List and queue of interrupt transfers */
     108        transfer_list_t transfers_interrupt;
     109        /** List and queue of low speed control transfers */
     110        transfer_list_t transfers_control_slow;
     111        /** List and queue of full speed bulk transfers */
    93112        transfer_list_t transfers_bulk_full;
     113        /** List and queue of full speed control transfers */
    94114        transfer_list_t transfers_control_full;
    95         transfer_list_t transfers_control_slow;
    96         transfer_list_t transfers_interrupt;
    97115
     116        /** Pointer table to the above lists, helps during scheduling */
    98117        transfer_list_t *transfers[2][4];
    99118
     119        /** Code to be executed in kernel interrupt handler */
    100120        irq_code_t interrupt_code;
    101121
    102         fid_t cleaner;
    103         fid_t debug_checker;
     122        /** Fibril periodically checking status register*/
     123        fid_t interrupt_emulator;
     124
     125        /** Indicator of hw interrupts availability */
    104126        bool hw_interrupts;
     127
     128        /** Number of hw failures detected. */
    105129        unsigned hw_failures;
    106 
    107         ddf_fun_t *ddf_instance;
    108130} hc_t;
    109131
  • uspace/drv/uhci-hcd/hw_struct/queue_head.h

    ref354b6 re50cd7f  
    3434#ifndef DRV_UHCI_QH_H
    3535#define DRV_UHCI_QH_H
    36 
    37 /* libc */
    3836#include <assert.h>
    3937
    4038#include "link_pointer.h"
     39#include "transfer_descriptor.h"
     40#include "utils/malloc32.h"
    4141
     42/** This structure is defined in UHCI design guide p. 31 */
    4243typedef struct queue_head {
     44        /** Pointer to the next entity (another QH or TD */
    4345        volatile link_pointer_t next;
     46        /** Pointer to the contained entities (execution controlled by vertical flag*/
    4447        volatile link_pointer_t element;
    4548} __attribute__((packed)) qh_t;
     
    6467 * @param[in] pa Physical address of the next queue head.
    6568 *
    66  * Adds proper flag. If the pointer is NULL or terminal, sets next to terminal
    67  * NULL.
     69 * Adds proper flag. If the pointer is NULL, sets next to terminal NULL.
    6870 */
    69 static inline void qh_set_next_qh(qh_t *instance, uint32_t pa)
     71static inline void qh_set_next_qh(qh_t *instance, qh_t *next)
    7072{
    71         /* Address is valid and not terminal */
    72         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     73        uint32_t pa = addr_to_phys(next);
     74        if (pa) {
    7375                instance->next = LINK_POINTER_QH(pa);
    7476        } else {
     
    8082 *
    8183 * @param[in] instance qh_t structure to initialize.
    82  * @param[in] pa Physical address of the next queue head.
    83  *
    84  * Adds proper flag. If the pointer is NULL or terminal, sets element
    85  * to terminal NULL.
    86  */
    87 static inline void qh_set_element_qh(qh_t *instance, uint32_t pa)
    88 {
    89         /* Address is valid and not terminal */
    90         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
    91                 instance->element = LINK_POINTER_QH(pa);
    92         } else {
    93                 instance->element = LINK_POINTER_TERM;
    94         }
    95 }
    96 /*----------------------------------------------------------------------------*/
    97 /** Set queue head element pointer
    98  *
    99  * @param[in] instance qh_t structure to initialize.
    10084 * @param[in] pa Physical address of the TD structure.
    10185 *
    102  * Adds proper flag. If the pointer is NULL or terminal, sets element
    103  * to terminal NULL.
     86 * Adds proper flag. If the pointer is NULL, sets element to terminal NULL.
    10487 */
    105 static inline void qh_set_element_td(qh_t *instance, uint32_t pa)
     88static inline void qh_set_element_td(qh_t *instance, td_t *td)
    10689{
    107         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     90        uint32_t pa = addr_to_phys(td);
     91        if (pa) {
    10892                instance->element = LINK_POINTER_TD(pa);
    10993        } else {
     
    11195        }
    11296}
    113 
    11497#endif
    11598/**
  • uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c

    ref354b6 re50cd7f  
    7777
    7878        instance->status = 0
    79             | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
     79            | ((err_count & TD_STATUS_ERROR_COUNT_MASK)
     80                << TD_STATUS_ERROR_COUNT_POS)
    8081            | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
    8182            | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
     
    8990            | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
    9091            | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
    91             | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
    92             | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
     92            | ((target.address & TD_DEVICE_ADDRESS_MASK)
     93                << TD_DEVICE_ADDRESS_POS)
     94            | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK)
     95                << TD_DEVICE_ENDPOINT_POS)
    9396            | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
    9497
     
    114117        assert(instance);
    115118
    116         /* this is hc internal error it should never be reported */
     119        /* This is hc internal error it should never be reported. */
    117120        if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
    118121                return EAGAIN;
     
    123126                return EBADCHECKSUM;
    124127
    125         /* hc does not end transaction on these, it should never be reported */
     128        /* HC does not end transactions on these, it should never be reported */
    126129        if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
    127130                return EAGAIN;
    128131
    129         /* buffer overrun or underrun */
     132        /* Buffer overrun or underrun */
    130133        if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
    131134                return ERANGE;
    132135
    133         /* device babble is something serious */
     136        /* Device babble is something serious */
    134137        if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0)
    135138                return EIO;
    136139
    137         /* stall might represent err count reaching zero or stall response from
    138          * the device, is err count reached zero, one of the above is reported*/
     140        /* Stall might represent err count reaching zero or stall response from
     141         * the device. If err count reached zero, one of the above is reported*/
    139142        if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
    140143                return ESTALL;
  • uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.h

    ref354b6 re50cd7f  
    4040#include "link_pointer.h"
    4141
    42 /** UHCI Transfer Descriptor */
     42/** Transfer Descriptor, defined in UHCI design guide p. 26 */
    4343typedef struct transfer_descriptor {
     44        /** Pointer to the next entity (TD or QH) */
    4445        link_pointer_t next;
    4546
     47        /** Status doubleword */
    4648        volatile uint32_t status;
    4749#define TD_STATUS_RESERVED_MASK 0xc000f800
    48 #define TD_STATUS_SPD_FLAG ( 1 << 29 )
    49 #define TD_STATUS_ERROR_COUNT_POS ( 27 )
    50 #define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )
    51 #define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 )
    52 #define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 )
    53 #define TD_STATUS_IOC_FLAG ( 1 << 24 )
     50#define TD_STATUS_SPD_FLAG         (1 << 29)
     51#define TD_STATUS_ERROR_COUNT_POS 27
     52#define TD_STATUS_ERROR_COUNT_MASK 0x3
     53#define TD_STATUS_LOW_SPEED_FLAG   (1 << 26)
     54#define TD_STATUS_ISOCHRONOUS_FLAG (1 << 25)
     55#define TD_STATUS_IOC_FLAG         (1 << 24)
    5456
    55 #define TD_STATUS_ERROR_ACTIVE ( 1 << 23 )
    56 #define TD_STATUS_ERROR_STALLED ( 1 << 22 )
    57 #define TD_STATUS_ERROR_BUFFER ( 1 << 21 )
    58 #define TD_STATUS_ERROR_BABBLE ( 1 << 20 )
    59 #define TD_STATUS_ERROR_NAK ( 1 << 19 )
    60 #define TD_STATUS_ERROR_CRC ( 1 << 18 )
    61 #define TD_STATUS_ERROR_BIT_STUFF ( 1 << 17 )
    62 #define TD_STATUS_ERROR_RESERVED ( 1 << 16 )
     57#define TD_STATUS_ERROR_ACTIVE    (1 << 23)
     58#define TD_STATUS_ERROR_STALLED   (1 << 22)
     59#define TD_STATUS_ERROR_BUFFER    (1 << 21)
     60#define TD_STATUS_ERROR_BABBLE    (1 << 20)
     61#define TD_STATUS_ERROR_NAK       (1 << 19)
     62#define TD_STATUS_ERROR_CRC       (1 << 18)
     63#define TD_STATUS_ERROR_BIT_STUFF (1 << 17)
     64#define TD_STATUS_ERROR_RESERVED  (1 << 16)
    6365#define TD_STATUS_ERROR_POS 16
    64 #define TD_STATUS_ERROR_MASK ( 0xff )
     66#define TD_STATUS_ERROR_MASK 0xff
    6567
    6668#define TD_STATUS_ACTLEN_POS 0
    6769#define TD_STATUS_ACTLEN_MASK 0x7ff
    6870
     71        /* double word with USB device specific info */
    6972        volatile uint32_t device;
    7073#define TD_DEVICE_MAXLEN_POS 21
    71 #define TD_DEVICE_MAXLEN_MASK ( 0x7ff )
    72 #define TD_DEVICE_RESERVED_FLAG ( 1 << 20 )
    73 #define TD_DEVICE_DATA_TOGGLE_ONE_FLAG ( 1 << 19 )
     74#define TD_DEVICE_MAXLEN_MASK 0x7ff
     75#define TD_DEVICE_RESERVED_FLAG        (1 << 20)
     76#define TD_DEVICE_DATA_TOGGLE_ONE_FLAG (1 << 19)
    7477#define TD_DEVICE_ENDPOINT_POS 15
    75 #define TD_DEVICE_ENDPOINT_MASK ( 0xf )
     78#define TD_DEVICE_ENDPOINT_MASK 0xf
    7679#define TD_DEVICE_ADDRESS_POS 8
    77 #define TD_DEVICE_ADDRESS_MASK ( 0x7f )
     80#define TD_DEVICE_ADDRESS_MASK 0x7f
    7881#define TD_DEVICE_PID_POS 0
    79 #define TD_DEVICE_PID_MASK ( 0xff )
     82#define TD_DEVICE_PID_MASK 0xff
    8083
     84        /** Pointer(physical) to the beginning of the transaction's buffer */
    8185        volatile uint32_t buffer_ptr;
    8286
    83         /* there is 16 bytes of data available here, according to UHCI
    84          * Design guide, according to linux kernel the hardware does not care,
    85          * it just needs to be aligned, we don't use it anyway
     87        /* According to UHCI design guide, there is 16 bytes of
     88         * data available here.
     89         * According to linux kernel the hardware does not care,
     90         * it just needs to be aligned. We don't use it anyway.
    8691         */
    8792} __attribute__((packed)) td_t;
  • uspace/drv/uhci-hcd/iface.c

    ref354b6 re50cd7f  
    4141#include "hc.h"
    4242
    43 /** Reserve default address interface function
    44  *
    45  * @param[in] fun DDF function that was called.
    46  * @param[in] speed Speed to associate with the new default address.
    47  * @return Error code.
    48  */
    49 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    50 {
     43static inline int setup_batch(
     44    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
     45    void *data, size_t size, void * setup_data, size_t setup_size,
     46    usbhc_iface_transfer_in_callback_t in,
     47    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
     48    hc_t **hc, usb_transfer_batch_t **batch)
     49{
     50        assert(hc);
     51        assert(batch);
    5152        assert(fun);
    52         hc_t *hc = fun_to_hc(fun);
    53         assert(hc);
    54         usb_log_debug("Default address request with speed %d.\n", speed);
    55         usb_device_keeper_reserve_default_address(&hc->manager, speed);
    56         return EOK;
    57 #if 0
    58         endpoint_t *ep = malloc(sizeof(endpoint_t));
    59         if (ep == NULL)
     53        *hc = fun_to_hc(fun);
     54        assert(*hc);
     55
     56        size_t res_bw;
     57        endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
     58            target.address, target.endpoint, direction, &res_bw);
     59        if (ep == NULL) {
     60                usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
     61                    target.address, target.endpoint, name);
     62                return ENOENT;
     63        }
     64
     65        usb_log_debug("%s %d:%d %zu(%zu).\n",
     66            name, target.address, target.endpoint, size, ep->max_packet_size);
     67
     68        const size_t bw = bandwidth_count_usb11(
     69            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     70        if (res_bw < bw) {
     71                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
     72                    "but only %zu is reserved.\n",
     73                    target.address, target.endpoint, name, bw, res_bw);
     74                return ENOSPC;
     75        }
     76
     77        *batch = batch_get(
     78                fun, ep, data, size, setup_data, setup_size, in, out, arg);
     79        if (!*batch)
    6080                return ENOMEM;
    61         const size_t max_packet_size = speed == USB_SPEED_LOW ? 8 : 64;
    62         endpoint_init(ep, USB_TRANSFER_CONTROL, speed, max_packet_size);
    63         int ret;
    64 try_retgister:
    65         ret = usb_endpoint_manager_register_ep(&hc->ep_manager,
    66             USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH, ep, endpoint_destroy, 0);
    67         if (ret == EEXISTS) {
    68                 async_usleep(1000);
    69                 goto try_retgister;
    70         }
    71         if (ret != EOK) {
    72                 endpoint_destroy(ep);
    73         }
    74         return ret;
    75 #endif
    76 }
    77 /*----------------------------------------------------------------------------*/
    78 /** Release default address interface function
    79  *
    80  * @param[in] fun DDF function that was called.
    81  * @return Error code.
    82  */
    83 static int release_default_address(ddf_fun_t *fun)
    84 {
    85         assert(fun);
    86         hc_t *hc = fun_to_hc(fun);
    87         assert(hc);
    88         usb_log_debug("Default address release.\n");
    89 //      return usb_endpoint_manager_unregister_ep(&hc->ep_manager,
    90 //          USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH);
    91         usb_device_keeper_release_default_address(&hc->manager);
    9281        return EOK;
    9382}
     
    151140/*----------------------------------------------------------------------------*/
    152141static int register_endpoint(
    153     ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
     142    ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
     143    usb_endpoint_t endpoint,
    154144    usb_transfer_type_t transfer_type, usb_direction_t direction,
    155145    size_t max_packet_size, unsigned int interval)
     
    157147        hc_t *hc = fun_to_hc(fun);
    158148        assert(hc);
    159         const usb_speed_t speed =
    160             usb_device_keeper_get_speed(&hc->manager, address);
    161         const size_t size =
    162             (transfer_type == USB_TRANSFER_INTERRUPT
    163             || transfer_type == USB_TRANSFER_ISOCHRONOUS) ?
    164             max_packet_size : 0;
    165         int ret;
    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 
     149        const size_t size = max_packet_size;
     150        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
     151        if (speed >= USB_SPEED_MAX) {
     152                speed = ep_speed;
     153        }
    177154        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    178155            address, endpoint, usb_str_transfer_type(transfer_type),
    179156            usb_str_speed(speed), direction, size, max_packet_size, interval);
    180157
    181         ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    182         if (ret != EOK) {
    183                 endpoint_destroy(ep);
    184         } else {
    185                 usb_device_keeper_add_ep(&hc->manager, address, ep);
    186         }
    187         return ret;
     158        return usb_endpoint_manager_add_ep(&hc->ep_manager, address, endpoint,
     159            direction, transfer_type, speed, max_packet_size, size);
    188160}
    189161/*----------------------------------------------------------------------------*/
     
    204176 * @param[in] fun DDF function that was called.
    205177 * @param[in] target USB device to write to.
    206  * @param[in] max_packet_size maximum size of data packet the device accepts
    207178 * @param[in] data Source of data.
    208179 * @param[in] size Size of data source.
     
    212183 */
    213184static int interrupt_out(
    214     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     185    ddf_fun_t *fun, usb_target_t target, void *data,
    215186    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    216187{
    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;
     188        usb_transfer_batch_t *batch = NULL;
     189        hc_t *hc = NULL;
     190        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     191            NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
     192        if (ret != EOK)
     193                return ret;
    251194        batch_interrupt_out(batch);
    252         const int ret = hc_schedule(hc, batch);
    253         if (ret != EOK) {
    254                 batch_dispose(batch);
     195        ret = hc_schedule(hc, batch);
     196        if (ret != EOK) {
     197                usb_transfer_batch_dispose(batch);
    255198        }
    256199        return ret;
     
    261204 * @param[in] fun DDF function that was called.
    262205 * @param[in] target USB device to write to.
    263  * @param[in] max_packet_size maximum size of data packet the device accepts
    264206 * @param[out] data Data destination.
    265207 * @param[in] size Size of data source.
     
    269211 */
    270212static int interrupt_in(
    271     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     213    ddf_fun_t *fun, usb_target_t target, void *data,
    272214    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    273215{
    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;
     216        usb_transfer_batch_t *batch = NULL;
     217        hc_t *hc = NULL;
     218        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     219            NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
     220        if (ret != EOK)
     221                return ret;
    309222        batch_interrupt_in(batch);
    310         const int ret = hc_schedule(hc, batch);
    311         if (ret != EOK) {
    312                 batch_dispose(batch);
     223        ret = hc_schedule(hc, batch);
     224        if (ret != EOK) {
     225                usb_transfer_batch_dispose(batch);
    313226        }
    314227        return ret;
     
    319232 * @param[in] fun DDF function that was called.
    320233 * @param[in] target USB device to write to.
    321  * @param[in] max_packet_size maximum size of data packet the device accepts
    322234 * @param[in] data Source of data.
    323235 * @param[in] size Size of data source.
     
    327239 */
    328240static int bulk_out(
    329     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     241    ddf_fun_t *fun, usb_target_t target, void *data,
    330242    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    331243{
    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;
     244        usb_transfer_batch_t *batch = NULL;
     245        hc_t *hc = NULL;
     246        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     247            NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
     248        if (ret != EOK)
     249                return ret;
    356250        batch_bulk_out(batch);
    357         const int ret = hc_schedule(hc, batch);
    358         if (ret != EOK) {
    359                 batch_dispose(batch);
     251        ret = hc_schedule(hc, batch);
     252        if (ret != EOK) {
     253                usb_transfer_batch_dispose(batch);
    360254        }
    361255        return ret;
     
    366260 * @param[in] fun DDF function that was called.
    367261 * @param[in] target USB device to write to.
    368  * @param[in] max_packet_size maximum size of data packet the device accepts
    369262 * @param[out] data Data destination.
    370263 * @param[in] size Size of data source.
     
    374267 */
    375268static int bulk_in(
    376     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
     269    ddf_fun_t *fun, usb_target_t target, void *data,
    377270    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    378271{
    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;
     272        usb_transfer_batch_t *batch = NULL;
     273        hc_t *hc = NULL;
     274        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     275            NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
     276        if (ret != EOK)
     277                return ret;
    402278        batch_bulk_in(batch);
    403         const int ret = hc_schedule(hc, batch);
    404         if (ret != EOK) {
    405                 batch_dispose(batch);
     279        ret = hc_schedule(hc, batch);
     280        if (ret != EOK) {
     281                usb_transfer_batch_dispose(batch);
    406282        }
    407283        return ret;
     
    412288 * @param[in] fun DDF function that was called.
    413289 * @param[in] target USB device to write to.
    414  * @param[in] max_packet_size maximum size of data packet the device accepts.
    415290 * @param[in] setup_data Data to send with SETUP transfer.
    416291 * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
     
    422297 */
    423298static int control_write(
    424     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     299    ddf_fun_t *fun, usb_target_t target,
    425300    void *setup_data, size_t setup_size, void *data, size_t size,
    426301    usbhc_iface_transfer_out_callback_t callback, void *arg)
    427302{
    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);
     303        usb_transfer_batch_t *batch = NULL;
     304        hc_t *hc = NULL;
     305        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     306            setup_data, setup_size, NULL, callback, arg, "Control WRITE",
     307            &hc, &batch);
     308        if (ret != EOK)
     309                return ret;
     310        usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
    451311        batch_control_write(batch);
    452         const int ret = hc_schedule(hc, batch);
    453         if (ret != EOK) {
    454                 batch_dispose(batch);
     312        ret = hc_schedule(hc, batch);
     313        if (ret != EOK) {
     314                usb_transfer_batch_dispose(batch);
    455315        }
    456316        return ret;
     
    461321 * @param[in] fun DDF function that was called.
    462322 * @param[in] target USB device to write to.
    463  * @param[in] max_packet_size maximum size of data packet the device accepts.
    464323 * @param[in] setup_data Data to send with SETUP packet.
    465324 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
     
    471330 */
    472331static int control_read(
    473     ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
     332    ddf_fun_t *fun, usb_target_t target,
    474333    void *setup_data, size_t setup_size, void *data, size_t size,
    475334    usbhc_iface_transfer_in_callback_t callback, void *arg)
    476335{
    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;
     336        usb_transfer_batch_t *batch = NULL;
     337        hc_t *hc = NULL;
     338        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     339            setup_data, setup_size, callback, NULL, arg, "Control READ",
     340            &hc, &batch);
     341        if (ret != EOK)
     342                return ret;
    496343        batch_control_read(batch);
    497         const int ret = hc_schedule(hc, batch);
    498         if (ret != EOK) {
    499                 batch_dispose(batch);
     344        ret = hc_schedule(hc, batch);
     345        if (ret != EOK) {
     346                usb_transfer_batch_dispose(batch);
    500347        }
    501348        return ret;
     
    503350/*----------------------------------------------------------------------------*/
    504351usbhc_iface_t hc_iface = {
    505         .reserve_default_address = reserve_default_address,
    506         .release_default_address = release_default_address,
    507352        .request_address = request_address,
    508353        .bind_address = bind_address,
  • uspace/drv/uhci-hcd/main.c

    ref354b6 re50cd7f  
    3939#include <usb/debug.h>
    4040
    41 #include "iface.h"
    4241#include "uhci.h"
    4342
     
    6261int uhci_add_device(ddf_dev_t *device)
    6362{
    64         usb_log_debug("uhci_add_device() called\n");
     63        usb_log_debug2("uhci_add_device() called\n");
    6564        assert(device);
     65
    6666        uhci_t *uhci = malloc(sizeof(uhci_t));
    6767        if (uhci == NULL) {
     
    7272        int ret = uhci_init(uhci, device);
    7373        if (ret != EOK) {
    74                 usb_log_error("Failed to initialize UHCI driver: %s.\n",
    75                     str_error(ret));
     74                usb_log_error("Failed(%d) to initialize UHCI driver: %s.\n",
     75                    ret, str_error(ret));
    7676                return ret;
    7777        }
    7878        device->driver_data = uhci;
    7979
    80         usb_log_info("Controlling new UHCI device `%s'.\n", device->name);
     80        usb_log_info("Controlling new UHCI device '%s'.\n", device->name);
    8181
    8282        return EOK;
     
    8585/** Initialize global driver structures (NONE).
    8686 *
    87  * @param[in] argc Nmber of arguments in argv vector (ignored).
     87 * @param[in] argc Number of arguments in argv vector (ignored).
    8888 * @param[in] argv Cmdline argument vector (ignored).
    8989 * @return Error code.
     
    9494{
    9595        printf(NAME ": HelenOS UHCI driver.\n");
    96 
    97         sleep(3); /* TODO: remove in final version */
    9896        usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
    9997
  • uspace/drv/uhci-hcd/pci.c

    ref354b6 re50cd7f  
    4444#include "pci.h"
    4545
    46 /** Get address of registers and IRQ for given device.
     46/** Get I/O address of registers and IRQ for given device.
    4747 *
    4848 * @param[in] dev Device asking for the addresses.
     
    5353 */
    5454int pci_get_my_registers(ddf_dev_t *dev,
    55     uintptr_t *io_reg_address, size_t *io_reg_size,
    56     int *irq_no)
     55    uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no)
    5756{
    5857        assert(dev != NULL);
    5958
    60         int parent_phone = devman_parent_device_connect(dev->handle,
    61             IPC_FLAG_BLOCKING);
     59        int parent_phone =
     60            devman_parent_device_connect(dev->handle, IPC_FLAG_BLOCKING);
    6261        if (parent_phone < 0) {
    6362                return parent_phone;
    6463        }
    6564
    66         int rc;
    6765        hw_resource_list_t hw_resources;
    68         rc = hw_res_get_resource_list(parent_phone, &hw_resources);
     66        int rc = hw_res_get_resource_list(parent_phone, &hw_resources);
    6967        if (rc != EOK) {
    7068                goto leave;
     
    9593                            res->res.io_range.address, res->res.io_range.size);
    9694                        io_found = true;
     95                        break;
    9796
    9897                default:
     
    113112leave:
    114113        async_hangup(parent_phone);
    115 
    116114        return rc;
    117115}
     
    145143        }
    146144
    147         /* See UHCI design guide for these values,
     145        /* See UHCI design guide for these values p.45,
    148146         * write all WC bits in USB legacy register */
    149147        sysarg_t address = 0xc0;
  • uspace/drv/uhci-hcd/root_hub.c

    ref354b6 re50cd7f  
    5555        int ret = asprintf(&match_str, "usb&uhci&root-hub");
    5656        if (ret < 0) {
    57                 usb_log_error("Failed to create root hub match string.\n");
    58                 return ENOMEM;
     57                usb_log_error(
     58                    "Failed(%d) to create root hub match string: %s.\n",
     59                    ret, str_error(ret));
     60                return ret;
    5961        }
    6062
    6163        ret = ddf_fun_add_match_id(fun, match_str, 100);
    6264        if (ret != EOK) {
     65                free(match_str);
    6366                usb_log_error("Failed(%d) to add root hub match id: %s\n",
    6467                    ret, str_error(ret));
     
    6669        }
    6770
    68         hw_resource_list_t *resource_list = &instance->resource_list;
    69         resource_list->count = 1;
    70         resource_list->resources = &instance->io_regs;
    71         assert(resource_list->resources);
     71        /* Initialize resource structure */
     72        instance->resource_list.count = 1;
     73        instance->resource_list.resources = &instance->io_regs;
     74
    7275        instance->io_regs.type = IO_RANGE;
    7376        instance->io_regs.res.io_range.address = reg_addr;
  • uspace/drv/uhci-hcd/root_hub.h

    ref354b6 re50cd7f  
    3939#include <ops/hw_res.h>
    4040
     41/** DDF support structure for uhci-rhd driver, provides I/O resources */
    4142typedef struct rh {
     43        /** List of resources available to the root hub. */
    4244        hw_resource_list_t resource_list;
     45        /** The only resource in the above list */
    4346        hw_resource_t io_regs;
    4447} rh_t;
  • uspace/drv/uhci-hcd/transfer_list.c

    ref354b6 re50cd7f  
    5757                return ENOMEM;
    5858        }
    59         instance->queue_head_pa = addr_to_phys(instance->queue_head);
     59        uint32_t queue_head_pa = addr_to_phys(instance->queue_head);
    6060        usb_log_debug2("Transfer list %s setup with QH: %p(%p).\n",
    61             name, instance->queue_head, instance->queue_head_pa);
     61            name, instance->queue_head, queue_head_pa);
    6262
    6363        qh_init(instance->queue_head);
     
    6767}
    6868/*----------------------------------------------------------------------------*/
     69/** Dispose transfer list structures.
     70 *
     71 * @param[in] instance Memory place to use.
     72 *
     73 * Frees memory for internal qh_t structure.
     74 */
     75void transfer_list_fini(transfer_list_t *instance)
     76{
     77        assert(instance);
     78        free32(instance->queue_head);
     79}
    6980/** Set the next list in transfer list chain.
    7081 *
     
    8192        if (!instance->queue_head)
    8293                return;
    83         /* Set both queue_head.next to point to the follower */
    84         qh_set_next_qh(instance->queue_head, next->queue_head_pa);
    85 }
    86 /*----------------------------------------------------------------------------*/
    87 /** Submit transfer batch to the list and queue.
     94        /* Set queue_head.next to point to the follower */
     95        qh_set_next_qh(instance->queue_head, next->queue_head);
     96}
     97/*----------------------------------------------------------------------------*/
     98/** Add transfer batch to the list and queue.
    8899 *
    89100 * @param[in] instance List to use.
    90101 * @param[in] batch Transfer batch to submit.
    91  * @return Error code
    92102 *
    93103 * The batch is added to the end of the list and queue.
     
    109119        } else {
    110120                /* There is something scheduled */
    111                 usb_transfer_batch_t *last = list_get_instance(
    112                     instance->batch_list.prev, usb_transfer_batch_t, link);
     121                usb_transfer_batch_t *last =
     122                    usb_transfer_batch_from_link(instance->batch_list.prev);
    113123                last_qh = batch_qh(last);
    114124        }
     
    118128        /* keep link */
    119129        batch_qh(batch)->next = last_qh->next;
    120         qh_set_next_qh(last_qh, pa);
     130        qh_set_next_qh(last_qh, batch_qh(batch));
    121131
    122132        asm volatile ("": : :"memory");
     
    132142}
    133143/*----------------------------------------------------------------------------*/
    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.
     144/** Add completed bantches to the provided list.
     145 *
     146 * @param[in] instance List to use.
     147 * @param[in] done list to fill
    142148 */
    143149void transfer_list_remove_finished(transfer_list_t *instance, link_t *done)
     
    151157                link_t *next = current->next;
    152158                usb_transfer_batch_t *batch =
    153                     list_get_instance(current, usb_transfer_batch_t, link);
     159                    usb_transfer_batch_from_link(current);
    154160
    155161                if (batch_is_complete(batch)) {
    156                         /* Save for post-processing */
     162                        /* Save for processing */
    157163                        transfer_list_remove_batch(instance, batch);
    158164                        list_append(current, done);
     
    161167        }
    162168        fibril_mutex_unlock(&instance->guard);
    163 
    164 }
    165 /*----------------------------------------------------------------------------*/
    166 /** Walk the list and abort all batches.
     169}
     170/*----------------------------------------------------------------------------*/
     171/** Walk the list and finish all batches with EINTR.
    167172 *
    168173 * @param[in] instance List to use.
     
    174179                link_t *current = instance->batch_list.next;
    175180                usb_transfer_batch_t *batch =
    176                     list_get_instance(current, usb_transfer_batch_t, link);
     181                    usb_transfer_batch_from_link(current);
    177182                transfer_list_remove_batch(instance, batch);
    178                 usb_transfer_batch_finish(batch, EIO);
     183                usb_transfer_batch_finish_error(batch, EINTR);
    179184        }
    180185        fibril_mutex_unlock(&instance->guard);
     
    185190 * @param[in] instance List to use.
    186191 * @param[in] batch Transfer batch to remove.
    187  * @return Error code
    188192 *
    189193 * Does not lock the transfer list, caller is responsible for that.
     
    202206
    203207        const char *qpos = NULL;
     208        qh_t *prev_qh = NULL;
    204209        /* Remove from the hardware queue */
    205210        if (instance->batch_list.next == &batch->link) {
    206211                /* I'm the first one here */
    207                 assert((instance->queue_head->next & LINK_POINTER_ADDRESS_MASK)
    208                     == addr_to_phys(batch_qh(batch)));
    209                 instance->queue_head->next = batch_qh(batch)->next;
     212                prev_qh = instance->queue_head;
    210213                qpos = "FIRST";
    211214        } else {
     215                /* The thing before me is a batch too */
    212216                usb_transfer_batch_t *prev =
    213                     list_get_instance(
    214                         batch->link.prev, usb_transfer_batch_t, link);
    215                 assert((batch_qh(prev)->next & LINK_POINTER_ADDRESS_MASK)
    216                     == addr_to_phys(batch_qh(batch)));
    217                 batch_qh(prev)->next = batch_qh(batch)->next;
     217                    usb_transfer_batch_from_link(batch->link.prev);
     218                prev_qh = batch_qh(prev);
    218219                qpos = "NOT FIRST";
    219220        }
     221        assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)
     222            == addr_to_phys(batch_qh(batch)));
     223        prev_qh->next = batch_qh(batch)->next;
    220224        asm volatile ("": : :"memory");
    221225        /* Remove from the batch list */
    222226        list_remove(&batch->link);
    223         usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n",
     227        usb_log_debug("Batch(%p) removed (%s) from %s, next: %x.\n",
    224228            batch, qpos, instance->name, batch_qh(batch)->next);
    225229}
  • uspace/drv/uhci-hcd/transfer_list.h

    ref354b6 re50cd7f  
    3939#include "batch.h"
    4040#include "hw_struct/queue_head.h"
    41 #include "utils/malloc32.h"
    4241
     42/** Structure maintaining both hw queue and software list
     43 * of currently executed transfers
     44 */
    4345typedef struct transfer_list
    4446{
     47        /** Guard against multiple add/remove races */
    4548        fibril_mutex_t guard;
     49        /** UHCI hw structure represeting this queue */
    4650        qh_t *queue_head;
    47         uint32_t queue_head_pa;
     51        /** Assigned name, for nicer debug output */
    4852        const char *name;
     53        /** List of all batches in this list */
    4954        link_t batch_list;
    5055} transfer_list_t;
    5156
    52 /** Dispose transfer list structures.
    53  *
    54  * @param[in] instance Memory place to use.
    55  *
    56  * Frees memory for internal qh_t structure.
    57  */
    58 static inline void transfer_list_fini(transfer_list_t *instance)
    59 {
    60         assert(instance);
    61         free32(instance->queue_head);
    62 }
    63 
     57void transfer_list_fini(transfer_list_t *instance);
    6458int transfer_list_init(transfer_list_t *instance, const char *name);
    65 
    6659void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    67 
    68 void transfer_list_add_batch(transfer_list_t *instance, usb_transfer_batch_t *batch);
    69 
     60void transfer_list_add_batch(
     61    transfer_list_t *instance, usb_transfer_batch_t *batch);
    7062void transfer_list_remove_finished(transfer_list_t *instance, link_t *done);
    71 
    7263void transfer_list_abort_all(transfer_list_t *instance);
    7364#endif
  • uspace/drv/uhci-hcd/uhci.c

    ref354b6 re50cd7f  
    4444#include "pci.h"
    4545
    46 /** IRQ handling callback, identifies device
     46/** IRQ handling callback, forward status from call to diver structure.
    4747 *
    4848 * @param[in] dev DDF instance of the device to use.
    4949 * @param[in] iid (Unused).
    50  * @param[in] call Pointer to the call that represents interrupt.
     50 * @param[in] call Pointer to the call from kernel.
    5151 */
    5252static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
     
    6161/** Get address of the device identified by handle.
    6262 *
    63  * @param[in] dev DDF instance of the device to use.
    64  * @param[in] iid (Unused).
    65  * @param[in] call Pointer to the call that represents interrupt.
     63 * @param[in] fun DDF instance of the function to use.
     64 * @param[in] handle DDF handle of the driver seeking its USB address.
     65 * @param[out] address Found address.
    6666 */
    6767static int usb_iface_get_address(
     
    6969{
    7070        assert(fun);
    71         usb_device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.manager;
     71        usb_device_keeper_t *manager =
     72            &((uhci_t*)fun->dev->driver_data)->hc.manager;
    7273
    7374        usb_address_t addr = usb_device_keeper_find(manager, handle);
     
    8384}
    8485/*----------------------------------------------------------------------------*/
    85 /** Gets handle of the respective hc (this or parent device).
    86  *
    87  * @param[in] root_hub_fun Root hub function seeking hc handle.
    88  * @param[out] handle Place to write the handle.
     86/** Gets handle of the respective hc.
     87 *
     88 * @param[in] fun DDF function of uhci device.
     89 * @param[out] handle Host cotnroller handle.
    8990 * @return Error code.
    9091 */
     
    100101}
    101102/*----------------------------------------------------------------------------*/
    102 /** This iface is generic for both RH and HC. */
     103/** USB interface implementation used by RH */
    103104static usb_iface_t usb_iface = {
    104105        .get_hc_handle = usb_iface_get_hc_handle,
     
    106107};
    107108/*----------------------------------------------------------------------------*/
     109/** Operations supported by the HC driver */
    108110static ddf_dev_ops_t hc_ops = {
    109 //      .interfaces[USB_DEV_IFACE] = &usb_iface,
    110111        .interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
    111112};
     
    122123}
    123124/*----------------------------------------------------------------------------*/
     125/** Interface to provide the root hub driver with hw info */
    124126static hw_res_ops_t hw_res_iface = {
    125127        .get_resource_list = get_resource_list,
     
    127129};
    128130/*----------------------------------------------------------------------------*/
     131/** RH function support for uhci-rhd */
    129132static ddf_dev_ops_t rh_ops = {
    130133        .interfaces[USB_DEV_IFACE] = &usb_iface,
     
    132135};
    133136/*----------------------------------------------------------------------------*/
    134 /** Initialize hc and rh ddf structures and their respective drivers.
     137/** Initialize hc and rh DDF structures and their respective drivers.
    135138 *
    136139 * @param[in] instance UHCI structure to use.
     
    138141 *
    139142 * This function does all the preparatory work for hc and rh drivers:
    140  *  - gets device hw resources
    141  *  - disables UHCI legacy support
     143 *  - gets device's hw resources
     144 *  - disables UHCI legacy support (PCI config space)
    142145 *  - asks for interrupt
    143146 *  - registers interrupt handler
     
    193196        ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
    194197        CHECK_RET_DEST_FUN_RETURN(ret,
    195             "Failed(%d) to create HC function.\n", ret);
     198            "Failed(%d) to create HC function: %s.\n", ret, str_error(ret));
    196199
    197200        ret = hc_init(&instance->hc, instance->hc_fun,
    198201            (void*)io_reg_base, io_reg_size, interrupts);
    199         CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
     202        CHECK_RET_DEST_FUN_RETURN(ret,
     203            "Failed(%d) to init uhci-hcd: %s.\n", ret, str_error(ret));
     204
    200205        instance->hc_fun->ops = &hc_ops;
    201206        instance->hc_fun->driver_data = &instance->hc;
     
    221226            &instance->hc.interrupt_code);
    222227        CHECK_RET_FINI_RETURN(ret,
    223             "Failed(%d) to register interrupt handler.\n", ret);
     228            "Failed(%d) to register interrupt handler: %s.\n",
     229            ret, str_error(ret));
    224230
    225231        instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh");
    226232        ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
    227233        CHECK_RET_FINI_RETURN(ret,
    228             "Failed(%d) to create root hub function.\n", ret);
     234            "Failed(%d) to create root hub function: %s.\n",
     235            ret, str_error(ret));
    229236
    230237        ret = rh_init(&instance->rh, instance->rh_fun,
    231238            (uintptr_t)instance->hc.registers + 0x10, 4);
    232239        CHECK_RET_FINI_RETURN(ret,
    233             "Failed(%d) to setup UHCI root hub.\n", ret);
     240            "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));
    234241
    235242        instance->rh_fun->ops = &rh_ops;
     
    237244        ret = ddf_fun_bind(instance->rh_fun);
    238245        CHECK_RET_FINI_RETURN(ret,
    239             "Failed(%d) to register UHCI root hub.\n", ret);
     246            "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
    240247
    241248        return EOK;
  • uspace/drv/uhci-hcd/uhci.h

    ref354b6 re50cd7f  
    4141#include "root_hub.h"
    4242
     43/** Structure representing both functions of UHCI hc, USB host controller
     44 * and USB root hub */
    4345typedef struct uhci {
     46        /** Pointer to DDF represenation of UHCI host controller */
    4447        ddf_fun_t *hc_fun;
     48        /** Pointer to DDF represenation of UHCI root hub */
    4549        ddf_fun_t *rh_fun;
    4650
     51        /** Internal driver's represenation of UHCI host controller */
    4752        hc_t hc;
     53        /** Internal driver's represenation of UHCI root hub */
    4854        rh_t rh;
    4955} uhci_t;
    5056
    5157int uhci_init(uhci_t *instance, ddf_dev_t *device);
    52 
    5358#endif
    5459/**
  • uspace/drv/uhci-rhd/port.c

    ref354b6 re50cd7f  
    6868 * @return Error code. (Always EOK)
    6969 */
    70 static inline void uhci_port_write_status(
    71     uhci_port_t *port, port_status_t value)
    72 {
    73         assert(port);
    74         pio_write_16(port->address, value);
     70static inline void uhci_port_write_status(uhci_port_t *port, port_status_t val)
     71{
     72        assert(port);
     73        pio_write_16(port->address, val);
    7574}
    7675/*----------------------------------------------------------------------------*/
     
    101100        port->rh = rh;
    102101
    103         int rc = usb_hc_connection_initialize_from_device(
    104             &port->hc_connection, rh);
    105         if (rc != EOK) {
     102        int ret =
     103            usb_hc_connection_initialize_from_device(&port->hc_connection, rh);
     104        if (ret != EOK) {
    106105                usb_log_error("Failed to initialize connection to HC.");
    107                 return rc;
     106                return ret;
    108107        }
    109108
     
    238237        /* Enable the port. */
    239238        uhci_port_set_enabled(port, true);
    240 
    241239        return EOK;
    242240}
     
    271269        usb_log_info("New device at port %u, address %d (handle %llu).\n",
    272270            port->number, dev_addr, port->attached_device);
    273 
    274271        return EOK;
    275272}
     
    313310        /* Write new value. */
    314311        uhci_port_write_status(port, port_status);
     312
     313        /* Wait for port to become enabled */
     314        do {
     315                async_usleep(1000);
     316                port_status = uhci_port_read_status(port);
     317        } while ((port_status & STATUS_CONNECTED) &&
     318            !(port_status & STATUS_ENABLED));
    315319
    316320        usb_log_debug("%s: %sabled port.\n",
  • uspace/drv/uhci-rhd/port.h

    ref354b6 re50cd7f  
    5454#define STATUS_SUSPEND   (1 << 12)
    5555
     56/** UHCI port structure */
    5657typedef struct uhci_port
    5758{
  • uspace/drv/uhci-rhd/root_hub.c

    ref354b6 re50cd7f  
    3333 */
    3434#include <errno.h>
     35#include <str_error.h>
    3536#include <ddi.h>
    3637#include <usb/debug.h>
     
    4344 * @param[in] addr Address of I/O registers.
    4445 * @param[in] size Size of available I/O space.
    45  * @param[in] rh Pointer to ddf instance of the root hub driver.
     46 * @param[in] rh Pointer to DDF instance of the root hub driver.
    4647 * @return Error code.
    4748 */
     
    5859        if (ret < 0) {
    5960                usb_log_error(
    60                     "Failed(%d) to gain access to port registers at %p\n",
    61                     ret, regs);
     61                    "Failed(%d) to gain access to port registers at %p: %s.\n",
     62                    ret, regs, str_error(ret));
    6263                return ret;
    6364        }
     
    6667        unsigned i = 0;
    6768        for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
    68                 /* NOTE: mind pointer arithmetics here */
    6969                ret = uhci_port_init(
    70                     &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);
     70                    &instance->ports[i], &regs[i], i, ROOT_HUB_WAIT_USEC, rh);
    7171                if (ret != EOK) {
    7272                        unsigned j = 0;
  • uspace/drv/uhci-rhd/root_hub.h

    ref354b6 re50cd7f  
    4040
    4141#define UHCI_ROOT_HUB_PORT_COUNT 2
    42 #define ROOT_HUB_WAIT_USEC 5000000 /* 5 seconds */
     42#define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */
    4343
     44/** UHCI root hub drvier structure */
    4445typedef struct root_hub {
     46        /** Ports provided by the hub */
    4547        uhci_port_t ports[UHCI_ROOT_HUB_PORT_COUNT];
    46         devman_handle_t hc_handle;
    4748} uhci_root_hub_t;
    4849
    4950int uhci_root_hub_init(
    50   uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh);
     51    uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh);
    5152
    5253void uhci_root_hub_fini(uhci_root_hub_t *instance);
  • uspace/drv/usbhid/generic/hiddev.h

    ref354b6 re50cd7f  
    11/*
    2  * Copyright (c) 2007 Jan Hudecek
    3  * Copyright (c) 2008 Martin Decky
     2 * Copyright (c) 2011 Lubos Slovak
    43 * All rights reserved.
    54 *
     
    2827 */
    2928
    30 /** @addtogroup genericproc
     29/** @addtogroup drvusbhid
    3130 * @{
    3231 */
    33 /** @file tasklet.c
    34  *  @brief Tasklet implementation
     32/** @file
     33 * USB HID driver API.
    3534 */
    3635
    37 #include <proc/tasklet.h>
    38 #include <synch/spinlock.h>
    39 #include <mm/slab.h>
    40 #include <config.h>
     36#ifndef USB_HID_HIDDDEV_H_
     37#define USB_HID_HIDDDEV_H_
    4138
    42 /** Spinlock protecting list of tasklets */
    43 SPINLOCK_INITIALIZE(tasklet_lock);
     39#include <usb/devdrv.h>
    4440
    45 /** Array of tasklet lists for every CPU */
    46 tasklet_descriptor_t **tasklet_list;
     41struct usb_hid_dev;
    4742
    48 void tasklet_init(void)
    49 {
    50         unsigned int i;
    51        
    52         tasklet_list = malloc(sizeof(tasklet_descriptor_t *) * config.cpu_count, 0);
    53         if (!tasklet_list)
    54                 panic("Error initializing tasklets.");
    55        
    56         for (i = 0; i < config.cpu_count; i++)
    57                 tasklet_list[i] = NULL;
    58        
    59         spinlock_initialize(&tasklet_lock, "tasklet_lock");
    60 }
     43usb_endpoint_description_t usb_hid_generic_poll_endpoint_description;
    6144
     45const char *HID_GENERIC_FUN_NAME;
     46const char *HID_GENERIC_CLASS_NAME;
    6247
    63 /** @}
     48bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev,
     49    uint8_t *buffer, size_t buffer_size);
     50
     51#endif // USB_HID_HIDDDEV_H_
     52
     53/**
     54 * @}
    6455 */
  • uspace/drv/usbhub/Makefile

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

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

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

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

    ref354b6 re50cd7f  
    3737#include <errno.h>
    3838#include <str_error.h>
     39#include <inttypes.h>
    3940
    4041#include <usb_iface.h>
     
    4445#include <usb/request.h>
    4546#include <usb/classes/hub.h>
     47#include <usb/devpoll.h>
    4648#include <stdio.h>
    4749
     
    5355#include "usb/classes/classes.h"
    5456
    55 static int usb_hub_trigger_connecting_non_removable_devices(
    56                 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor);
    57 
     57
     58static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev);
     59
     60static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info);
     61
     62static int usb_hub_set_configuration(usb_hub_info_t * hub_info);
     63
     64static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info);
     65
     66static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     67    usb_hub_status_t status);
     68
     69static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
     70    usb_hub_status_t status);
     71
     72static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info);
     73
     74
     75/// \TODO malloc checking
    5876
    5977//*********************************************
    6078//
    6179//  hub driver code, initialization
     80//
     81//*********************************************
     82
     83/**
     84 * Initialize hub device driver fibril
     85 *
     86 * Creates hub representation and fibril that periodically checks hub`s status.
     87 * Hub representation is passed to the fibril.
     88 * @param usb_dev generic usb device information
     89 * @return error code
     90 */
     91int usb_hub_add_device(usb_device_t * usb_dev) {
     92        if (!usb_dev) return EINVAL;
     93        usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);
     94        //create hc connection
     95        usb_log_debug("Initializing USB wire abstraction.\n");
     96        int opResult = usb_hc_connection_initialize_from_device(
     97            &hub_info->connection,
     98            hub_info->usb_device->ddf_dev);
     99        if (opResult != EOK) {
     100                usb_log_error("could not initialize connection to device, "
     101                    "errno %d\n",
     102                    opResult);
     103                free(hub_info);
     104                return opResult;
     105        }
     106
     107        //usb_pipe_start_session(hub_info->control_pipe);
     108        //set hub configuration
     109        opResult = usb_hub_set_configuration(hub_info);
     110        if (opResult != EOK) {
     111                usb_log_error("could not set hub configuration, errno %d\n",
     112                    opResult);
     113                free(hub_info);
     114                return opResult;
     115        }
     116        //get port count and create attached_devs
     117        opResult = usb_hub_process_hub_specific_info(hub_info);
     118        if (opResult != EOK) {
     119                usb_log_error("could process hub specific info, errno %d\n",
     120                    opResult);
     121                free(hub_info);
     122                return opResult;
     123        }
     124        //usb_pipe_end_session(hub_info->control_pipe);
     125
     126
     127        usb_log_debug("Creating 'hub' function in DDF.\n");
     128        ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
     129            fun_exposed, "hub");
     130        assert(hub_fun != NULL);
     131        hub_fun->ops = NULL;
     132
     133        opResult = ddf_fun_bind(hub_fun);
     134        assert(opResult == EOK);
     135        opResult = ddf_fun_add_to_class(hub_fun, "hub");
     136        assert(opResult == EOK);
     137
     138        opResult = usb_hub_start_hub_fibril(hub_info);
     139        if(opResult!=EOK)
     140                free(hub_info);
     141        return opResult;
     142}
     143
     144
     145/** Callback for polling hub for changes.
     146 *
     147 * @param dev Device where the change occured.
     148 * @param change_bitmap Bitmap of changed ports.
     149 * @param change_bitmap_size Size of the bitmap in bytes.
     150 * @param arg Custom argument, points to @c usb_hub_info_t.
     151 * @return Whether to continue polling.
     152 */
     153bool hub_port_changes_callback(usb_device_t *dev,
     154    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) {
     155        usb_log_debug("hub_port_changes_callback\n");
     156        usb_hub_info_t *hub = (usb_hub_info_t *) arg;
     157
     158        /* FIXME: check that we received enough bytes. */
     159        if (change_bitmap_size == 0) {
     160                goto leave;
     161        }
     162
     163        bool change;
     164        change = ((uint8_t*) change_bitmap)[0] & 1;
     165        if (change) {
     166                usb_hub_process_global_interrupt(hub);
     167        }
     168
     169        size_t port;
     170        for (port = 1; port < hub->port_count + 1; port++) {
     171                bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;
     172                if (change) {
     173                        usb_hub_process_interrupt(hub, port);
     174                }
     175        }
     176leave:
     177        /* FIXME: proper interval. */
     178        async_usleep(1000 * 1000 * 10);
     179
     180        return true;
     181}
     182
     183
     184//*********************************************
     185//
     186//  support functions
    62187//
    63188//*********************************************
     
    71196 */
    72197static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) {
    73         usb_hub_info_t * result = usb_new(usb_hub_info_t);
    74         if(!result) return NULL;
     198        usb_hub_info_t * result = malloc(sizeof(usb_hub_info_t));
     199        if (!result) return NULL;
    75200        result->usb_device = usb_dev;
    76201        result->status_change_pipe = usb_dev->pipes[0].pipe;
     
    90215 * @return error code
    91216 */
    92 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info){
     217static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) {
    93218        // get hub descriptor
    94219        usb_log_debug("creating serialized descriptor\n");
    95         void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
     220        //void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
     221        uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
    96222        usb_hub_descriptor_t * descriptor;
    97 
    98         /* this was one fix of some bug, should not be needed anymore
    99          * these lines allow to reset hub once more, it can be used as
    100          * brute-force initialization for non-removable devices
    101         int opResult = usb_request_set_configuration(&result->endpoints.control, 1);
    102         if(opResult!=EOK){
    103                 usb_log_error("could not set default configuration, errno %d",opResult);
    104                 return opResult;
    105         }
    106          */
     223        int opResult;
     224
    107225        size_t received_size;
    108         int opResult = usb_request_get_descriptor(&hub_info->usb_device->ctrl_pipe,
    109                         USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
    110                         USB_DESCTYPE_HUB,
    111                         0, 0, serialized_descriptor,
    112                         USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
    113 
    114         if (opResult != EOK) {
    115                 usb_log_error("failed when receiving hub descriptor, badcode = %d\n",
    116                                 opResult);
     226        opResult = usb_request_get_descriptor(hub_info->control_pipe,
     227            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
     228            USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
     229            USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
     230
     231        if (opResult != EOK) {
     232                usb_log_error("failed when receiving hub descriptor, "
     233                    "badcode = %d\n",
     234                    opResult);
    117235                free(serialized_descriptor);
    118236                return opResult;
    119237        }
    120238        usb_log_debug2("deserializing descriptor\n");
    121         descriptor = usb_deserialize_hub_desriptor(serialized_descriptor);
    122         if(descriptor==NULL){
     239        descriptor = usb_create_deserialized_hub_desriptor(
     240            serialized_descriptor);
     241        if (descriptor == NULL) {
    123242                usb_log_warning("could not deserialize descriptor \n");
    124                 return opResult;
    125         }
    126         usb_log_debug("setting port count to %d\n",descriptor->ports_count);
     243                return ENOMEM;
     244        }
     245        usb_log_debug("setting port count to %d\n", descriptor->ports_count);
    127246        hub_info->port_count = descriptor->ports_count;
    128         hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1));
     247        /// \TODO this is not semantically correct
     248        bool is_power_switched =
     249            ((descriptor->hub_characteristics & 1) ==0);
     250        bool has_individual_port_powering =
     251            ((descriptor->hub_characteristics & 1) !=0);
     252        hub_info->ports = malloc(
     253            sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
    129254        size_t port;
    130255        for (port = 0; port < hub_info->port_count + 1; port++) {
    131256                usb_hub_port_init(&hub_info->ports[port]);
    132257        }
    133         //handle non-removable devices
    134         usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor);
     258        if(is_power_switched){
     259                usb_log_debug("is_power_switched\n");
     260                if(has_individual_port_powering){
     261                        usb_log_debug("has_individual_port_powering\n");
     262                        for (port = 0; port < hub_info->port_count; port++) {
     263                                opResult = usb_hub_set_port_feature(hub_info->control_pipe,
     264                                    port+1, USB_HUB_FEATURE_PORT_POWER);
     265                                if (opResult != EOK) {
     266                                        usb_log_error("cannot power on port %d;  %d\n",
     267                                            port+1, opResult);
     268                                }
     269                        }
     270                }else{
     271                        usb_log_debug("!has_individual_port_powering\n");
     272                        opResult = usb_hub_set_feature(hub_info->control_pipe,
     273                            USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
     274                        if (opResult != EOK) {
     275                                usb_log_error("cannot power hub;  %d\n",
     276                                  opResult);
     277                        }
     278                }
     279        }else{
     280                usb_log_debug("!is_power_switched\n");
     281        }
    135282        usb_log_debug2("freeing data\n");
    136         free(serialized_descriptor);
    137         free(descriptor->devices_removable);
     283        //free(serialized_descriptor);
     284        //free(descriptor->devices_removable);
    138285        free(descriptor);
    139286        return EOK;
    140287}
     288
    141289/**
    142290 * Set configuration of hub
     
    147295 * @return error code
    148296 */
    149 static int usb_hub_set_configuration(usb_hub_info_t * hub_info){
     297static int usb_hub_set_configuration(usb_hub_info_t * hub_info) {
    150298        //device descriptor
    151299        usb_standard_device_descriptor_t *std_descriptor
     
    153301        usb_log_debug("hub has %d configurations\n",
    154302            std_descriptor->configuration_count);
    155         if(std_descriptor->configuration_count<1){
     303        if (std_descriptor->configuration_count < 1) {
    156304                usb_log_error("there are no configurations available\n");
    157305                return EINVAL;
     
    173321        }
    174322        usb_log_debug("\tused configuration %d\n",
    175                         config_descriptor->configuration_number);
     323            config_descriptor->configuration_number);
    176324
    177325        return EOK;
     
    179327
    180328/**
    181  * Initialize hub device driver fibril
    182  *
    183  * Creates hub representation and fibril that periodically checks hub`s status.
    184  * Hub representation is passed to the fibril.
    185  * @param usb_dev generic usb device information
    186  * @return error code
    187  */
    188 int usb_hub_add_device(usb_device_t * usb_dev){
    189         if(!usb_dev) return EINVAL;
    190         usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);
    191         //create hc connection
    192         usb_log_debug("Initializing USB wire abstraction.\n");
    193         int opResult = usb_hc_connection_initialize_from_device(
    194                         &hub_info->connection,
    195                         hub_info->usb_device->ddf_dev);
    196         if(opResult != EOK){
    197                 usb_log_error("could not initialize connection to device, errno %d\n",
    198                                 opResult);
    199                 free(hub_info);
    200                 return opResult;
    201         }
    202        
    203         usb_pipe_start_session(hub_info->control_pipe);
    204         //set hub configuration
    205         opResult = usb_hub_set_configuration(hub_info);
    206         if(opResult!=EOK){
    207                 usb_log_error("could not set hub configuration, errno %d\n",opResult);
    208                 free(hub_info);
    209                 return opResult;
    210         }
    211         //get port count and create attached_devs
    212         opResult = usb_hub_process_hub_specific_info(hub_info);
    213         if(opResult!=EOK){
    214                 usb_log_error("could not set hub configuration, errno %d\n",opResult);
    215                 free(hub_info);
    216                 return opResult;
    217         }
    218         usb_pipe_end_session(hub_info->control_pipe);
    219 
    220 
    221         /// \TODO what is this?
    222         usb_log_debug("Creating `hub' function.\n");
    223         ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
    224                         fun_exposed, "hub");
    225         assert(hub_fun != NULL);
    226         hub_fun->ops = NULL;
    227 
    228         int rc = ddf_fun_bind(hub_fun);
    229         assert(rc == EOK);
    230         rc = ddf_fun_add_to_class(hub_fun, "hub");
    231         assert(rc == EOK);
    232 
     329 * create and start fibril with hub control loop
     330 *
     331 * Before the fibril is started, the control pipe and host controller
     332 * connection of the hub is open.
     333 *
     334 * @param hub_info hub representing structure
     335 * @return error code
     336 */
     337static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info){
    233338        /*
    234339         * The processing will require opened control pipe and connection
     
    239344         * auto destruction, this could work better.
    240345         */
    241         rc = usb_pipe_start_session(&usb_dev->ctrl_pipe);
     346        int rc = usb_hc_connection_open(&hub_info->connection);
    242347        if (rc != EOK) {
    243                 usb_log_error("Failed to start session on control pipe: %s.\n",
    244                     str_error(rc));
    245                 goto leave;
    246         }
    247         rc = usb_hc_connection_open(&hub_info->connection);
    248         if (rc != EOK) {
    249                 usb_pipe_end_session(&usb_dev->ctrl_pipe);
     348                //usb_pipe_end_session(hub_info->control_pipe);
    250349                usb_log_error("Failed to open connection to HC: %s.\n",
    251350                    str_error(rc));
    252                 goto leave;
     351                return rc;
    253352        }
    254353
    255354        rc = usb_device_auto_poll(hub_info->usb_device, 0,
    256             hub_port_changes_callback, ((hub_info->port_count+1) / 8) + 1,
     355            hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
    257356            NULL, hub_info);
    258357        if (rc != EOK) {
     
    266365            hub_info->usb_device->ddf_dev->name, hub_info->port_count);
    267366        return EOK;
    268 
    269 leave:
    270         free(hub_info);
    271 
    272         return rc;
    273 }
    274 
    275 
    276 //*********************************************
    277 //
    278 //  hub driver code, main loop and port handling
    279 //
    280 //*********************************************
    281 
    282 /**
    283  * triggers actions to connect non0removable devices
    284  *
    285  * This will trigger operations leading to activated non-removable device.
    286  * Control pipe of the hub must be open fo communication.
    287  * @param hub hub representation
    288  * @param descriptor usb hub descriptor
    289  * @return error code
    290  */
    291 static int usb_hub_trigger_connecting_non_removable_devices(usb_hub_info_t * hub,
    292                 usb_hub_descriptor_t * descriptor)
    293 {
    294         usb_log_info("attaching non-removable devices(if any)\n");
     367}
     368
     369//*********************************************
     370//
     371//  change handling functions
     372//
     373//*********************************************
     374
     375
     376/**
     377 * process hub over current change
     378 *
     379 * This means either to power off the hub or power it on.
     380 * @param hub_info hub instance
     381 * @param status hub status bitmask
     382 * @return error code
     383 */
     384static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     385    usb_hub_status_t status) {
     386        int opResult;
     387        if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_OVER_CURRENT)){
     388                opResult = usb_hub_clear_feature(hub_info->control_pipe,
     389                    USB_HUB_FEATURE_HUB_LOCAL_POWER);
     390                if (opResult != EOK) {
     391                        usb_log_error("cannot power off hub: %d\n",
     392                            opResult);
     393                }
     394        } else {
     395                opResult = usb_hub_set_feature(hub_info->control_pipe,
     396                    USB_HUB_FEATURE_HUB_LOCAL_POWER);
     397                if (opResult != EOK) {
     398                        usb_log_error("cannot power on hub: %d\n",
     399                            opResult);
     400                }
     401        }
     402        return opResult;
     403}
     404
     405/**
     406 * process hub power change
     407 *
     408 * If the power has been lost, reestablish it.
     409 * If it was reestablished, re-power all ports.
     410 * @param hub_info hub instance
     411 * @param status hub status bitmask
     412 * @return error code
     413 */
     414static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
     415    usb_hub_status_t status) {
     416        int opResult;
     417        if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_LOCAL_POWER)) {
     418                //restart power on hub
     419                opResult = usb_hub_set_feature(hub_info->control_pipe,
     420                    USB_HUB_FEATURE_HUB_LOCAL_POWER);
     421                if (opResult != EOK) {
     422                        usb_log_error("cannot power on hub: %d\n",
     423                            opResult);
     424                }
     425        } else {//power reestablished on hub- restart ports
     426                size_t port;
     427                for (port = 0; port < hub_info->port_count; ++port) {
     428                        opResult = usb_hub_set_port_feature(
     429                            hub_info->control_pipe,
     430                            port, USB_HUB_FEATURE_PORT_POWER);
     431                        if (opResult != EOK) {
     432                                usb_log_error("cannot power on port %d;  %d\n",
     433                                    port, opResult);
     434                        }
     435                }
     436        }
     437        return opResult;
     438}
     439
     440/**
     441 * process hub interrupts
     442 *
     443 * The change can be either in the over-current condition or
     444 * local-power lost condition.
     445 * @param hub_info hub instance
     446 */
     447static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info) {
     448        usb_log_debug("global interrupt on a hub\n");
     449        usb_pipe_t *pipe = hub_info->control_pipe;
     450        int opResult;
     451
     452        usb_port_status_t status;
     453        size_t rcvd_size;
    295454        usb_device_request_setup_packet_t request;
    296         int opResult;
    297         size_t rcvd_size;
    298         usb_port_status_t status;
    299         uint8_t * non_removable_dev_bitmap = descriptor->devices_removable;
    300         int port;
    301         for(port=1;port<=descriptor->ports_count;++port){
    302                 bool is_non_removable =
    303                                 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2;
    304                 if(is_non_removable){
    305                         usb_log_debug("non-removable device on port %d\n",port);
    306                         usb_hub_set_port_status_request(&request, port);
    307                         opResult = usb_pipe_control_read(
    308                                         hub->control_pipe,
    309                                         &request, sizeof(usb_device_request_setup_packet_t),
    310                                         &status, 4, &rcvd_size
    311                                         );
    312                         if (opResult != EOK) {
    313                                 usb_log_error("could not get port status of port %d errno:%d\n",
    314                                                 port, opResult);
    315                                 return opResult;
    316                         }
    317                         //set the status change bit, so it will be noticed in driver loop
    318                         if(usb_port_dev_connected(&status)){
    319                                 usb_hub_set_disable_port_feature_request(&request, port,
    320                                                 USB_HUB_FEATURE_PORT_CONNECTION);
    321                                 opResult = usb_pipe_control_read(
    322                                                 hub->control_pipe,
    323                                                 &request, sizeof(usb_device_request_setup_packet_t),
    324                                                 &status, 4, &rcvd_size
    325                                                 );
    326                                 if (opResult != EOK) {
    327                                         usb_log_warning(
    328                                                         "could not clear port connection on port %d errno:%d\n",
    329                                                         port, opResult);
    330                                 }
    331                                 usb_log_debug("cleared port connection\n");
    332                                 usb_hub_set_enable_port_feature_request(&request, port,
    333                                                 USB_HUB_FEATURE_PORT_ENABLE);
    334                                 opResult = usb_pipe_control_read(
    335                                                 hub->control_pipe,
    336                                                 &request, sizeof(usb_device_request_setup_packet_t),
    337                                                 &status, 4, &rcvd_size
    338                                                 );
    339                                 if (opResult != EOK) {
    340                                         usb_log_warning(
    341                                                         "could not set port enabled on port %d errno:%d\n",
    342                                                         port, opResult);
    343                                 }
    344                                 usb_log_debug("port set to enabled - should lead to connection change\n");
    345                         }
    346                 }
    347         }
    348         /// \TODO this is just a debug code
    349         for(port=1;port<=descriptor->ports_count;++port){
    350                 bool is_non_removable =
    351                                 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2;
    352                 if(is_non_removable){
    353                         usb_log_debug("port %d is non-removable\n",port);
    354                         usb_port_status_t status;
    355                         size_t rcvd_size;
    356                         usb_device_request_setup_packet_t request;
    357                         //int opResult;
    358                         usb_hub_set_port_status_request(&request, port);
    359                         //endpoint 0
    360                         opResult = usb_pipe_control_read(
    361                                         hub->control_pipe,
    362                                         &request, sizeof(usb_device_request_setup_packet_t),
    363                                         &status, 4, &rcvd_size
    364                                         );
    365                         if (opResult != EOK) {
    366                                 usb_log_error("could not get port status %d\n",opResult);
    367                         }
    368                         if (rcvd_size != sizeof (usb_port_status_t)) {
    369                                 usb_log_error("received status has incorrect size\n");
    370                         }
    371                         //something connected/disconnected
    372                         if (usb_port_connect_change(&status)) {
    373                                 usb_log_debug("some connection changed\n");
    374                         }
    375                         usb_log_debug("status: %s\n",usb_debug_str_buffer(
    376                                         (uint8_t *)&status,4,4));
    377                 }
    378         }
    379         return EOK;
    380 }
    381 
    382 
    383 /**
    384  * release default address used by given hub
    385  *
    386  * Also unsets hub->is_default_address_used. Convenience wrapper function.
    387  * @note hub->connection MUST be open for communication
    388  * @param hub hub representation
    389  * @return error code
    390  */
    391 static int usb_hub_release_default_address(usb_hub_info_t * hub){
    392         int opResult = usb_hc_release_default_address(&hub->connection);
    393         if(opResult!=EOK){
    394                 usb_log_error("could not release default address, errno %d\n",opResult);
    395                 return opResult;
    396         }
    397         hub->is_default_address_used = false;
    398         return EOK;
    399 }
    400 
    401 /**
    402  * routine called when a device on port has been removed
    403  *
    404  * If the device on port had default address, it releases default address.
    405  * Otherwise does not do anything, because DDF does not allow to remove device
    406  * from it`s device tree.
    407  * @param hub hub representation
    408  * @param port port number, starting from 1
    409  */
    410 void usb_hub_removed_device(
    411     usb_hub_info_t * hub,uint16_t port) {
    412 
    413         int opResult = usb_hub_clear_port_feature(hub->control_pipe,
    414                                 port, USB_HUB_FEATURE_C_PORT_CONNECTION);
    415         if(opResult != EOK){
    416                 usb_log_warning("could not clear port-change-connection flag\n");
    417         }
    418         /** \TODO remove device from device manager - not yet implemented in
    419          * devide manager
    420          */
    421        
    422         //close address
    423         if(hub->ports[port].attached_device.address >= 0){
    424                 /*uncomment this code to use it when DDF allows device removal
    425                 opResult = usb_hc_unregister_device(
    426                                 &hub->connection, hub->attached_devs[port].address);
    427                 if(opResult != EOK) {
    428                         dprintf(USB_LOG_LEVEL_WARNING, "could not release address of " \
    429                             "removed device: %d", opResult);
    430                 }
    431                 hub->attached_devs[port].address = 0;
    432                 hub->attached_devs[port].handle = 0;
    433                  */
    434         }else{
    435                 usb_log_warning("this is strange, disconnected device had no address\n");
    436                 //device was disconnected before it`s port was reset - return default address
    437                 usb_hub_release_default_address(hub);
    438         }
    439 }
    440 
    441 
    442 /**
    443  * Process over current condition on port.
    444  *
    445  * Turn off the power on the port.
    446  *
    447  * @param hub hub representation
    448  * @param port port number, starting from 1
    449  */
    450 void usb_hub_over_current( usb_hub_info_t * hub,
    451                 uint16_t port){
    452         int opResult;
    453         opResult = usb_hub_clear_port_feature(hub->control_pipe,
    454             port, USB_HUB_FEATURE_PORT_POWER);
    455         if(opResult!=EOK){
    456                 usb_log_error("cannot power off port %d;  %d\n",
    457                                 port, opResult);
    458         }
    459 }
    460 
     455        //int opResult;
     456        usb_hub_set_hub_status_request(&request);
     457        //endpoint 0
     458
     459        opResult = usb_pipe_control_read(
     460            pipe,
     461            &request, sizeof (usb_device_request_setup_packet_t),
     462            &status, 4, &rcvd_size
     463            );
     464        if (opResult != EOK) {
     465                usb_log_error("could not get hub status\n");
     466                return;
     467        }
     468        if (rcvd_size != sizeof (usb_port_status_t)) {
     469                usb_log_error("received status has incorrect size\n");
     470                return;
     471        }
     472        //port reset
     473        if (
     474            usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {
     475                usb_process_hub_over_current(hub_info, status);
     476        }
     477        if (
     478            usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {
     479                usb_process_hub_power_change(hub_info, status);
     480        }
     481}
    461482
    462483/**
  • uspace/drv/usbhub/usbhub.h

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

    ref354b6 re50cd7f  
    5454//
    5555//************
    56 #define usb_new(type) (type*)malloc(sizeof(type))
    5756
    5857
    59 /**
    60  * Create hub structure instance
    61  *
    62  * Set the address and port count information most importantly.
    63  *
    64  * @param device
    65  * @param hc host controller phone
    66  * @return
    67  */
    6858usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device);
    6959
     
    110100
    111101/**
    112  * create uint8_t array with serialized descriptor
     102 * Clear feature on hub port.
    113103 *
    114  * @param descriptor
    115  * @return newly created serializd descriptor pointer
     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
    116109 */
    117 void * usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor);
     110static inline int usb_hub_set_port_feature(usb_pipe_t *pipe,
     111    int port_index,
     112    usb_hub_class_feature_t feature) {
     113
     114        usb_device_request_setup_packet_t clear_request = {
     115                .request_type = USB_HUB_REQ_TYPE_SET_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
    118125
    119126/**
    120  * create deserialized desriptor structure out of serialized descriptor
     127 * Clear feature on hub port.
    121128 *
    122  * The serialized descriptor must be proper usb hub descriptor,
    123  * otherwise an eerror might occur.
     129 * @param pipe pipe to hub control endpoint
     130 * @param feature Feature selector
     131 * @return Operation result
     132 */
     133static inline int usb_hub_clear_feature(usb_pipe_t *pipe,
     134    usb_hub_class_feature_t feature) {
     135
     136        usb_device_request_setup_packet_t clear_request = {
     137                .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
     138                .request = USB_DEVREQ_CLEAR_FEATURE,
     139                .length = 0,
     140                .index = 0
     141        };
     142        clear_request.value = feature;
     143        return usb_pipe_control_write(pipe, &clear_request,
     144            sizeof(clear_request), NULL, 0);
     145}
     146
     147/**
     148 * Clear feature on hub port.
    124149 *
    125  * @param sdescriptor serialized descriptor
    126  * @return newly created deserialized descriptor pointer
     150 * @param pipe pipe to hub control endpoint
     151 * @param feature Feature selector
     152 * @return Operation result
    127153 */
    128 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * sdescriptor);
     154static inline int usb_hub_set_feature(usb_pipe_t *pipe,
     155    usb_hub_class_feature_t feature) {
     156
     157        usb_device_request_setup_packet_t clear_request = {
     158                .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
     159                .request = USB_DEVREQ_SET_FEATURE,
     160                .length = 0,
     161                .index = 0
     162        };
     163        clear_request.value = feature;
     164        return usb_pipe_control_write(pipe, &clear_request,
     165            sizeof(clear_request), NULL, 0);
     166}
     167
     168
     169void * usb_create_serialized_hub_descriptor(usb_hub_descriptor_t * descriptor);
     170
     171void usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor,
     172    void * serialized_descriptor);
     173
     174usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
     175    void * serialized_descriptor);
     176
     177void usb_deserialize_hub_desriptor(void * serialized_descriptor,
     178    usb_hub_descriptor_t * descriptor);
    129179
    130180
  • uspace/drv/usbhub/utils.c

    ref354b6 re50cd7f  
    5656//hub descriptor utils
    5757
    58 void * usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor) {
     58/**
     59 * create uint8_t array with serialized descriptor
     60 *
     61 * @param descriptor
     62 * @return newly created serializd descriptor pointer
     63 */
     64void * usb_create_serialized_hub_descriptor(usb_hub_descriptor_t * descriptor) {
    5965        //base size
    6066        size_t size = 7;
    6167        //variable size according to port count
    62         size_t var_size = descriptor->ports_count / 8 + ((descriptor->ports_count % 8 > 0) ? 1 : 0);
     68        size_t var_size = (descriptor->ports_count+7)/8;
    6369        size += 2 * var_size;
    64         uint8_t * result = (uint8_t*) malloc(size);
     70        uint8_t * result = malloc(size);
    6571        //size
    66         result[0] = size;
     72        if(result)
     73                usb_serialize_hub_descriptor(descriptor,result);
     74        return result;
     75}
     76
     77/**
     78 * serialize descriptor into given buffer
     79 *
     80 * The buffer size is not checked.
     81 * @param descriptor
     82 * @param serialized_descriptor
     83 */
     84void usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor,
     85    void * serialized_descriptor) {
     86        //base size
     87        uint8_t * sdescriptor = serialized_descriptor;
     88        size_t size = 7;
     89        //variable size according to port count
     90        size_t var_size = (descriptor->ports_count+7)/8;
     91        size += 2 * var_size;
     92        //size
     93        sdescriptor[0] = size;
    6794        //descriptor type
    68         result[1] = USB_DESCTYPE_HUB;
    69         result[2] = descriptor->ports_count;
     95        sdescriptor[1] = USB_DESCTYPE_HUB;
     96        sdescriptor[2] = descriptor->ports_count;
    7097        /// @fixme handling of endianness??
    71         result[3] = descriptor->hub_characteristics / 256;
    72         result[4] = descriptor->hub_characteristics % 256;
    73         result[5] = descriptor->pwr_on_2_good_time;
    74         result[6] = descriptor->current_requirement;
     98        sdescriptor[3] = descriptor->hub_characteristics / 256;
     99        sdescriptor[4] = descriptor->hub_characteristics % 256;
     100        sdescriptor[5] = descriptor->pwr_on_2_good_time;
     101        sdescriptor[6] = descriptor->current_requirement;
    75102
    76103        size_t i;
    77104        for (i = 0; i < var_size; ++i) {
    78                 result[7 + i] = descriptor->devices_removable[i];
     105                sdescriptor[7 + i] = descriptor->devices_removable[i];
    79106        }
    80107        for (i = 0; i < var_size; ++i) {
    81                 result[7 + var_size + i] = 255;
     108                sdescriptor[7 + var_size + i] = 255;
    82109        }
     110}
     111
     112
     113/**
     114 * create deserialized desriptor structure out of serialized descriptor
     115 *
     116 * The serialized descriptor must be proper usb hub descriptor,
     117 * otherwise an eerror might occur.
     118 *
     119 * @param sdescriptor serialized descriptor
     120 * @return newly created deserialized descriptor pointer
     121 */
     122usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
     123void * serialized_descriptor) {
     124        uint8_t * sdescriptor = serialized_descriptor;
     125
     126        if (sdescriptor[1] != USB_DESCTYPE_HUB) {
     127                usb_log_warning("trying to deserialize wrong descriptor %x\n",
     128                    sdescriptor[1]);
     129                return NULL;
     130        }
     131
     132        usb_hub_descriptor_t * result = malloc(sizeof(usb_hub_descriptor_t));
     133        if(result)
     134                usb_deserialize_hub_desriptor(serialized_descriptor,result);
    83135        return result;
    84136}
    85137
    86 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * serialized_descriptor) {
    87         uint8_t * sdescriptor = (uint8_t*) serialized_descriptor;
    88 
    89         if (sdescriptor[1] != USB_DESCTYPE_HUB) {
    90                 usb_log_warning("trying to deserialize wrong descriptor %x\n",sdescriptor[1]);
    91                 return NULL;
    92         }
    93 
    94         usb_hub_descriptor_t * result = usb_new(usb_hub_descriptor_t);
    95        
    96 
    97         result->ports_count = sdescriptor[2];
     138/**
     139 * deserialize descriptor into given pointer
     140 *
     141 * @param serialized_descriptor
     142 * @param descriptor
     143 * @return
     144 */
     145void usb_deserialize_hub_desriptor(
     146void * serialized_descriptor, usb_hub_descriptor_t * descriptor) {
     147        uint8_t * sdescriptor = serialized_descriptor;
     148        descriptor->ports_count = sdescriptor[2];
    98149        /// @fixme handling of endianness??
    99         result->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
    100         result->pwr_on_2_good_time = sdescriptor[5];
    101         result->current_requirement = sdescriptor[6];
    102         size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0)
    103                         ? 1 : 0);
    104         result->devices_removable = (uint8_t*) malloc(var_size);
     150        descriptor->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
     151        descriptor->pwr_on_2_good_time = sdescriptor[5];
     152        descriptor->current_requirement = sdescriptor[6];
     153        size_t var_size = (descriptor->ports_count+7) / 8;
     154        //descriptor->devices_removable = (uint8_t*) malloc(var_size);
    105155
    106156        size_t i;
    107157        for (i = 0; i < var_size; ++i) {
    108                 result->devices_removable[i] = sdescriptor[7 + i];
     158                descriptor->devices_removable[i] = sdescriptor[7 + i];
    109159        }
    110         return result;
    111160}
    112 
    113 
    114161
    115162/**
  • uspace/drv/usbkbd/kbddev.c

    ref354b6 re50cd7f  
    268268static void usb_kbd_set_led(usb_kbd_t *kbd_dev)
    269269{
     270        if (kbd_dev->output_size == 0) {
     271                return;
     272        }
     273
    270274        unsigned i = 0;
    271275       
     
    544548 *                  according to HID Usage Tables.
    545549 * @param count Number of key codes in report (size of the report).
    546  * @param modifiers Bitmap of modifiers (Ctrl, Alt, Shift, GUI).
     550 * @param report_id
    547551 * @param arg User-specified argument. Expects pointer to the keyboard device
    548552 *            structure representing the keyboard.
     
    551555 */
    552556static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
    553     uint8_t modifiers, void *arg)
     557    uint8_t report_id, void *arg)
    554558{
    555559        if (arg == NULL) {
     
    562566        assert(kbd_dev != NULL);
    563567
    564         usb_log_debug("Got keys from parser (report id: %d): %s\n", modifiers,
     568        usb_log_debug("Got keys from parser (report id: %d): %s\n", report_id,
    565569            usb_debug_str_buffer(key_codes, count, 0));
    566570       
     
    763767        usb_hid_report_path_t *path = usb_hid_report_path();
    764768        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
     769       
     770        usb_hid_report_path_set_report_id(path, 0);
     771       
    765772        kbd_dev->key_count = usb_hid_report_input_length(
    766773            kbd_dev->parser, path, USB_HID_PATH_COMPARE_END);
     
    796803       
    797804        kbd_dev->led_output_size = usb_hid_report_output_size(kbd_dev->parser,
    798             kbd_dev->led_path, USB_HID_PATH_COMPARE_END);
     805            kbd_dev->led_path,
     806            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
    799807       
    800808        usb_log_debug("Output report size (in items): %zu\n",
  • uspace/drv/usbkbd/main.c

    ref354b6 re50cd7f  
    3333/**
    3434 * @file
    35  * Main routines of USB HID driver.
     35 * Main routines of USB KBD driver.
    3636 */
    3737
     
    4242
    4343#include <usb/devdrv.h>
     44#include <usb/devpoll.h>
    4445
    4546#include "kbddev.h"
     
    7576 * @sa usb_kbd_fibril(), usb_kbd_repeat_fibril()
    7677 */
    77 static int usbhid_try_add_device(usb_device_t *dev)
     78static int usb_kbd_try_add_device(usb_device_t *dev)
    7879{
    7980        /* Create the function exposed under /dev/devices. */
     
    105106                usb_kbd_free(&kbd_dev);
    106107                return rc;
    107         }       
     108        }
    108109       
    109110        usb_log_debug("USB/HID KBD device structure initialized.\n");
     
    195196 * @retval EREFUSED if the device is not supported.
    196197 */
    197 static int usbhid_add_device(usb_device_t *dev)
     198static int usb_kbd_add_device(usb_device_t *dev)
    198199{
    199         usb_log_debug("usbhid_add_device()\n");
     200        usb_log_debug("usb_kbd_add_device()\n");
    200201       
    201202        if (dev->interface_no < 0) {
    202203                usb_log_warning("Device is not a supported keyboard.\n");
    203                 usb_log_error("Failed to add HID device: endpoint not found."
    204                     "\n");
     204                usb_log_error("Failed to add USB KBD device: endpoint not "
     205                    "found.\n");
    205206                return ENOTSUP;
    206207        }
    207208       
    208         int rc = usbhid_try_add_device(dev);
     209        int rc = usb_kbd_try_add_device(dev);
    209210       
    210211        if (rc != EOK) {
    211212                usb_log_warning("Device is not a supported keyboard.\n");
    212                 usb_log_error("Failed to add HID device: %s.\n",
     213                usb_log_error("Failed to add KBD device: %s.\n",
    213214                    str_error(rc));
    214215                return rc;
     
    224225/* Currently, the framework supports only device adding. Once the framework
    225226 * supports unplug, more callbacks will be added. */
    226 static usb_driver_ops_t usbhid_driver_ops = {
    227         .add_device = usbhid_add_device,
     227static usb_driver_ops_t usb_kbd_driver_ops = {
     228        .add_device = usb_kbd_add_device,
    228229};
    229230
    230231
    231232/* The driver itself. */
    232 static usb_driver_t usbhid_driver = {
     233static usb_driver_t usb_kbd_driver = {
    233234        .name = NAME,
    234         .ops = &usbhid_driver_ops,
     235        .ops = &usb_kbd_driver_ops,
    235236        .endpoints = usb_kbd_endpoints
    236237};
     
    238239/*----------------------------------------------------------------------------*/
    239240
    240 //static driver_ops_t kbd_driver_ops = {
    241 //      .add_device = usbhid_add_device,
    242 //};
    243 
    244 ///*----------------------------------------------------------------------------*/
    245 
    246 //static driver_t kbd_driver = {
    247 //      .name = NAME,
    248 //      .driver_ops = &kbd_driver_ops
    249 //};
    250 
    251 /*----------------------------------------------------------------------------*/
    252 
    253241int main(int argc, char *argv[])
    254242{
    255         printf(NAME ": HelenOS USB HID driver.\n");
     243        printf(NAME ": HelenOS USB KBD driver.\n");
    256244
    257245        usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
    258246
    259         return usb_driver_main(&usbhid_driver);
     247        return usb_driver_main(&usb_kbd_driver);
    260248}
    261249
  • uspace/drv/usbkbd/usbkbd.ma

    ref354b6 re50cd7f  
    1 100 usb&interface&class=HID&subclass=0x01&protocol=0x01
    2 10 usb&interface&class=HID
     110 usb&interface&class=HID&subclass=0x01&protocol=0x01
  • uspace/drv/usbmid/main.c

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

    ref354b6 re50cd7f  
    3636#include "mouse.h"
    3737#include <usb/debug.h>
     38#include <usb/devpoll.h>
    3839#include <errno.h>
    3940#include <str_error.h>
  • uspace/drv/vhc/connhost.c

    ref354b6 re50cd7f  
    257257
    258258static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
    259     size_t max_packet_size,
    260259    void *data, size_t size,
    261260    usbhc_iface_transfer_out_callback_t callback, void *arg)
     
    267266
    268267static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
    269     size_t max_packet_size,
    270268    void *data, size_t size,
    271269    usbhc_iface_transfer_in_callback_t callback, void *arg)
     
    277275
    278276static int control_write(ddf_fun_t *fun, usb_target_t target,
    279     size_t max_packet_size,
    280277    void *setup_packet, size_t setup_packet_size,
    281278    void *data, size_t data_size,
     
    295292
    296293static int control_read(ddf_fun_t *fun, usb_target_t target,
    297     size_t max_packet_size,
    298294    void *setup_packet, size_t setup_packet_size,
    299295    void *data, size_t data_size,
     
    328324}
    329325
    330 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t ignored)
    331 {
    332         usb_address_keeping_reserve_default(&addresses);
    333         return EOK;
    334 }
    335 
    336 static int release_default_address(ddf_fun_t *fun)
    337 {
    338         usb_address_keeping_release_default(&addresses);
    339         return EOK;
    340 }
    341 
    342326static int request_address(ddf_fun_t *fun, usb_speed_t ignored,
    343327    usb_address_t *address)
     
    392376
    393377usbhc_iface_t vhc_iface = {
    394         .reserve_default_address = reserve_default_address,
    395         .release_default_address = release_default_address,
    396378        .request_address = request_address,
    397379        .bind_address = bind_address,
Note: See TracChangeset for help on using the changeset viewer.