Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbhost/src/endpoint.c

    r17873ac7 rf527f58  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
    3  * Copyright (c) 2017 Ondrej Hlavaty <aearsis@eideo.cz>
    43 * All rights reserved.
    54 *
     
    3635
    3736#include <usb/host/endpoint.h>
    38 #include <usb/host/usb_transfer_batch.h>
    39 #include <usb/host/bus.h>
    4037
    4138#include <assert.h>
     39#include <stdlib.h>
    4240#include <atomic.h>
    43 #include <mem.h>
    44 #include <stdlib.h>
    4541
    46 /** Initialize provided endpoint structure.
     42/** Allocate ad initialize endpoint_t structure.
     43 * @param address USB address.
     44 * @param endpoint USB endpoint number.
     45 * @param direction Communication direction.
     46 * @param type USB transfer type.
     47 * @param speed Communication speed.
     48 * @param max_packet_size Maximum size of data packets.
     49 * @param bw Required bandwidth.
     50 * @return Pointer to initialized endpoint_t structure, NULL on failure.
    4751 */
    48 void endpoint_init(endpoint_t *ep, bus_t *bus)
     52endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint,
     53    usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
     54    size_t max_packet_size, unsigned packets, size_t bw,
     55    usb_address_t tt_address, unsigned tt_p)
    4956{
    50         memset(ep, 0, sizeof(endpoint_t));
    51 
    52         ep->bus = bus;
    53         atomic_set(&ep->refcnt, 0);
    54         link_initialize(&ep->link);
    55         fibril_mutex_initialize(&ep->guard);
    56         fibril_condvar_initialize(&ep->avail);
     57        endpoint_t *instance = malloc(sizeof(endpoint_t));
     58        if (instance) {
     59                atomic_set(&instance->refcnt, 0);
     60                instance->address = address;
     61                instance->endpoint = endpoint;
     62                instance->direction = direction;
     63                instance->transfer_type = type;
     64                instance->speed = speed;
     65                instance->max_packet_size = max_packet_size;
     66                instance->packets = packets;
     67                instance->bandwidth = bw;
     68                instance->toggle = 0;
     69                instance->active = false;
     70                instance->tt.address = tt_address;
     71                instance->tt.port = tt_p;
     72                instance->hc_data.data = NULL;
     73                instance->hc_data.toggle_get = NULL;
     74                instance->hc_data.toggle_set = NULL;
     75                link_initialize(&instance->link);
     76                fibril_mutex_initialize(&instance->guard);
     77                fibril_condvar_initialize(&instance->avail);
     78        }
     79        return instance;
    5780}
    5881
    59 void endpoint_add_ref(endpoint_t *ep)
     82/** Properly dispose of endpoint_t structure.
     83 * @param instance endpoint_t structure.
     84 */
     85void endpoint_destroy(endpoint_t *instance)
    6086{
    61         atomic_inc(&ep->refcnt);
     87        assert(instance);
     88        assert(!instance->active);
     89        assert(instance->hc_data.data == NULL);
     90        free(instance);
    6291}
    6392
    64 void endpoint_del_ref(endpoint_t *ep)
     93void endpoint_add_ref(endpoint_t *instance)
    6594{
    66         if (atomic_predec(&ep->refcnt) == 0) {
    67                 if (ep->bus->ops.destroy_endpoint) {
    68                         ep->bus->ops.destroy_endpoint(ep);
    69                 }
    70                 else {
    71                         assert(ep->active_batch == NULL);
     95        atomic_inc(&instance->refcnt);
     96}
    7297
    73                         /* Assume mostly the eps will be allocated by malloc. */
    74                         free(ep);
    75                 }
    76         }
     98void endpoint_del_ref(endpoint_t *instance)
     99{
     100        if (atomic_predec(&instance->refcnt) == 0)
     101                endpoint_destroy(instance);
     102}
     103
     104/** Set device specific data and hooks.
     105 * @param instance endpoint_t structure.
     106 * @param data device specific data.
     107 * @param toggle_get Hook to call when retrieving value of toggle bit.
     108 * @param toggle_set Hook to call when setting the value of toggle bit.
     109 */
     110void endpoint_set_hc_data(endpoint_t *instance,
     111    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
     112{
     113        assert(instance);
     114        fibril_mutex_lock(&instance->guard);
     115        instance->hc_data.data = data;
     116        instance->hc_data.toggle_get = toggle_get;
     117        instance->hc_data.toggle_set = toggle_set;
     118        fibril_mutex_unlock(&instance->guard);
     119}
     120
     121/** Clear device specific data and hooks.
     122 * @param instance endpoint_t structure.
     123 * @note This function does not free memory pointed to by data pointer.
     124 */
     125void endpoint_clear_hc_data(endpoint_t *instance)
     126{
     127        assert(instance);
     128        endpoint_set_hc_data(instance, NULL, NULL, NULL);
    77129}
    78130
    79131/** Mark the endpoint as active and block access for further fibrils.
    80  * @param ep endpoint_t structure.
     132 * @param instance endpoint_t structure.
    81133 */
    82 void endpoint_activate_locked(endpoint_t *ep, usb_transfer_batch_t *batch)
     134void endpoint_use(endpoint_t *instance)
    83135{
    84         assert(ep);
    85         assert(batch);
    86         assert(batch->ep == ep);
    87         assert(fibril_mutex_is_locked(&ep->guard));
    88 
    89         while (ep->active_batch != NULL)
    90                 fibril_condvar_wait(&ep->avail, &ep->guard);
    91         ep->active_batch = batch;
     136        assert(instance);
     137        /* Add reference for active endpoint. */
     138        endpoint_add_ref(instance);
     139        fibril_mutex_lock(&instance->guard);
     140        while (instance->active)
     141                fibril_condvar_wait(&instance->avail, &instance->guard);
     142        instance->active = true;
     143        fibril_mutex_unlock(&instance->guard);
    92144}
    93145
    94146/** Mark the endpoint as inactive and allow access for further fibrils.
    95  * @param ep endpoint_t structure.
     147 * @param instance endpoint_t structure.
    96148 */
    97 void endpoint_deactivate_locked(endpoint_t *ep)
     149void endpoint_release(endpoint_t *instance)
    98150{
    99         assert(ep);
    100         assert(fibril_mutex_is_locked(&ep->guard));
    101 
    102         if (ep->active_batch && ep->active_batch->error == EOK)
    103                 usb_transfer_batch_reset_toggle(ep->active_batch);
    104 
    105         ep->active_batch = NULL;
    106         fibril_condvar_signal(&ep->avail);
     151        assert(instance);
     152        fibril_mutex_lock(&instance->guard);
     153        instance->active = false;
     154        fibril_mutex_unlock(&instance->guard);
     155        fibril_condvar_signal(&instance->avail);
     156        /* Drop reference for active endpoint. */
     157        endpoint_del_ref(instance);
    107158}
    108159
    109 /** Abort an active batch on endpoint, if any.
    110  *
    111  * @param[in] ep endpoint_t structure.
     160/** Get the value of toggle bit.
     161 * @param instance endpoint_t structure.
     162 * @note Will use provided hook.
    112163 */
    113 void endpoint_abort(endpoint_t *ep)
     164int endpoint_toggle_get(endpoint_t *instance)
    114165{
    115         assert(ep);
    116 
    117         fibril_mutex_lock(&ep->guard);
    118         usb_transfer_batch_t *batch = ep->active_batch;
    119         endpoint_deactivate_locked(ep);
    120         fibril_mutex_unlock(&ep->guard);
    121 
    122         if (batch)
    123                 usb_transfer_batch_abort(batch);
     166        assert(instance);
     167        fibril_mutex_lock(&instance->guard);
     168        if (instance->hc_data.toggle_get)
     169                instance->toggle =
     170                    instance->hc_data.toggle_get(instance->hc_data.data);
     171        const int ret = instance->toggle;
     172        fibril_mutex_unlock(&instance->guard);
     173        return ret;
    124174}
    125175
    126 /** Get the value of toggle bit. Either uses the toggle_get op, or just returns
    127  * the value of the toggle.
    128  * @param ep endpoint_t structure.
     176/** Set the value of toggle bit.
     177 * @param instance endpoint_t structure.
     178 * @note Will use provided hook.
    129179 */
    130 int endpoint_toggle_get(endpoint_t *ep)
     180void endpoint_toggle_set(endpoint_t *instance, int toggle)
    131181{
    132         assert(ep);
    133 
    134         return ep->bus->ops.endpoint_get_toggle
    135             ? ep->bus->ops.endpoint_get_toggle(ep)
    136             : ep->toggle;
     182        assert(instance);
     183        assert(toggle == 0 || toggle == 1);
     184        fibril_mutex_lock(&instance->guard);
     185        instance->toggle = toggle;
     186        if (instance->hc_data.toggle_set)
     187                instance->hc_data.toggle_set(instance->hc_data.data, toggle);
     188        fibril_mutex_unlock(&instance->guard);
    137189}
    138 
    139 /** Set the value of toggle bit. Either uses the toggle_set op, or just sets
    140  * the toggle inside.
    141  * @param ep endpoint_t structure.
    142  */
    143 void endpoint_toggle_set(endpoint_t *ep, bool toggle)
    144 {
    145         assert(ep);
    146 
    147         if (ep->bus->ops.endpoint_set_toggle) {
    148                 ep->bus->ops.endpoint_set_toggle(ep, toggle);
    149         }
    150         else {
    151                 ep->toggle = toggle;
    152         }
    153 }
    154 
    155190
    156191/**
Note: See TracChangeset for help on using the changeset viewer.