Changes in / [45bf63c:1737bfb] in mainline


Ignore:
Location:
uspace
Files:
36 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ohci/endpoint_list.c

    r45bf63c r1737bfb  
    7373 * Does not check whether this replaces an existing list.
    7474 */
    75 void endpoint_list_set_next(
    76     const endpoint_list_t *instance, const endpoint_list_t *next)
     75void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
    7776{
    7877        assert(instance);
  • uspace/drv/bus/usb/ohci/endpoint_list.h

    r45bf63c r1737bfb  
    6868
    6969int endpoint_list_init(endpoint_list_t *instance, const char *name);
    70 void endpoint_list_set_next(
    71     const endpoint_list_t *instance, const endpoint_list_t *next);
     70void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next);
    7271void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep);
    7372void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep);
  • uspace/drv/bus/usb/ohci/hc.c

    r45bf63c r1737bfb  
    142142if (ret != EOK) { \
    143143        usb_log_error(message); \
    144         usb_endpoint_manager_remove_ep( \
    145             &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH, \
    146             NULL, NULL);\
     144        usb_endpoint_manager_unregister_ep( \
     145            &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH);\
    147146        usb_device_manager_release( \
    148147            &instance->generic.dev_manager, hub_address); \
     
    151150        int ret = usb_endpoint_manager_add_ep(
    152151            &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH,
    153             USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0, NULL, NULL);
     152            USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0);
    154153        CHECK_RET_UNREG_RETURN(ret,
    155154            "Failed to register root hub control endpoint: %s.\n",
     
    193192        list_initialize(&instance->pending_batches);
    194193
    195         hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
     194        ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
    196195            bandwidth_count_usb11);
     196        CHECK_RET_RETURN(ret, "Failed to initialize generic driver: %s.\n",
     197            str_error(ret));
    197198        instance->generic.private_data = instance;
    198199        instance->generic.schedule = hc_schedule;
    199200        instance->generic.ep_add_hook = ohci_endpoint_init;
    200         instance->generic.ep_remove_hook = ohci_endpoint_fini;
    201201
    202202        ret = hc_init_memory(instance);
     
    221221}
    222222/*----------------------------------------------------------------------------*/
    223 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
    224 {
    225         assert(instance);
    226         assert(ep);
    227 
     223void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep)
     224{
    228225        endpoint_list_t *list = &instance->lists[ep->transfer_type];
    229226        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
    230         assert(list);
    231         assert(ohci_ep);
    232 
    233227        /* Enqueue ep */
    234228        switch (ep->transfer_type) {
     
    253247}
    254248/*----------------------------------------------------------------------------*/
    255 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep)
    256 {
    257         assert(instance);
    258         assert(ep);
    259 
     249void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep)
     250{
    260251        /* Dequeue ep */
    261252        endpoint_list_t *list = &instance->lists[ep->transfer_type];
    262253        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
    263 
    264         assert(list);
    265         assert(ohci_ep);
    266254        switch (ep->transfer_type) {
    267255        case USB_TRANSFER_CONTROL:
  • uspace/drv/bus/usb/ohci/hc.h

    r45bf63c r1737bfb  
    8686static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
    8787
    88 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep);
    89 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep);
     88void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep);
     89void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep);
    9090
    9191void hc_interrupt(hc_t *instance, uint32_t status);
  • uspace/drv/bus/usb/ohci/ohci.c

    r45bf63c r1737bfb  
    8989            &dev_to_ohci(fun->dev)->hc.generic.dev_manager;
    9090
    91         const usb_address_t addr =
    92             usb_device_manager_find_address(manager, handle);
     91        const usb_address_t addr = usb_device_manager_find(manager, handle);
    9392        if (addr < 0) {
    9493                return addr;
  • uspace/drv/bus/usb/ohci/ohci_batch.c

    r45bf63c r1737bfb  
    5959                free(ohci_batch->tds);
    6060        }
    61         usb_transfer_batch_destroy(ohci_batch->usb_batch);
     61        usb_transfer_batch_dispose(ohci_batch->usb_batch);
    6262        free32(ohci_batch->device_buffer);
    6363        free(ohci_batch);
  • uspace/drv/bus/usb/ohci/ohci_endpoint.c

    r45bf63c r1737bfb  
    6262}
    6363/*----------------------------------------------------------------------------*/
     64/** Disposes hcd endpoint structure
     65 *
     66 * @param[in] hcd_ep endpoint structure
     67 */
     68static void ohci_endpoint_fini(endpoint_t *ep)
     69{
     70        ohci_endpoint_t *instance = ep->hc_data.data;
     71        hc_dequeue_endpoint(instance->hcd->private_data, ep);
     72        if (instance) {
     73                free32(instance->ed);
     74                free32(instance->td);
     75                free(instance);
     76        }
     77}
     78/*----------------------------------------------------------------------------*/
    6479/** Creates new hcd endpoint representation.
    6580 *
    6681 * @param[in] ep USBD endpoint structure
    67  * @return Error code.
     82 * @return pointer to a new hcd endpoint structure, NULL on failure.
    6883 */
    6984int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep)
     
    89104        ed_init(ohci_ep->ed, ep, ohci_ep->td);
    90105        endpoint_set_hc_data(
    91             ep, ohci_ep, ohci_ep_toggle_get, ohci_ep_toggle_set);
     106            ep, ohci_ep, ohci_endpoint_fini, ohci_ep_toggle_get, ohci_ep_toggle_set);
     107        ohci_ep->hcd = hcd;
    92108        hc_enqueue_endpoint(hcd->private_data, ep);
    93109        return EOK;
    94 }
    95 /*----------------------------------------------------------------------------*/
    96 /** Disposes hcd endpoint structure
    97  *
    98  * @param[in] hcd driver using this instance.
    99  * @param[in] ep endpoint structure.
    100  */
    101 void ohci_endpoint_fini(hcd_t *hcd, endpoint_t *ep)
    102 {
    103         assert(hcd);
    104         assert(ep);
    105         ohci_endpoint_t *instance = ohci_endpoint_get(ep);
    106         hc_dequeue_endpoint(hcd->private_data, ep);
    107         if (instance) {
    108                 free32(instance->ed);
    109                 free32(instance->td);
    110                 free(instance);
    111         }
    112         endpoint_clear_hc_data(ep);
    113110}
    114111/**
  • uspace/drv/bus/usb/ohci/ohci_endpoint.h

    r45bf63c r1737bfb  
    5151        /** Linked list used by driver software */
    5252        link_t link;
     53        /** Device using this ep */
     54        hcd_t *hcd;
    5355} ohci_endpoint_t;
    5456
    5557int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep);
    56 void ohci_endpoint_fini(hcd_t *hcd, endpoint_t *ep);
    5758
    5859/** Get and convert assigned ohci_endpoint_t structure
     
    6061 * @return Pointer to assigned hcd endpoint structure
    6162 */
    62 static inline ohci_endpoint_t * ohci_endpoint_get(const endpoint_t *ep)
     63static inline ohci_endpoint_t * ohci_endpoint_get(endpoint_t *ep)
    6364{
    6465        assert(ep);
  • uspace/drv/bus/usb/ohci/ohci_regs.h

    r45bf63c r1737bfb  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbohci
     28/** @addtogroup drvusbohcihc
    2929 * @{
    3030 */
  • uspace/drv/bus/usb/ohci/root_hub.c

    r45bf63c r1737bfb  
    235235                usb_transfer_batch_finish_error(request, NULL, 0, EINVAL);
    236236        }
    237         usb_transfer_batch_destroy(request);
     237        usb_transfer_batch_dispose(request);
    238238}
    239239/*----------------------------------------------------------------------------*/
     
    254254                interrupt_request(instance->unfinished_interrupt_transfer,
    255255                    mask, instance->interrupt_mask_size);
    256                 usb_transfer_batch_destroy(
     256                usb_transfer_batch_dispose(
    257257                    instance->unfinished_interrupt_transfer);
    258258                instance->unfinished_interrupt_transfer = NULL;
  • uspace/drv/bus/usb/uhci/hc.c

    r45bf63c r1737bfb  
    192192            "Device registers at %p (%zuB) accessible.\n", io, reg_size);
    193193
    194         ret = hc_init_mem_structures(instance);
    195         CHECK_RET_RETURN(ret,
    196             "Failed to initialize UHCI memory structures: %s.\n",
     194        ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
     195            bandwidth_count_usb11);
     196        CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n",
    197197            str_error(ret));
    198 
    199 #undef CHECK_RET_RETURN
    200 
    201         hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
    202             bandwidth_count_usb11);
    203198
    204199        instance->generic.private_data = instance;
    205200        instance->generic.schedule = hc_schedule;
    206201        instance->generic.ep_add_hook = NULL;
     202
     203#undef CHECK_RET_DEST_FUN_RETURN
     204
     205        ret = hc_init_mem_structures(instance);
     206        if (ret != EOK) {
     207                usb_log_error(
     208                    "Failed to initialize UHCI memory structures: %s.\n",
     209                    str_error(ret));
     210                hcd_destroy(&instance->generic);
     211                return ret;
     212        }
    207213
    208214        hc_init_hw(instance);
  • uspace/drv/bus/usb/uhci/uhci.c

    r45bf63c r1737bfb  
    101101        usb_device_manager_t *manager =
    102102            &dev_to_uhci(fun->dev)->hc.generic.dev_manager;
    103         const usb_address_t addr =
    104             usb_device_manager_find_address(manager, handle);
     103        const usb_address_t addr = usb_device_manager_find(manager, handle);
    105104
    106105        if (addr < 0) {
  • uspace/drv/bus/usb/uhci/uhci_batch.c

    r45bf63c r1737bfb  
    4848{
    4949        if (uhci_batch) {
    50                 usb_transfer_batch_destroy(uhci_batch->usb_batch);
     50                usb_transfer_batch_dispose(uhci_batch->usb_batch);
    5151                free32(uhci_batch->device_buffer);
    5252                free(uhci_batch);
  • uspace/drv/bus/usb/usbflbk/main.c

    r45bf63c r1737bfb  
    7474}
    7575
    76 /** Callback when new device is about to be removed.
    77  *
    78  * @param dev Representation of a generic DDF device.
    79  * @return Error code.
    80  */
    81 static int usbfallback_device_remove(usb_device_t *dev)
    82 {
    83         return EOK;
    84 }
    85 
    8676/** Callback when new device is removed and recognized as gone by DDF.
    8777 *
     
    10393        return EOK;
    10494}
    105 
    10695/** USB fallback driver ops. */
    107 static const usb_driver_ops_t usbfallback_driver_ops = {
     96static usb_driver_ops_t usbfallback_driver_ops = {
    10897        .device_add = usbfallback_device_add,
    109         .device_rem = usbfallback_device_remove,
    11098        .device_gone = usbfallback_device_gone,
    11199};
    112100
    113101/** USB fallback driver. */
    114 static const usb_driver_t usbfallback_driver = {
     102static usb_driver_t usbfallback_driver = {
    115103        .name = NAME,
    116104        .ops = &usbfallback_driver_ops,
  • uspace/drv/bus/usb/usbhid/main.c

    r45bf63c r1737bfb  
    4646#include "usbhid.h"
    4747
     48/*----------------------------------------------------------------------------*/
     49
    4850#define NAME "usbhid"
    4951
     
    6567 *
    6668 * @param dev Device to add.
    67  * @return Error code.
     69 *
     70 * @retval EOK if successful.
     71 * @retval ENOMEM if there
     72 * @return Other error code inherited from one of functions usb_kbd_init(),
     73 *         ddf_fun_bind() and ddf_fun_add_to_class().
    6874 */
    6975static int usb_hid_try_add_device(usb_device_t *dev)
     
    132138        return EOK;
    133139}
     140
    134141/*----------------------------------------------------------------------------*/
    135142/**
     
    139146 *
    140147 * @param dev Structure representing the new device.
    141  * @return Error code.
     148 *
     149 * @retval EOK if successful.
     150 * @retval EREFUSED if the device is not supported.
    142151 */
    143152static int usb_hid_device_add(usb_device_t *dev)
     
    170179        return EOK;
    171180}
    172 /*----------------------------------------------------------------------------*/
    173 /**
    174  * Callback for a device about to be removed from the driver.
     181
     182/*----------------------------------------------------------------------------*/
     183
     184/**
     185 * Callback for removing a device from the driver.
    175186 *
    176187 * @param dev Structure representing the device.
    177  * @return Error code.
    178  */
    179 static int usb_hid_device_rem(usb_device_t *dev)
    180 {
    181         return EOK;
    182 }
    183 /*----------------------------------------------------------------------------*/
    184 /**
    185  * Callback for removing a device from the driver.
    186  *
    187  * @param dev Structure representing the device.
    188  * @return Error code.
     188 *
     189 * @retval EOK if successful.
     190 * @retval EREFUSED if the device is not supported.
    189191 */
    190192static int usb_hid_device_gone(usb_device_t *dev)
     
    196198                if (!tries--) {
    197199                        usb_log_error("Can't remove hub, still running.\n");
    198                         return EBUSY;
     200                        return EINPROGRESS;
    199201                }
    200202        }
     
    205207        return EOK;
    206208}
    207 /*----------------------------------------------------------------------------*/
     209
    208210/** USB generic driver callbacks */
    209 static const usb_driver_ops_t usb_hid_driver_ops = {
     211static usb_driver_ops_t usb_hid_driver_ops = {
    210212        .device_add = usb_hid_device_add,
    211         .device_rem = usb_hid_device_rem,
    212213        .device_gone = usb_hid_device_gone,
    213214};
    214 /*----------------------------------------------------------------------------*/
     215
     216
    215217/** The driver itself. */
    216 static const usb_driver_t usb_hid_driver = {
     218static usb_driver_t usb_hid_driver = {
    217219        .name = NAME,
    218220        .ops = &usb_hid_driver_ops,
    219221        .endpoints = usb_hid_endpoints
    220222};
    221 /*----------------------------------------------------------------------------*/
     223
     224/*----------------------------------------------------------------------------*/
     225
    222226int main(int argc, char *argv[])
    223227{
     
    228232        return usb_driver_main(&usb_hid_driver);
    229233}
     234
    230235/**
    231236 * @}
  • uspace/drv/bus/usb/usbhub/main.c

    r45bf63c r1737bfb  
    4747 * For more information see section 11.15.1 of USB 1.1 specification.
    4848 */
    49 static const usb_endpoint_description_t hub_status_change_endpoint_description =
    50 {
     49static usb_endpoint_description_t hub_status_change_endpoint_description = {
    5150        .transfer_type = USB_TRANSFER_INTERRUPT,
    5251        .direction = USB_DIRECTION_IN,
     
    5756};
    5857
    59 /** USB hub driver operations. */
    60 static const usb_driver_ops_t usb_hub_driver_ops = {
     58/**
     59 * USB hub driver operations
     60 *
     61 * The most important one is device_add, which is set to usb_hub_device_add.
     62 */
     63static usb_driver_ops_t usb_hub_driver_ops = {
    6164        .device_add = usb_hub_device_add,
    62 //      .device_rem = usb_hub_device_remove,
    6365        .device_gone = usb_hub_device_gone,
    6466};
     
    7072};
    7173/** Static usb hub driver information. */
    72 static const usb_driver_t usb_hub_driver = {
     74static usb_driver_t usb_hub_driver = {
    7375        .name = NAME,
    7476        .ops = &usb_hub_driver_ops,
    7577        .endpoints = usb_hub_endpoints
    7678};
     79
    7780
    7881int main(int argc, char *argv[])
  • uspace/drv/bus/usb/usbhub/port.h

    r45bf63c r1737bfb  
    4444/** Information about single port on a hub. */
    4545typedef struct {
    46         /* Port number as reporteed in descriptors. */
    4746        size_t port_number;
    48         /** Device communication pipe. */
    4947        usb_pipe_t *control_pipe;
    5048        /** Mutex needed not only by CV for checking port reset. */
  • uspace/drv/bus/usb/usbhub/usbhub.c

    r45bf63c r1737bfb  
    6868
    6969static int usb_set_first_configuration(usb_device_t *usb_device);
     70static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev);
    7071static int usb_hub_process_hub_specific_info(usb_hub_dev_t *hub_dev);
    7172static void usb_hub_over_current(const usb_hub_dev_t *hub_dev,
     
    7475static void usb_hub_polling_terminated_callback(usb_device_t *device,
    7576    bool was_error, void *data);
    76 
    77 /**
    78  * Initialize hub device driver structure.
     77/**
     78 * Initialize hub device driver fibril
    7979 *
    8080 * Creates hub representation and fibril that periodically checks hub's status.
    8181 * Hub representation is passed to the fibril.
    82  * @param usb_dev generic usb device information
    83  * @return error code
    84  */
    85 int usb_hub_device_add(usb_device_t *usb_dev)
    86 {
    87         assert(usb_dev);
    88         /* Create driver soft-state structure */
    89         usb_hub_dev_t *hub_dev =
    90             usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t));
    91         if (hub_dev == NULL) {
    92                 usb_log_error("Failed to create hub driver structure.\n");
    93                 return ENOMEM;
    94         }
    95         hub_dev->usb_device = usb_dev;
    96         hub_dev->pending_ops_count = 0;
    97         hub_dev->running = false;
    98         fibril_mutex_initialize(&hub_dev->pending_ops_mutex);
    99         fibril_condvar_initialize(&hub_dev->pending_ops_cv);
    100 
    101         /* Create hc connection */
    102         usb_log_debug("Initializing USB wire abstraction.\n");
    103         int opResult = usb_hc_connection_initialize_from_device(
    104             &hub_dev->connection, hub_dev->usb_device->ddf_dev);
    105         if (opResult != EOK) {
    106                 usb_log_error("Could not initialize connection to device: %s\n",
    107                     str_error(opResult));
    108                 return opResult;
    109         }
    110 
    111         /* Set hub's first configuration. (There should be only one) */
    112         opResult = usb_set_first_configuration(usb_dev);
    113         if (opResult != EOK) {
    114                 usb_log_error("Could not set hub configuration: %s\n",
    115                     str_error(opResult));
    116                 return opResult;
    117         }
    118 
    119         /* Get port count and create attached_devices. */
    120         opResult = usb_hub_process_hub_specific_info(hub_dev);
    121         if (opResult != EOK) {
    122                 usb_log_error("Could process hub specific info, %s\n",
    123                     str_error(opResult));
    124                 return opResult;
    125         }
    126 
    127         /* Create hub control function. */
    128         usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");
    129         hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,
    130             fun_exposed, HUB_FNC_NAME);
    131         if (hub_dev->hub_fun == NULL) {
    132                 usb_log_error("Failed to create hub function.\n");
    133                 return ENOMEM;
    134         }
    135 
    136         /* Bind hub control function. */
    137         opResult = ddf_fun_bind(hub_dev->hub_fun);
    138         if (opResult != EOK) {
    139                 usb_log_error("Failed to bind hub function: %s.\n",
    140                    str_error(opResult));
    141                 ddf_fun_destroy(hub_dev->hub_fun);
    142                 return opResult;
    143         }
    144 
    145         /* Start hub operation. */
    146         opResult = usb_device_auto_poll(hub_dev->usb_device, 0,
    147             hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8),
    148             usb_hub_polling_terminated_callback, hub_dev);
    149         if (opResult != EOK) {
    150                 /* Function is already bound */
    151                 ddf_fun_unbind(hub_dev->hub_fun);
    152                 ddf_fun_destroy(hub_dev->hub_fun);
    153                 usb_log_error("Failed to create polling fibril: %s.\n",
    154                     str_error(opResult));
    155                 return opResult;
    156         }
    157         hub_dev->running = true;
    158         usb_log_info("Controlling hub '%s' (%zu ports).\n",
    159             hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);
    160 
    161         return EOK;
    162 }
    163 /*----------------------------------------------------------------------------*/
    164 /**
    165  * Turn off power to all ports.
    166  *
    167  * @param usb_dev generic usb device information
    168  * @return error code
    169  */
    170 int usb_hub_device_remove(usb_device_t *usb_dev)
    171 {
    172         assert(usb_dev);
    173         usb_hub_dev_t *hub_dev = usb_dev->driver_data;
    174         assert(hub_dev);
    175         //TODO: Cascade the call here.
    176         //TODO: Enable after cascading is implemented.
    177         return ENOTSUP;
    178         if (!hub_dev->power_switched) {
    179                 /* That is all we can do. */
    180                 return EOK;
    181         }
    182         int ret = EOK;
    183         usb_log_info("Hub is about to be removed, powering down all ports.\n");
    184         for (size_t port = 0; port < hub_dev->port_count; ++port) {
    185                 usb_log_debug("Powering down port %zu.\n", port);
    186                 int pret = usb_hub_port_clear_feature(
    187                     &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
    188                 if (pret != EOK) {
    189                         usb_log_error("Cannot power down port %zu: %s.\n",
    190                             hub_dev->ports[port].port_number, str_error(pret));
    191                         ret = pret;
    192                 } else {
    193                         if (!hub_dev->per_port_power) {
    194                                 usb_log_debug("Ganged power switching mode, "
    195                                    "one port is enough.\n");
    196                                 break;
    197                         }
    198                 }
    199         }
    200         return ret;
    201 }
    202 /*----------------------------------------------------------------------------*/
    203 /**
    204  * Remove all attached devices
    20582 * @param usb_dev generic usb device information
    20683 * @return error code
     
    244121}
    245122/*----------------------------------------------------------------------------*/
     123/**
     124 * Initialize hub device driver fibril
     125 *
     126 * Creates hub representation and fibril that periodically checks hub's status.
     127 * Hub representation is passed to the fibril.
     128 * @param usb_dev generic usb device information
     129 * @return error code
     130 */
     131int usb_hub_device_add(usb_device_t *usb_dev)
     132{
     133        assert(usb_dev);
     134        /* Create driver soft-state structure */
     135        usb_hub_dev_t *hub_dev = usb_hub_dev_create(usb_dev);
     136        if (hub_dev == NULL) {
     137                usb_log_error("Failed to create hun driver structure.\n");
     138                return ENOMEM;
     139        }
     140
     141        /* Create hc connection */
     142        usb_log_debug("Initializing USB wire abstraction.\n");
     143        int opResult = usb_hc_connection_initialize_from_device(
     144            &hub_dev->connection, hub_dev->usb_device->ddf_dev);
     145        if (opResult != EOK) {
     146                usb_log_error("Could not initialize connection to device: %s\n",
     147                    str_error(opResult));
     148                free(hub_dev);
     149                return opResult;
     150        }
     151
     152        /* Set hub's first configuration. (There should be only one) */
     153        opResult = usb_set_first_configuration(usb_dev);
     154        if (opResult != EOK) {
     155                usb_log_error("Could not set hub configuration: %s\n",
     156                    str_error(opResult));
     157                free(hub_dev);
     158                return opResult;
     159        }
     160
     161        /* Get port count and create attached_devices. */
     162        opResult = usb_hub_process_hub_specific_info(hub_dev);
     163        if (opResult != EOK) {
     164                usb_log_error("Could process hub specific info, %s\n",
     165                    str_error(opResult));
     166                free(hub_dev);
     167                return opResult;
     168        }
     169
     170        usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");
     171        hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,
     172            fun_exposed, HUB_FNC_NAME);
     173        if (hub_dev->hub_fun == NULL) {
     174                usb_log_error("Failed to create hub function.\n");
     175                free(hub_dev);
     176                return ENOMEM;
     177        }
     178
     179        opResult = ddf_fun_bind(hub_dev->hub_fun);
     180        if (opResult != EOK) {
     181                usb_log_error("Failed to bind hub function: %s.\n",
     182                   str_error(opResult));
     183                free(hub_dev);
     184                ddf_fun_destroy(hub_dev->hub_fun);
     185                return opResult;
     186        }
     187
     188        opResult = usb_device_auto_poll(hub_dev->usb_device, 0,
     189            hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8),
     190            usb_hub_polling_terminated_callback, hub_dev);
     191        if (opResult != EOK) {
     192                /* Function is already bound */
     193                ddf_fun_unbind(hub_dev->hub_fun);
     194                ddf_fun_destroy(hub_dev->hub_fun);
     195                free(hub_dev);
     196                usb_log_error("Failed to create polling fibril: %s.\n",
     197                    str_error(opResult));
     198                return opResult;
     199        }
     200        hub_dev->running = true;
     201        usb_log_info("Controlling hub '%s' (%zu ports).\n",
     202            hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);
     203
     204        return EOK;
     205}
     206/*----------------------------------------------------------------------------*/
    246207/** Callback for polling hub for changes.
    247208 *
     
    282243/*----------------------------------------------------------------------------*/
    283244/**
     245 * create usb_hub_dev_t structure
     246 *
     247 * Does only basic copying of known information into new structure.
     248 * @param usb_dev usb device structure
     249 * @return basic usb_hub_dev_t structure
     250 */
     251static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev)
     252{
     253        assert(usb_dev);
     254        usb_hub_dev_t *hub_dev =
     255            usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t));
     256        if (!hub_dev)
     257            return NULL;
     258
     259        hub_dev->usb_device = usb_dev;
     260        hub_dev->ports = NULL;
     261        hub_dev->port_count = 0;
     262        hub_dev->pending_ops_count = 0;
     263        hub_dev->running = false;
     264        fibril_mutex_initialize(&hub_dev->pending_ops_mutex);
     265        fibril_condvar_initialize(&hub_dev->pending_ops_cv);
     266
     267        return hub_dev;
     268}
     269/*----------------------------------------------------------------------------*/
     270/**
    284271 * Load hub-specific information into hub_dev structure and process if needed
    285272 *
     
    324311        }
    325312
    326         hub_dev->power_switched =
     313        const bool is_power_switched =
    327314            !(descriptor.characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);
    328         hub_dev->per_port_power =
    329             descriptor.characteristics & HUB_CHAR_POWER_PER_PORT_FLAG;
    330 
    331         if (!hub_dev->power_switched) {
    332                 usb_log_info(
    333                    "Power switching not supported, ports always powered.\n");
    334                 return EOK;
    335         }
    336 
    337         usb_log_info("Hub port power switching enabled.\n");
    338 
    339         for (size_t port = 0; port < hub_dev->port_count; ++port) {
    340                 usb_log_debug("Powering port %zu.\n", port);
    341                 const int ret = usb_hub_port_set_feature(
    342                     &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
    343 
    344                 if (ret != EOK) {
    345                         usb_log_error("Cannot power on port %zu: %s.\n",
    346                             hub_dev->ports[port].port_number, str_error(ret));
    347                 } else {
    348                         if (!hub_dev->per_port_power) {
    349                                 usb_log_debug("Ganged power switching, "
    350                                     "one port is enough.\n");
    351                                 break;
     315        if (is_power_switched) {
     316                usb_log_debug("Hub power switched\n");
     317                const bool per_port_power = descriptor.characteristics
     318                    & HUB_CHAR_POWER_PER_PORT_FLAG;
     319
     320                for (size_t port = 0; port < hub_dev->port_count; ++port) {
     321                        usb_log_debug("Powering port %zu.\n", port);
     322                        opResult = usb_hub_port_set_feature(
     323                            &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
     324                        if (opResult != EOK) {
     325                                usb_log_error("Cannot power on port %zu: %s.\n",
     326                                    port, str_error(opResult));
     327                        } else {
     328                                if (!per_port_power) {
     329                                        usb_log_debug(
     330                                            "Ganged power switching mode, "
     331                                            "one port is enough.\n");
     332                                        break;
     333                                }
    352334                        }
    353335                }
     336        } else {
     337                usb_log_debug("Power not switched, ports always powered\n");
    354338        }
    355339        return EOK;
     
    418402                usb_log_warning("Detected hub over-current condition, "
    419403                    "all ports should be powered off.");
    420                 return;
    421         }
    422 
    423         /* Ports are always powered. */
    424         if (!hub_dev->power_switched)
    425                 return;
    426 
    427         /* Over-current condition is gone, it is safe to turn the ports on. */
    428         for (size_t port = 0; port < hub_dev->port_count; ++port) {
    429                 const int ret = usb_hub_port_set_feature(
    430                     &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
    431                 if (ret != EOK) {
    432                         usb_log_warning("HUB OVER-CURRENT GONE: Cannot power on"
    433                             " port %zu: %s\n", hub_dev->ports[port].port_number,
    434                             str_error(ret));
    435                 } else {
    436                         if (!hub_dev->per_port_power)
    437                                 return;
    438                 }
    439         }
    440 
     404        } else {
     405                /* Over-current condition is gone, it is safe to turn the
     406                 * ports on. */
     407                for (size_t port = 0; port < hub_dev->port_count; ++port) {
     408                        const int opResult = usb_hub_port_set_feature(
     409                            &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
     410                        // TODO: consider power policy here
     411                        if (opResult != EOK) {
     412                                usb_log_warning(
     413                                    "HUB OVER-CURRENT GONE: Cannot power on "
     414                                    "port %zu;  %s\n",
     415                                    port, str_error(opResult));
     416                        }
     417                }
     418        }
     419        const int opResult = usb_request_clear_feature(
     420            &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,
     421            USB_REQUEST_RECIPIENT_DEVICE,
     422            USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
     423        if (opResult != EOK) {
     424                usb_log_error(
     425                    "Failed to clear hub over-current change flag: %s.\n",
     426                    str_error(opResult));
     427        }
    441428}
    442429/*----------------------------------------------------------------------------*/
     
    474461        if (status & USB_HUB_STATUS_C_OVER_CURRENT) {
    475462                usb_hub_over_current(hub_dev, status);
    476                 /* Ack change in hub OC flag */
    477                 const int ret = usb_request_clear_feature(
    478                     &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,
    479                     USB_REQUEST_RECIPIENT_DEVICE,
    480                     USB_HUB_FEATURE_C_HUB_OVER_CURRENT, 0);
    481                 if (ret != EOK) {
    482                         usb_log_error("Failed to clear hub over-current "
    483                             "change flag: %s.\n", str_error(opResult));
    484                 }
    485463        }
    486464
     
    499477                 * Just ACK the change.
    500478                 */
    501                 const int ret = usb_request_clear_feature(
     479                const int opResult = usb_request_clear_feature(
    502480                    control_pipe, USB_REQUEST_TYPE_CLASS,
    503481                    USB_REQUEST_RECIPIENT_DEVICE,
    504482                    USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
    505483                if (opResult != EOK) {
    506                         usb_log_error("Failed to clear hub power change "
    507                             "flag: %s.\n", str_error(ret));
     484                        usb_log_error(
     485                            "Failed to clear hub power change flag: %s.\n",
     486                            str_error(opResult));
    508487                }
    509488        }
  • uspace/drv/bus/usb/usbhub/usbhub.h

    r45bf63c r1737bfb  
    7777        /** Status indicator */
    7878        bool running;
    79         /** Hub supports port power switching. */
    80         bool power_switched;
    81         /** Each port is switched individually. */
    82         bool per_port_power;
    8379};
    8480
    8581int usb_hub_device_add(usb_device_t *usb_dev);
    86 int usb_hub_device_remove(usb_device_t *usb_dev);
    8782int usb_hub_device_gone(usb_device_t *usb_dev);
    8883
  • uspace/drv/bus/usb/usbmast/main.c

    r45bf63c r1737bfb  
    5555#define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe)
    5656
    57 static const usb_endpoint_description_t bulk_in_ep = {
     57static usb_endpoint_description_t bulk_in_ep = {
    5858        .transfer_type = USB_TRANSFER_BULK,
    5959        .direction = USB_DIRECTION_IN,
     
    6363        .flags = 0
    6464};
    65 static const usb_endpoint_description_t bulk_out_ep = {
     65static usb_endpoint_description_t bulk_out_ep = {
    6666        .transfer_type = USB_TRANSFER_BULK,
    6767        .direction = USB_DIRECTION_OUT,
     
    106106}
    107107
    108 /** Callback when a device is about to be removed.
    109  *
    110  * @param dev Representation of USB device.
    111  * @return Error code.
    112  */
    113 static int usbmast_device_remove(usb_device_t *dev)
    114 {
    115         //TODO: flush buffers, or whatever.
    116         return ENOTSUP;
    117 }
    118 
    119108/** Callback when new device is attached and recognized as a mass storage.
    120109 *
    121  * @param dev Representation of USB device.
     110 * @param dev Representation of a the USB device.
    122111 * @return Error code.
    123112 */
     
    347336
    348337/** USB mass storage driver ops. */
    349 static const usb_driver_ops_t usbmast_driver_ops = {
     338static usb_driver_ops_t usbmast_driver_ops = {
    350339        .device_add = usbmast_device_add,
    351         .device_rem = usbmast_device_remove,
    352340        .device_gone = usbmast_device_gone,
    353341};
    354342
    355343/** USB mass storage driver. */
    356 static const usb_driver_t usbmast_driver = {
     344static usb_driver_t usbmast_driver = {
    357345        .name = NAME,
    358346        .ops = &usbmast_driver_ops,
  • uspace/drv/bus/usb/usbmid/main.c

    r45bf63c r1737bfb  
    6565        return EOK;
    6666}
    67 /*----------------------------------------------------------------------------*/
    68 /** Callback when a MID device is about to be removed from the host.
    69  *
    70  * @param gen_dev Generic DDF device representing the removed device.
    71  * @return Error code.
    72  */
    73 static int usbmid_device_remove(usb_device_t *dev)
    74 {
    75         assert(dev);
    76         int ret = ENOTSUP;
    77         usb_mid_t *usb_mid = dev->driver_data;
    78         assert(usb_mid);
    7967
    80         /* Signal all interface functions */
    81         list_foreach(usb_mid->interface_list, item) {
    82                 usbmid_interface_t *iface = usbmid_interface_from_link(item);
    83 
    84                 usb_log_info("Signaling remove to child for interface "
    85                     "%d (%s).\n", iface->interface_no,
    86                     usb_str_class(iface->interface->interface_class));
    87                 // TODO cascade the call.
    88         }
    89         return ret;
    90 }
    91 /*----------------------------------------------------------------------------*/
    92 /** Callback when a MID device was removed from the host.
    93  *
    94  * @param gen_dev Generic DDF device representing the removed device.
    95  * @return Error code.
    96  */
    9768static int usbmid_device_gone(usb_device_t *dev)
    9869{
     
    11586                list_remove(item);
    11687
    117                 usbmid_interface_t *iface = usbmid_interface_from_link(item);
     88                usbmid_interface_t *iface = list_get_instance(item,
     89                    usbmid_interface_t, link);
    11890
    11991                usb_log_info("Removing child for interface %d (%s).\n",
     
    135107
    136108/** USB MID driver ops. */
    137 static const usb_driver_ops_t mid_driver_ops = {
     109static usb_driver_ops_t mid_driver_ops = {
    138110        .device_add = usbmid_device_add,
    139         .device_rem = usbmid_device_remove,
    140111        .device_gone = usbmid_device_gone,
    141112};
    142113
    143114/** USB MID driver. */
    144 static const usb_driver_t mid_driver = {
     115static usb_driver_t mid_driver = {
    145116        .name = NAME,
    146117        .ops = &mid_driver_ops,
  • uspace/drv/bus/usb/usbmid/usbmid.h

    r45bf63c r1737bfb  
    7171int usbmid_interface_destroy(usbmid_interface_t *mid_iface);
    7272
    73 static inline usbmid_interface_t * usbmid_interface_from_link(link_t *item)
    74 {
    75         return list_get_instance(item, usbmid_interface_t, link);
    76 }
    77 
    7873#endif
    7974/**
  • uspace/drv/bus/usb/vhc/connhost.c

    r45bf63c r1737bfb  
    104104{
    105105        VHC_DATA(vhc, fun);
    106         return usb_device_manager_get_info_by_address(
    107             &vhc->dev_manager, address, handle, NULL);
     106        bool found =
     107            usb_device_manager_find_by_address(&vhc->dev_manager, address, handle);
     108        return found ? EOK : ENOENT;
    108109}
    109110
     
    140141    size_t max_packet_size, unsigned int interval)
    141142{
    142         VHC_DATA(vhc, fun);
    143 
    144         return usb_endpoint_manager_add_ep(&vhc->ep_manager,
    145             address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1, 0,
    146             NULL, NULL);
    147 
     143        /* TODO: Use usb_endpoint_manager_add_ep */
     144        VHC_DATA(vhc, fun);
     145
     146        endpoint_t *ep = endpoint_get(
     147            address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1);
     148        if (ep == NULL) {
     149                return ENOMEM;
     150        }
     151
     152        int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
     153        if (rc != EOK) {
     154                endpoint_destroy(ep);
     155                return rc;
     156        }
     157
     158        return EOK;
    148159}
    149160
     
    161172        VHC_DATA(vhc, fun);
    162173
    163         int rc = usb_endpoint_manager_remove_ep(&vhc->ep_manager,
    164             address, endpoint, direction, NULL, NULL);
     174        int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager,
     175            address, endpoint, direction);
    165176
    166177        return rc;
     
    403414        VHC_DATA(vhc, fun);
    404415
    405         endpoint_t *ep = usb_endpoint_manager_find_ep(&vhc->ep_manager,
    406             target.address, target.endpoint, USB_DIRECTION_IN);
     416        endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
     417            target.address, target.endpoint, USB_DIRECTION_IN, NULL);
    407418        if (ep == NULL) {
    408419                return ENOENT;
     
    445456        VHC_DATA(vhc, fun);
    446457
    447         endpoint_t *ep = usb_endpoint_manager_find_ep(&vhc->ep_manager,
    448             target.address, target.endpoint, USB_DIRECTION_OUT);
     458        endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
     459            target.address, target.endpoint, USB_DIRECTION_OUT, NULL);
    449460        if (ep == NULL) {
    450461                return ENOENT;
     
    507518
    508519        usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
    509         const usb_address_t addr =
    510             usb_device_manager_find_address(&vhc->dev_manager, handle);
     520        usb_address_t addr = usb_device_manager_find(&vhc->dev_manager, handle);
    511521        if (addr < 0) {
    512522                return addr;
  • uspace/lib/usbdev/include/usb/dev/driver.h

    r45bf63c r1737bfb  
    161161} usb_driver_t;
    162162
    163 int usb_driver_main(const usb_driver_t *);
     163int usb_driver_main(usb_driver_t *);
    164164
    165165int usb_device_select_interface(usb_device_t *, uint8_t,
     
    171171    usb_endpoint_mapping_t **, size_t *);
    172172int usb_device_destroy_pipes(const ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
    173 int usb_device_init(usb_device_t *, ddf_dev_t *,
    174     const usb_endpoint_description_t **, const char **);
     173int usb_device_create(ddf_dev_t *, const usb_endpoint_description_t **,
     174    usb_device_t **, const char **);
    175175void usb_device_deinit(usb_device_t *);
    176 
    177176void * usb_device_data_alloc(usb_device_t *, size_t);
    178177
     
    180179int usb_alternate_interfaces_create(const uint8_t *, size_t, int,
    181180    usb_alternate_interfaces_t **);
    182 void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *);
     181
    183182#endif
    184183/**
  • uspace/lib/usbdev/src/altiface.c

    r45bf63c r1737bfb  
    9898        assert(config_descr_size > 0);
    9999
    100         *alternates_ptr = NULL;
    101100        if (interface_number < 0) {
     101                alternates_ptr = NULL;
    102102                return EOK;
    103103        }
     
    105105        usb_alternate_interfaces_t *alternates
    106106            = malloc(sizeof(usb_alternate_interfaces_t));
     107
    107108        if (alternates == NULL) {
    108109                return ENOMEM;
     
    118119        }
    119120
    120         alternates->alternatives = calloc(alternates->alternative_count,
    121             sizeof(usb_alternate_interface_descriptors_t));
     121        alternates->alternatives = malloc(alternates->alternative_count
     122            * sizeof(usb_alternate_interface_descriptors_t));
    122123        if (alternates->alternatives == NULL) {
    123124                free(alternates);
     
    175176}
    176177
    177 void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *alternate)
    178 {
    179         if (!alternate)
    180                 return;
    181         free(alternate->alternatives);
    182         free(alternate);
    183 }
     178
    184179/**
    185180 * @}
  • uspace/lib/usbdev/src/devdrv.c

    r45bf63c r1737bfb  
    6464 * @return Task exit status.
    6565 */
    66 int usb_driver_main(const usb_driver_t *drv)
     66int usb_driver_main(usb_driver_t *drv)
    6767{
    6868        assert(drv != NULL);
     
    140140        assert(driver->ops->device_add);
    141141
    142         usb_device_t *dev = ddf_dev_data_alloc(gen_dev, sizeof(usb_device_t));
    143         if (dev == NULL) {
    144                 usb_log_error("USB device `%s' structure allocation failed.\n",
    145                     gen_dev->name);
    146                 return ENOMEM;
    147         }
     142        int rc;
     143
     144        usb_device_t *dev = NULL;
    148145        const char *err_msg = NULL;
    149         int rc = usb_device_init(dev, gen_dev, driver->endpoints, &err_msg);
    150         if (rc != EOK) {
    151                 usb_log_error("USB device `%s' init failed (%s): %s.\n",
     146        rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg);
     147        if (rc != EOK) {
     148                usb_log_error("USB device `%s' creation failed (%s): %s.\n",
    152149                    gen_dev->name, err_msg, str_error(rc));
    153150                return rc;
    154151        }
     152        gen_dev->driver_data = dev;
    155153
    156154        rc = driver->ops->device_add(dev);
     
    518516
    519517
    520 /** Initialize new instance of USB device.
    521  *
    522  * @param[in] usb_dev Pointer to the new device.
     518/** Create new instance of USB device.
     519 *
    523520 * @param[in] ddf_dev Generic DDF device backing the USB one.
    524521 * @param[in] endpoints NULL terminated array of endpoints (NULL for none).
     522 * @param[out] dev_ptr Where to store pointer to the new device.
    525523 * @param[out] errstr_ptr Where to store description of context
    526524 *      (in case error occurs).
    527525 * @return Error code.
    528526 */
    529 int usb_device_init(usb_device_t *usb_dev, ddf_dev_t *ddf_dev,
    530     const usb_endpoint_description_t **endpoints, const char **errstr_ptr)
    531 {
    532         assert(usb_dev != NULL);
     527int usb_device_create(ddf_dev_t *ddf_dev,
     528    const usb_endpoint_description_t **endpoints,
     529    usb_device_t **dev_ptr, const char **errstr_ptr)
     530{
     531        assert(dev_ptr != NULL);
    533532        assert(ddf_dev != NULL);
    534533
    535         usb_dev->ddf_dev = ddf_dev;
    536         usb_dev->driver_data = NULL;
    537         usb_dev->descriptors.configuration = NULL;
    538         usb_dev->alternate_interfaces = NULL;
    539         usb_dev->pipes_count = 0;
    540         usb_dev->pipes = NULL;
     534        int rc;
     535
     536        usb_device_t *dev = malloc(sizeof(usb_device_t));
     537        if (dev == NULL) {
     538                *errstr_ptr = "structure allocation";
     539                return ENOMEM;
     540        }
     541
     542        // FIXME: proper deallocation in case of errors
     543
     544        dev->ddf_dev = ddf_dev;
     545        dev->driver_data = NULL;
     546        dev->descriptors.configuration = NULL;
     547        dev->alternate_interfaces = NULL;
     548
     549        dev->pipes_count = 0;
     550        dev->pipes = NULL;
    541551
    542552        /* Initialize backing wire and control pipe. */
    543         int rc = init_wire_and_ctrl_pipe(usb_dev, errstr_ptr);
     553        rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);
    544554        if (rc != EOK) {
    545555                return rc;
     
    547557
    548558        /* Get our interface. */
    549         usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev);
     559        dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
    550560
    551561        /* Retrieve standard descriptors. */
    552         rc = usb_device_retrieve_descriptors(&usb_dev->ctrl_pipe,
    553             &usb_dev->descriptors);
    554         if (rc != EOK) {
    555                 /* Nothing allocated, nothing to free. */
     562        rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
     563            &dev->descriptors);
     564        if (rc != EOK) {
    556565                *errstr_ptr = "descriptor retrieval";
    557566                return rc;
    558567        }
    559568
    560         /* Create alternate interfaces. We will silently ignore failure. */
    561         //TODO Why ignore?
    562         usb_alternate_interfaces_create(usb_dev->descriptors.configuration,
    563             usb_dev->descriptors.configuration_size, usb_dev->interface_no,
    564             &usb_dev->alternate_interfaces);
    565 
    566         rc = initialize_other_pipes(endpoints, usb_dev, 0);
    567         if (rc != EOK) {
    568                 /* Full configuration descriptor is allocated. */
    569                 free(usb_dev->descriptors.configuration);
    570                 /* Alternate interfaces may be allocated */
    571                 usb_alternate_interfaces_destroy(usb_dev->alternate_interfaces);
     569        /* Create alternate interfaces. */
     570        rc = usb_alternate_interfaces_create(dev->descriptors.configuration,
     571            dev->descriptors.configuration_size, dev->interface_no,
     572            &dev->alternate_interfaces);
     573        if (rc != EOK) {
     574                /* We will try to silently ignore this. */
     575                dev->alternate_interfaces = NULL;
     576        }
     577
     578        rc = initialize_other_pipes(endpoints, dev, 0);
     579        if (rc != EOK) {
    572580                *errstr_ptr = "pipes initialization";
    573581                return rc;
     
    575583
    576584        *errstr_ptr = NULL;
     585        *dev_ptr = dev;
    577586
    578587        return EOK;
    579588}
    580589
    581 /** Clean instance of a USB device.
     590/** Destroy instance of a USB device.
    582591 *
    583592 * @param dev Device to be de-initialized.
     
    587596void usb_device_deinit(usb_device_t *dev)
    588597{
    589         if (dev) {
    590                 /* Ignore errors and hope for the best. */
    591                 destroy_current_pipes(dev);
    592 
    593                 usb_alternate_interfaces_destroy(dev->alternate_interfaces);
    594                 free(dev->descriptors.configuration);
    595                 free(dev->driver_data);
    596         }
     598        if (dev == NULL) {
     599                return;
     600        }
     601
     602        /* Ignore errors and hope for the best. */
     603        destroy_current_pipes(dev);
     604
     605        if (dev->alternate_interfaces != NULL) {
     606                free(dev->alternate_interfaces->alternatives);
     607        }
     608        free(dev->alternate_interfaces);
     609        free(dev->descriptors.configuration);
     610        free(dev->driver_data);
    597611}
    598612
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    r45bf63c r1737bfb  
    3636#define LIBUSBHOST_HOST_ENDPOINT_H
    3737
     38#include <assert.h>
    3839#include <bool.h>
    3940#include <adt/list.h>
    4041#include <fibril_synch.h>
     42
    4143#include <usb/usb.h>
    4244
    43 /** Host controller side endpoint structure. */
    4445typedef struct endpoint {
    45         /** Part of linked list. */
    46         link_t link;
    47         /** USB address. */
    4846        usb_address_t address;
    49         /** USB endpoint number. */
    5047        usb_endpoint_t endpoint;
    51         /** Communication direction. */
    5248        usb_direction_t direction;
    53         /** USB transfer type. */
    5449        usb_transfer_type_t transfer_type;
    55         /** Communication speed. */
    5650        usb_speed_t speed;
    57         /** Maximum size of data packets. */
    5851        size_t max_packet_size;
    59         /** Necessary bandwidth. */
    60         size_t bandwidth;
    61         /** Value of the toggle bit. */
    6252        unsigned toggle:1;
    63         /** True if there is a batch using this scheduled for this endpoint. */
     53        fibril_mutex_t guard;
     54        fibril_condvar_t avail;
    6455        volatile bool active;
    65         /** Protects resources and active status changes. */
    66         fibril_mutex_t guard;
    67         /** Signals change of active status. */
    68         fibril_condvar_t avail;
    69         /** Optional device specific data. */
     56        void (*destroy_hook)(struct endpoint *);
    7057        struct {
    71                 /** Device specific data. */
    7258                void *data;
    73                 /** Callback to get the value of toggle bit. */
    7459                int (*toggle_get)(void *);
    75                 /** Callback to set the value of toggle bit. */
    7660                void (*toggle_set)(void *, int);
    7761        } hc_data;
    7862} endpoint_t;
    7963
    80 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint,
     64endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint,
    8165    usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
    82     size_t max_packet_size, size_t bw);
     66    size_t max_packet_size);
     67
    8368void endpoint_destroy(endpoint_t *instance);
    8469
    8570void endpoint_set_hc_data(endpoint_t *instance,
    86     void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
     71    void *data, void (*destroy_hook)(endpoint_t *),
     72    int (*toggle_get)(void *), void (*toggle_set)(void *, int));
     73
    8774void endpoint_clear_hc_data(endpoint_t *instance);
    8875
    8976void endpoint_use(endpoint_t *instance);
     77
    9078void endpoint_release(endpoint_t *instance);
    9179
    9280int endpoint_toggle_get(endpoint_t *instance);
     81
    9382void endpoint_toggle_set(endpoint_t *instance, int toggle);
    9483
    95 /** list_get_instance wrapper.
    96  * @param item Pointer to link member.
    97  * @return Pointer to enpoint_t structure.
    98  */
    99 static inline endpoint_t * endpoint_get_instance(link_t *item)
    100 {
    101         return list_get_instance(item, endpoint_t, link);
    102 }
     84void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target);
    10385#endif
    10486/**
  • uspace/lib/usbhost/include/usb/host/hcd.h

    r45bf63c r1737bfb  
    3737
    3838#include <assert.h>
    39 #include <usbhc_iface.h>
    40 
    4139#include <usb/host/usb_device_manager.h>
    4240#include <usb/host/usb_endpoint_manager.h>
    4341#include <usb/host/usb_transfer_batch.h>
     42#include <usbhc_iface.h>
    4443
    4544typedef struct hcd hcd_t;
    4645
    47 /** Generic host controller driver structure. */
    4846struct hcd {
    49         /** Device manager storing handles and addresses. */
    5047        usb_device_manager_t dev_manager;
    51         /** Endpoint manager. */
    5248        usb_endpoint_manager_t ep_manager;
     49        void *private_data;
    5350
    54         /** Device specific driver data. */
    55         void *private_data;
    56         /** Transfer scheduling, implement in device driver. */
    5751        int (*schedule)(hcd_t *, usb_transfer_batch_t *);
    58         /** Hook called upon registering new endpoint. */
    5952        int (*ep_add_hook)(hcd_t *, endpoint_t *);
    60         /** Hook called upon removing of an endpoint. */
    61         void (*ep_remove_hook)(hcd_t *, endpoint_t *);
    6253};
    6354/*----------------------------------------------------------------------------*/
    64 /** Initialize hcd_t structure.
    65  * Initializes device and endpoint managers. Sets data nd hook pointer to NULL.
    66  * @param hcd hcd_t structure to initialize, non-null.
    67  * @param bandwidth Available bandwidth, passed to endpoint manager.
    68  * @param bw_count Bandwidth compute function, passed to endpoint manager.
    69  */
    70 static inline void hcd_init(hcd_t *hcd, size_t bandwidth,
     55static inline int hcd_init(hcd_t *hcd, size_t bandwidth,
    7156    size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t))
    7257{
    7358        assert(hcd);
    7459        usb_device_manager_init(&hcd->dev_manager);
    75         usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count);
    76         hcd->private_data = NULL;
    77         hcd->schedule = NULL;
    78         hcd->ep_add_hook = NULL;
    79         hcd->ep_remove_hook = NULL;
     60        return usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count);
    8061}
    8162/*----------------------------------------------------------------------------*/
    82 /** Check registered endpoints and reset toggle bit if necessary.
    83  * @param hcd hcd_t structure, non-null.
    84  * @param target Control communication target.
    85  * @param setup_data Setup packet of the control communication.
    86  */
    87 static inline void reset_ep_if_need(hcd_t *hcd, usb_target_t target,
    88     const char setup_data[8])
     63static inline void hcd_destroy(hcd_t *hcd)
     64{
     65        usb_endpoint_manager_destroy(&hcd->ep_manager);
     66}
     67/*----------------------------------------------------------------------------*/
     68static inline void reset_ep_if_need(
     69    hcd_t *hcd, usb_target_t target, const char* setup_data)
    8970{
    9071        assert(hcd);
    91         usb_endpoint_manager_reset_eps_if_need(
     72        usb_endpoint_manager_reset_if_need(
    9273            &hcd->ep_manager, target, (const uint8_t *)setup_data);
    9374}
    9475/*----------------------------------------------------------------------------*/
    95 /** Data retrieve wrapper.
    96  * @param fun ddf function, non-null.
    97  * @return pointer cast to hcd_t*.
    98  */
    99 static inline hcd_t * fun_to_hcd(const ddf_fun_t *fun)
     76static inline hcd_t * fun_to_hcd(ddf_fun_t *fun)
    10077{
    10178        assert(fun);
  • uspace/lib/usbhost/include/usb/host/usb_device_manager.h

    r45bf63c r1737bfb  
    4949#define USB_ADDRESS_COUNT (USB11_ADDRESS_MAX + 1)
    5050
     51/** Information about attached USB device. */
     52struct usb_device_info {
     53        usb_speed_t speed;
     54        bool occupied;
     55        devman_handle_t handle;
     56};
     57
    5158/** Host controller device manager.
    52  * You shall not access members directly.
     59 * You shall not access members directly but only using functions below.
    5360 */
    5461typedef struct {
    55         /** Information about attached USB devices. */
    56         struct {
    57                 usb_speed_t speed;      /**< Device speed */
    58                 bool occupied;          /**< The address is in use. */
    59                 devman_handle_t handle; /**< Devman handle of the device. */
    60         } devices[USB_ADDRESS_COUNT];
     62        struct usb_device_info devices[USB_ADDRESS_COUNT];
    6163        fibril_mutex_t guard;
    62         /** The last reserved address */
    6364        usb_address_t last_address;
    6465} usb_device_manager_t;
     
    6970    usb_device_manager_t *instance, usb_speed_t speed);
    7071
    71 int usb_device_manager_bind(usb_device_manager_t *instance,
     72void usb_device_manager_bind(usb_device_manager_t *instance,
    7273    usb_address_t address, devman_handle_t handle);
    7374
    74 int usb_device_manager_release(usb_device_manager_t *instance,
     75void usb_device_manager_release(usb_device_manager_t *instance,
    7576    usb_address_t address);
    7677
    77 usb_address_t usb_device_manager_find_address(usb_device_manager_t *instance,
     78usb_address_t usb_device_manager_find(usb_device_manager_t *instance,
    7879    devman_handle_t handle);
    7980
    80 int usb_device_manager_get_info_by_address(usb_device_manager_t *instance,
    81     usb_address_t address, devman_handle_t *handle, usb_speed_t *speed);
     81bool usb_device_manager_find_by_address(usb_device_manager_t *instance,
     82    usb_address_t address, devman_handle_t *handle);
     83
     84usb_speed_t usb_device_manager_get_speed(usb_device_manager_t *instance,
     85    usb_address_t address);
    8286#endif
    8387/**
  • uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h

    r45bf63c r1737bfb  
    4040#define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H
    4141
    42 #include <adt/list.h>
     42#include <stdlib.h>
     43#include <adt/hash_table.h>
    4344#include <fibril_synch.h>
    4445#include <usb/usb.h>
    45 
    4646#include <usb/host/endpoint.h>
    4747
    48 /** Bytes per second in FULL SPEED */
    49 #define BANDWIDTH_TOTAL_USB11 (12000000 / 8)
    50 /** 90% of total bandwidth is available for periodic transfers */
     48#define BANDWIDTH_TOTAL_USB11 12000000
    5149#define BANDWIDTH_AVAILABLE_USB11 ((BANDWIDTH_TOTAL_USB11 / 10) * 9)
    52 /** 16 addresses per list */
    53 #define ENDPOINT_LIST_COUNT 8
    5450
    55 /** Endpoint management structure */
    5651typedef struct usb_endpoint_manager {
    57         /** Store endpoint_t instances */
    58         list_t endpoint_lists[ENDPOINT_LIST_COUNT];
    59         /** Prevents races accessing lists */
     52        hash_table_t ep_table;
    6053        fibril_mutex_t guard;
    61         /** Size of the bandwidth pool */
    6254        size_t free_bw;
    63         /** Use this function to count bw required by EP */
    6455        size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t);
    6556} usb_endpoint_manager_t;
     
    7263    size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t));
    7364
    74 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance,
    75     usb_target_t target, const uint8_t data[8]);
     65void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance);
    7666
    77 int usb_endpoint_manager_register_ep(
    78     usb_endpoint_manager_t *instance, endpoint_t *ep, size_t data_size);
    79 int usb_endpoint_manager_unregister_ep(
    80     usb_endpoint_manager_t *instance, endpoint_t *ep);
    81 endpoint_t * usb_endpoint_manager_find_ep(usb_endpoint_manager_t *instance,
     67int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance,
     68    endpoint_t *ep, size_t data_size);
     69
     70int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance,
    8271    usb_address_t address, usb_endpoint_t ep, usb_direction_t direction);
    8372
    84 int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
     73endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance,
     74    usb_address_t address, usb_endpoint_t ep, usb_direction_t direction,
     75    size_t *bw);
     76
     77void usb_endpoint_manager_reset_if_need(
     78    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
     79
     80/** Wrapper combining allocation and insertion */
     81static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
    8582    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
    8683    usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size,
    87     size_t data_size, int (*callback)(endpoint_t *, void *), void *arg);
     84    size_t data_size)
     85{
     86        endpoint_t *ep = endpoint_get(
     87            address, endpoint, direction, type, speed, max_packet_size);
     88        if (!ep)
     89                return ENOMEM;
    8890
    89 int usb_endpoint_manager_remove_ep(usb_endpoint_manager_t *instance,
    90     usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
    91     void (*callback)(endpoint_t *, void *), void *arg);
     91        const int ret =
     92            usb_endpoint_manager_register_ep(instance, ep, data_size);
     93        if (ret != EOK) {
     94                endpoint_destroy(ep);
     95        }
     96        return ret;
     97}
    9298#endif
    9399/**
    94100 * @}
    95101 */
     102
  • uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h

    r45bf63c r1737bfb  
    4343#define USB_SETUP_PACKET_SIZE 8
    4444
     45typedef struct usb_transfer_batch usb_transfer_batch_t;
    4546/** Structure stores additional data needed for communication with EP */
    46 typedef struct usb_transfer_batch {
     47struct usb_transfer_batch {
    4748        /** Endpoint used for communication */
    4849        endpoint_t *ep;
     
    7677        /** Callback to properly remove driver data during destruction */
    7778        void (*private_data_dtor)(void *p_data);
    78 } usb_transfer_batch_t;
     79};
    7980
    8081/** Printf formatting string for dumping usb_transfer_batch_t. */
     
    9293
    9394
    94 usb_transfer_batch_t * usb_transfer_batch_create(
     95usb_transfer_batch_t * usb_transfer_batch_get(
    9596    endpoint_t *ep,
    9697    char *buffer,
     
    104105    void (*private_data_dtor)(void *p_data)
    105106);
    106 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance);
    107107
    108 void usb_transfer_batch_finish(const usb_transfer_batch_t *instance,
     108void usb_transfer_batch_finish(usb_transfer_batch_t *instance,
    109109    const void* data, size_t size);
     110void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
     111void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
     112void usb_transfer_batch_dispose(usb_transfer_batch_t *instance);
     113
     114/** Helper function, calls callback and correctly destroys batch structure.
     115 *
     116 * @param[in] instance Batch structure to use.
     117 */
     118static inline void usb_transfer_batch_call_in_and_dispose(
     119    usb_transfer_batch_t *instance)
     120{
     121        assert(instance);
     122        usb_transfer_batch_call_in(instance);
     123        usb_transfer_batch_dispose(instance);
     124}
    110125/*----------------------------------------------------------------------------*/
    111 /** Override error value and finishes transfer.
     126/** Helper function calls callback and correctly destroys batch structure.
     127 *
     128 * @param[in] instance Batch structure to use.
     129 */
     130static inline void usb_transfer_batch_call_out_and_dispose(
     131    usb_transfer_batch_t *instance)
     132{
     133        assert(instance);
     134        usb_transfer_batch_call_out(instance);
     135        usb_transfer_batch_dispose(instance);
     136}
     137/*----------------------------------------------------------------------------*/
     138/** Helper function, sets error value and finishes transfer.
    112139 *
    113140 * @param[in] instance Batch structure to use.
     
    124151}
    125152/*----------------------------------------------------------------------------*/
    126 /** Determine batch direction based on the callbacks present
    127  * @param[in] instance Batch structure to use, non-null.
     153/** Helper function, determines batch direction absed on the present callbacks
     154 * @param[in] instance Batch structure to use.
    128155 * @return USB_DIRECTION_IN, or USB_DIRECTION_OUT.
    129156 */
  • uspace/lib/usbhost/src/endpoint.c

    r45bf63c r1737bfb  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup libusbhost
     28
     29/** @addtogroup drvusbuhcihc
    2930 * @{
    3031 */
     
    3839#include <usb/host/endpoint.h>
    3940
    40 /** Allocate ad initialize endpoint_t structure.
    41  * @param address USB address.
    42  * @param endpoint USB endpoint number.
    43  * @param direction Communication direction.
    44  * @param type USB transfer type.
    45  * @param speed Communication speed.
    46  * @param max_packet_size Maximum size of data packets.
    47  * @param bw Required bandwidth.
    48  * @return Pointer to initialized endpoint_t structure, NULL on failure.
    49  */
    50 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint,
     41endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint,
    5142    usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
    52     size_t max_packet_size, size_t bw)
     43    size_t max_packet_size)
    5344{
    5445        endpoint_t *instance = malloc(sizeof(endpoint_t));
     
    6051                instance->speed = speed;
    6152                instance->max_packet_size = max_packet_size;
    62                 instance->bandwidth = bw;
    6353                instance->toggle = 0;
    6454                instance->active = false;
     55                instance->destroy_hook = NULL;
    6556                instance->hc_data.data = NULL;
    6657                instance->hc_data.toggle_get = NULL;
    6758                instance->hc_data.toggle_set = NULL;
    68                 link_initialize(&instance->link);
    6959                fibril_mutex_initialize(&instance->guard);
    7060                fibril_condvar_initialize(&instance->avail);
     61                endpoint_clear_hc_data(instance);
    7162        }
    7263        return instance;
    7364}
    7465/*----------------------------------------------------------------------------*/
    75 /** Properly dispose of endpoint_t structure.
    76  * @param instance endpoint_t structure.
    77  */
    7866void endpoint_destroy(endpoint_t *instance)
    7967{
    8068        assert(instance);
    81         //TODO: Do something about waiting fibrils.
    8269        assert(!instance->active);
    83         assert(instance->hc_data.data == NULL);
     70        if (instance->hc_data.data) {
     71                assert(instance->destroy_hook);
     72                instance->destroy_hook(instance);
     73        }
    8474        free(instance);
    8575}
    8676/*----------------------------------------------------------------------------*/
    87 /** Set device specific data and hooks.
    88  * @param instance endpoint_t structure.
    89  * @param data device specific data.
    90  * @param toggle_get Hook to call when retrieving value of toggle bit.
    91  * @param toggle_set Hook to call when setting the value of toggle bit.
    92  */
    9377void endpoint_set_hc_data(endpoint_t *instance,
    94     void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
     78    void *data, void (*destroy_hook)(endpoint_t *),
     79    int (*toggle_get)(void *), void (*toggle_set)(void *, int))
    9580{
    9681        assert(instance);
    97         fibril_mutex_lock(&instance->guard);
     82        instance->destroy_hook = destroy_hook;
    9883        instance->hc_data.data = data;
    9984        instance->hc_data.toggle_get = toggle_get;
    10085        instance->hc_data.toggle_set = toggle_set;
    101         fibril_mutex_unlock(&instance->guard);
    10286}
    10387/*----------------------------------------------------------------------------*/
    104 /** Clear device specific data and hooks.
    105  * @param instance endpoint_t structure.
    106  * @note This function does not free memory pointed to by data pointer.
    107  */
    10888void endpoint_clear_hc_data(endpoint_t *instance)
    10989{
    11090        assert(instance);
    111         fibril_mutex_lock(&instance->guard);
     91        instance->destroy_hook = NULL;
    11292        instance->hc_data.data = NULL;
    11393        instance->hc_data.toggle_get = NULL;
    11494        instance->hc_data.toggle_set = NULL;
    115         fibril_mutex_unlock(&instance->guard);
    11695}
    11796/*----------------------------------------------------------------------------*/
    118 /** Mark the endpoint as active and block access for further fibrils.
    119  * @param instance endpoint_t structure.
    120  */
    12197void endpoint_use(endpoint_t *instance)
    12298{
     
    129105}
    130106/*----------------------------------------------------------------------------*/
    131 /** Mark the endpoint as inactive and allow access for further fibrils.
    132  * @param instance endpoint_t structure.
    133  */
    134107void endpoint_release(endpoint_t *instance)
    135108{
     
    141114}
    142115/*----------------------------------------------------------------------------*/
    143 /** Get the value of toggle bit.
    144  * @param instance endpoint_t structure.
    145  * @note Will use provided hook.
    146  */
    147116int endpoint_toggle_get(endpoint_t *instance)
    148117{
    149118        assert(instance);
    150         fibril_mutex_lock(&instance->guard);
    151119        if (instance->hc_data.toggle_get)
    152120                instance->toggle =
    153121                    instance->hc_data.toggle_get(instance->hc_data.data);
    154         const int ret = instance->toggle;
    155         fibril_mutex_unlock(&instance->guard);
    156         return ret;
     122        return (int)instance->toggle;
    157123}
    158124/*----------------------------------------------------------------------------*/
    159 /** Set the value of toggle bit.
    160  * @param instance endpoint_t structure.
    161  * @note Will use provided hook.
    162  */
    163125void endpoint_toggle_set(endpoint_t *instance, int toggle)
    164126{
    165127        assert(instance);
    166128        assert(toggle == 0 || toggle == 1);
    167         fibril_mutex_lock(&instance->guard);
    168         instance->toggle = toggle;
    169129        if (instance->hc_data.toggle_set)
    170130                instance->hc_data.toggle_set(instance->hc_data.data, toggle);
    171         fibril_mutex_unlock(&instance->guard);
     131        instance->toggle = toggle;
     132}
     133/*----------------------------------------------------------------------------*/
     134void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target)
     135{
     136        assert(instance);
     137        if (instance->address == target.address &&
     138            (instance->endpoint == target.endpoint || target.endpoint == 0))
     139                endpoint_toggle_set(instance, 0);
    172140}
    173141/**
  • uspace/lib/usbhost/src/iface.c

    r45bf63c r1737bfb  
    4949        assert(hcd);
    5050
    51         endpoint_t *ep = usb_endpoint_manager_find_ep(&hcd->ep_manager,
    52             target.address, target.endpoint, direction);
     51        int ret;
     52
     53        size_t res_bw;
     54        endpoint_t *ep = usb_endpoint_manager_get_ep(&hcd->ep_manager,
     55            target.address, target.endpoint, direction, &res_bw);
    5356        if (ep == NULL) {
    5457                usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
     
    6265        const size_t bw = bandwidth_count_usb11(
    6366            ep->speed, ep->transfer_type, size, ep->max_packet_size);
    64         /* Check if we have enough bandwidth reserved */
    65         if (ep->bandwidth < bw) {
     67        if (res_bw < bw) {
    6668                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
    6769                    "but only %zu is reserved.\n",
    68                     ep->address, ep->endpoint, name, bw, ep->bandwidth);
     70                    target.address, target.endpoint, name, bw, res_bw);
    6971                return ENOSPC;
    7072        }
     
    7678        /* No private data and no private data dtor */
    7779        usb_transfer_batch_t *batch =
    78             usb_transfer_batch_create(ep, data, size, setup_data,
     80            usb_transfer_batch_get(ep, data, size, setup_data,
    7981            in, out, arg, fun, NULL, NULL);
    8082        if (!batch) {
     
    8284        }
    8385
    84         const int ret = hcd->schedule(hcd, batch);
     86        ret = hcd->schedule(hcd, batch);
    8587        if (ret != EOK)
    86                 usb_transfer_batch_destroy(batch);
     88                usb_transfer_batch_dispose(batch);
    8789
    8890        return ret;
     
    128130
    129131        usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
    130         return usb_device_manager_bind(&hcd->dev_manager, address, handle);
     132        usb_device_manager_bind(&hcd->dev_manager, address, handle);
     133        return EOK;
    131134}
    132135/*----------------------------------------------------------------------------*/
     
    144147        hcd_t *hcd = fun_to_hcd(fun);
    145148        assert(hcd);
    146         return usb_device_manager_get_info_by_address(
    147             &hcd->dev_manager, address, handle, NULL);
     149        const bool found =
     150            usb_device_manager_find_by_address(&hcd->dev_manager, address, handle);
     151        return found ? EOK : ENOENT;
    148152}
    149153/*----------------------------------------------------------------------------*/
     
    162166        usb_device_manager_release(&hcd->dev_manager, address);
    163167        return EOK;
    164 }
    165 /*----------------------------------------------------------------------------*/
    166 static int register_helper(endpoint_t *ep, void *arg)
    167 {
    168         hcd_t *hcd = arg;
    169         assert(ep);
    170         assert(hcd);
    171         if (hcd->ep_add_hook)
    172                 return hcd->ep_add_hook(hcd, ep);
    173         return EOK;
    174 }
    175 /*----------------------------------------------------------------------------*/
    176 static void unregister_helper(endpoint_t *ep, void *arg)
    177 {
    178         hcd_t *hcd = arg;
    179         assert(ep);
    180         assert(hcd);
    181         if (hcd->ep_remove_hook)
    182                 hcd->ep_remove_hook(hcd, ep);
    183168}
    184169/*----------------------------------------------------------------------------*/
     
    195180        /* Default address is not bound or registered,
    196181         * thus it does not provide speed info. */
    197         usb_speed_t speed = ep_speed;
    198         /* NOTE The function will return EINVAL and won't
    199          * touch speed variable for default address */
    200         usb_device_manager_get_info_by_address(
    201             &hcd->dev_manager, address, NULL, &speed);
     182        const usb_speed_t speed = (address == 0) ? ep_speed :
     183            usb_device_manager_get_speed(&hcd->dev_manager, address);
    202184
    203185        usb_log_debug("Register endpoint %d:%d %s-%s %s %zuB %ums.\n",
     
    206188            max_packet_size, interval);
    207189
    208         return usb_endpoint_manager_add_ep(&hcd->ep_manager, address, endpoint,
    209             direction, transfer_type, speed, max_packet_size, size,
    210             register_helper, hcd);
     190        endpoint_t *ep = endpoint_get(
     191            address, endpoint, direction, transfer_type, speed, max_packet_size);
     192        if (!ep)
     193                return ENOMEM;
     194        int ret = EOK;
     195
     196        if (hcd->ep_add_hook) {
     197                ret = hcd->ep_add_hook(hcd, ep);
     198        }
     199        if (ret != EOK) {
     200                endpoint_destroy(ep);
     201                return ret;
     202        }
     203
     204        ret = usb_endpoint_manager_register_ep(&hcd->ep_manager, ep, size);
     205        if (ret != EOK) {
     206                endpoint_destroy(ep);
     207        }
     208        return ret;
    211209}
    212210/*----------------------------------------------------------------------------*/
     
    220218        usb_log_debug("Unregister endpoint %d:%d %s.\n",
    221219            address, endpoint, usb_str_direction(direction));
    222         return usb_endpoint_manager_remove_ep(&hcd->ep_manager, address,
    223             endpoint, direction, unregister_helper, hcd);
     220        return usb_endpoint_manager_unregister_ep(&hcd->ep_manager, address,
     221            endpoint, direction);
    224222}
    225223/*----------------------------------------------------------------------------*/
  • uspace/lib/usbhost/src/usb_device_manager.c

    r45bf63c r1737bfb  
    3838#include <usb/host/usb_device_manager.h>
    3939
     40/*----------------------------------------------------------------------------*/
    4041/** Initialize device manager structure.
    4142 *
     
    4748{
    4849        assert(instance);
    49         for (unsigned i = 0; i < USB_ADDRESS_COUNT; ++i) {
     50        unsigned i = 0;
     51        for (; i < USB_ADDRESS_COUNT; ++i) {
    5052                instance->devices[i].occupied = false;
    5153                instance->devices[i].handle = 0;
     
    7577                ++new_address;
    7678                if (new_address > USB11_ADDRESS_MAX)
    77                         new_address = 1; // NOTE it should be safe to put 0 here
    78                                          // TODO Use mod
     79                        new_address = 1;
    7980                if (new_address == instance->last_address) {
    8081                        fibril_mutex_unlock(&instance->guard);
     
    8586        assert(new_address != USB_ADDRESS_DEFAULT);
    8687        assert(instance->devices[new_address].occupied == false);
    87         assert(instance->devices[new_address].handle == 0);
    8888
    8989        instance->devices[new_address].occupied = true;
     
    100100 * @param[in] address Device address
    101101 * @param[in] handle Devman handle of the device.
    102  * @return Error code.
    103  */
    104 int usb_device_manager_bind(usb_device_manager_t *instance,
     102 */
     103void usb_device_manager_bind(usb_device_manager_t *instance,
    105104    usb_address_t address, devman_handle_t handle)
    106105{
    107         if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) {
    108                 return EINVAL;
    109         }
    110         assert(instance);
    111 
    112         fibril_mutex_lock(&instance->guard);
    113         /* Not reserved */
    114         if (!instance->devices[address].occupied) {
    115                 fibril_mutex_unlock(&instance->guard);
    116                 return ENOENT;
    117         }
    118         /* Already bound */
    119         if (instance->devices[address].handle != 0) {
    120                 fibril_mutex_unlock(&instance->guard);
    121                 return EEXISTS;
    122         }
     106        assert(instance);
     107        fibril_mutex_lock(&instance->guard);
     108
     109        assert(address > 0);
     110        assert(address <= USB11_ADDRESS_MAX);
     111        assert(instance->devices[address].occupied);
     112
    123113        instance->devices[address].handle = handle;
    124114        fibril_mutex_unlock(&instance->guard);
    125         return EOK;
    126115}
    127116/*----------------------------------------------------------------------------*/
     
    130119 * @param[in] instance Device manager structure to use.
    131120 * @param[in] address Device address
    132  * @return Error code.
    133  */
    134 int usb_device_manager_release(
     121 */
     122void usb_device_manager_release(
    135123    usb_device_manager_t *instance, usb_address_t address)
    136124{
    137         if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) {
    138                 return EINVAL;
    139         }
    140         assert(instance);
    141 
    142         fibril_mutex_lock(&instance->guard);
    143         if (!instance->devices[address].occupied) {
    144                 fibril_mutex_unlock(&instance->guard);
    145                 return ENOENT;
    146         }
     125        assert(instance);
     126        assert(address > 0);
     127        assert(address <= USB11_ADDRESS_MAX);
     128
     129        fibril_mutex_lock(&instance->guard);
     130        assert(instance->devices[address].occupied);
    147131
    148132        instance->devices[address].occupied = false;
    149         instance->devices[address].handle = 0;
    150         fibril_mutex_unlock(&instance->guard);
    151         return EOK;
     133        fibril_mutex_unlock(&instance->guard);
    152134}
    153135/*----------------------------------------------------------------------------*/
     
    158140 * @return USB Address, or error code.
    159141 */
    160 usb_address_t usb_device_manager_find_address(
     142usb_address_t usb_device_manager_find(
    161143    usb_device_manager_t *instance, devman_handle_t handle)
    162144{
    163145        assert(instance);
    164146        fibril_mutex_lock(&instance->guard);
    165         for (usb_address_t address = 1; address <= USB11_ADDRESS_MAX; ++address)
    166         {
     147        usb_address_t address = 1;
     148        while (address <= USB11_ADDRESS_MAX) {
    167149                if (instance->devices[address].handle == handle) {
    168150                        assert(instance->devices[address].occupied);
     
    170152                        return address;
    171153                }
     154                ++address;
    172155        }
    173156        fibril_mutex_unlock(&instance->guard);
    174157        return ENOENT;
    175158}
    176 /*----------------------------------------------------------------------------*/
    177 /** Find devman handle and speed assigned to USB address.
    178  * Intentionally refuse to work on default address.
     159
     160/** Find devman handle assigned to USB address.
     161 * Intentionally refuse to find handle of default address.
    179162 *
    180163 * @param[in] instance Device manager structure to use.
    181164 * @param[in] address Address the caller wants to find.
    182165 * @param[out] handle Where to store found handle.
    183  * @param[out] speed Assigned speed.
    184  * @return Error code.
    185  */
    186 int usb_device_manager_get_info_by_address(usb_device_manager_t *instance,
    187     usb_address_t address, devman_handle_t *handle, usb_speed_t *speed)
    188 {
    189         assert(instance);
     166 * @return Whether such address is currently occupied.
     167 */
     168bool usb_device_manager_find_by_address(usb_device_manager_t *instance,
     169    usb_address_t address, devman_handle_t *handle)
     170{
     171        assert(instance);
     172        fibril_mutex_lock(&instance->guard);
    190173        if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) {
    191                 return EINVAL;
    192         }
    193 
    194         fibril_mutex_lock(&instance->guard);
     174                fibril_mutex_unlock(&instance->guard);
     175                return false;
     176        }
    195177        if (!instance->devices[address].occupied) {
    196178                fibril_mutex_unlock(&instance->guard);
    197                 return ENOENT;
     179                return false;
    198180        }
    199181
     
    201183                *handle = instance->devices[address].handle;
    202184        }
    203         if (speed != NULL) {
    204                 *speed = instance->devices[address].speed;
    205         }
    206 
    207         fibril_mutex_unlock(&instance->guard);
    208         return EOK;
     185
     186        fibril_mutex_unlock(&instance->guard);
     187        return true;
     188}
     189
     190/*----------------------------------------------------------------------------*/
     191/** Get speed associated with the address
     192 *
     193 * @param[in] instance Device manager structure to use.
     194 * @param[in] address Address of the device.
     195 * @return USB speed.
     196 */
     197usb_speed_t usb_device_manager_get_speed(
     198    usb_device_manager_t *instance, usb_address_t address)
     199{
     200        assert(instance);
     201        assert(address >= 0);
     202        assert(address <= USB11_ADDRESS_MAX);
     203
     204        return instance->devices[address].speed;
    209205}
    210206/**
  • uspace/lib/usbhost/src/usb_endpoint_manager.c

    r45bf63c r1737bfb  
    3434#include <usb/host/usb_endpoint_manager.h>
    3535
    36 /** Endpoint compare helper function.
    37  *
    38  * USB_DIRECTION_BOTH matches both IN and OUT.
    39  * @param ep Endpoint to compare, non-null.
    40  * @param address Tested address.
    41  * @param endpoint Tested endpoint number.
    42  * @param direction Tested direction.
    43  * @return True if ep can be used to communicate with given device,
    44  * false otherwise.
    45  */
    46 static inline bool ep_match(const endpoint_t *ep,
    47     usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
    48 {
    49         assert(ep);
    50         return
    51             ((direction == ep->direction)
    52                 || (ep->direction == USB_DIRECTION_BOTH)
    53                 || (direction == USB_DIRECTION_BOTH))
    54             && (endpoint == ep->endpoint)
    55             && (address == ep->address);
    56 }
    57 /*----------------------------------------------------------------------------*/
    58 /** Get list that holds endpints for given address.
    59  * @param instance usb_endpoint_manager structure, non-null.
    60  * @param addr USB address, must be >= 0.
    61  * @return Pointer to the appropriate list.
    62  */
    63 static list_t * get_list(usb_endpoint_manager_t *instance, usb_address_t addr)
    64 {
    65         assert(instance);
    66         assert(addr >= 0);
    67         return &instance->endpoint_lists[addr % ENDPOINT_LIST_COUNT];
    68 }
    69 /*----------------------------------------------------------------------------*/
    70 /** Internal search function, works on locked structure.
    71  * @param instance usb_endpoint_manager structure, non-null.
    72  * @param address USB address, must be valid.
    73  * @param endpoint USB endpoint number.
    74  * @param direction Communication direction.
    75  * @return Pointer to endpoint_t structure representing given communication
    76  * target, NULL if there is no such endpoint registered.
    77  */
    78 static endpoint_t * find_locked(usb_endpoint_manager_t *instance,
    79     usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
    80 {
    81         assert(instance);
    82         assert(fibril_mutex_is_locked(&instance->guard));
    83         if (address < 0)
    84                 return NULL;
    85         list_foreach(*get_list(instance, address), iterator) {
    86                 endpoint_t *ep = endpoint_get_instance(iterator);
    87                 if (ep_match(ep, address, endpoint, direction))
    88                         return ep;
    89         }
    90         return NULL;
    91 }
    92 /*----------------------------------------------------------------------------*/
    93 /** Calculate bandwidth that needs to be reserved for communication with EP.
    94  * Calculation follows USB 1.1 specification.
    95  * @param speed Device's speed.
    96  * @param type Type of the transfer.
    97  * @param size Number of byte to transfer.
    98  * @param max_packet_size Maximum bytes in one packet.
    99  */
     36#define BUCKET_COUNT 7
     37
     38#define MAX_KEYS (3)
     39typedef struct {
     40        link_t link;
     41        size_t bw;
     42        endpoint_t *ep;
     43} node_t;
     44/*----------------------------------------------------------------------------*/
     45static hash_index_t node_hash(unsigned long key[])
     46{
     47        /* USB endpoints use 4 bits, thus ((key[0] << 4) | key[1])
     48         * produces unique value for every address.endpoint pair */
     49        return ((key[0] << 4) | key[1]) % BUCKET_COUNT;
     50}
     51/*----------------------------------------------------------------------------*/
     52static int node_compare(unsigned long key[], hash_count_t keys, link_t *item)
     53{
     54        assert(item);
     55        node_t *node = hash_table_get_instance(item, node_t, link);
     56        assert(node);
     57        assert(node->ep);
     58        bool match = true;
     59        switch (keys) {
     60        case 3:
     61                match = match &&
     62                    ((key[2] == node->ep->direction)
     63                    || (node->ep->direction == USB_DIRECTION_BOTH));
     64        case 2:
     65                match = match && (key[1] == (unsigned long)node->ep->endpoint);
     66        case 1:
     67                match = match && (key[0] == (unsigned long)node->ep->address);
     68                break;
     69        default:
     70                match = false;
     71        }
     72        return match;
     73}
     74/*----------------------------------------------------------------------------*/
     75static void node_remove(link_t *item)
     76{
     77        assert(item);
     78        node_t *node = hash_table_get_instance(item, node_t, link);
     79        endpoint_destroy(node->ep);
     80        free(node);
     81}
     82/*----------------------------------------------------------------------------*/
     83static void node_toggle_reset_filtered(link_t *item, void *arg)
     84{
     85        assert(item);
     86        node_t *node = hash_table_get_instance(item, node_t, link);
     87        usb_target_t *target = arg;
     88        endpoint_toggle_reset_filtered(node->ep, *target);
     89}
     90/*----------------------------------------------------------------------------*/
     91static hash_table_operations_t op = {
     92        .hash = node_hash,
     93        .compare = node_compare,
     94        .remove_callback = node_remove,
     95};
     96/*----------------------------------------------------------------------------*/
    10097size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type,
    10198    size_t size, size_t max_packet_size)
     
    109106        const unsigned packet_count =
    110107            (size + max_packet_size - 1) / max_packet_size;
    111         /* TODO: It may be that ISO and INT transfers use only one packet per
    112          * transaction, but I did not find text in USB spec to confirm this */
     108        /* TODO: It may be that ISO and INT transfers use only one data packet
     109         * per transaction, but I did not find text in UB spec that confirms
     110         * this */
    113111        /* NOTE: All data packets will be considered to be max_packet_size */
    114112        switch (speed)
     
    139137}
    140138/*----------------------------------------------------------------------------*/
    141 /** Initialize to default state.
    142  * You need to provide valid bw_count function if you plan to use
    143  * add_endpoint/remove_endpoint pair.
    144  *
    145  * @param instance usb_endpoint_manager structure, non-null.
    146  * @param available_bandwidth Size of the bandwidth pool.
    147  * @param bw_count function to use to calculate endpoint bw requirements.
    148  * @return Error code.
    149  */
    150139int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
    151140    size_t available_bandwidth,
     
    156145        instance->free_bw = available_bandwidth;
    157146        instance->bw_count = bw_count;
    158         for (unsigned i = 0; i < ENDPOINT_LIST_COUNT; ++i) {
    159                 list_initialize(&instance->endpoint_lists[i]);
    160         }
     147        const bool ht =
     148            hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op);
     149        return ht ? EOK : ENOMEM;
     150}
     151/*----------------------------------------------------------------------------*/
     152void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance)
     153{
     154        hash_table_destroy(&instance->ep_table);
     155}
     156/*----------------------------------------------------------------------------*/
     157int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance,
     158    endpoint_t *ep, size_t data_size)
     159{
     160        assert(instance);
     161        assert(instance->bw_count);
     162        assert(ep);
     163        const size_t bw = instance->bw_count(ep->speed, ep->transfer_type,
     164            data_size, ep->max_packet_size);
     165
     166        fibril_mutex_lock(&instance->guard);
     167
     168        if (bw > instance->free_bw) {
     169                fibril_mutex_unlock(&instance->guard);
     170                return ENOSPC;
     171        }
     172
     173        unsigned long key[MAX_KEYS] =
     174            {ep->address, ep->endpoint, ep->direction};
     175
     176        const link_t *item =
     177            hash_table_find(&instance->ep_table, key);
     178        if (item != NULL) {
     179                fibril_mutex_unlock(&instance->guard);
     180                return EEXISTS;
     181        }
     182
     183        node_t *node = malloc(sizeof(node_t));
     184        if (node == NULL) {
     185                fibril_mutex_unlock(&instance->guard);
     186                return ENOMEM;
     187        }
     188
     189        node->bw = bw;
     190        node->ep = ep;
     191        link_initialize(&node->link);
     192
     193        hash_table_insert(&instance->ep_table, key, &node->link);
     194        instance->free_bw -= bw;
     195        fibril_mutex_unlock(&instance->guard);
    161196        return EOK;
    162197}
    163198/*----------------------------------------------------------------------------*/
     199int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance,
     200    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
     201{
     202        assert(instance);
     203        unsigned long key[MAX_KEYS] = {address, endpoint, direction};
     204
     205        fibril_mutex_lock(&instance->guard);
     206        link_t *item = hash_table_find(&instance->ep_table, key);
     207        if (item == NULL) {
     208                fibril_mutex_unlock(&instance->guard);
     209                return EINVAL;
     210        }
     211
     212        node_t *node = hash_table_get_instance(item, node_t, link);
     213        if (node->ep->active) {
     214                fibril_mutex_unlock(&instance->guard);
     215                return EBUSY;
     216        }
     217
     218        instance->free_bw += node->bw;
     219        hash_table_remove(&instance->ep_table, key, MAX_KEYS);
     220
     221        fibril_mutex_unlock(&instance->guard);
     222        return EOK;
     223}
     224/*----------------------------------------------------------------------------*/
     225endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance,
     226    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
     227    size_t *bw)
     228{
     229        assert(instance);
     230        unsigned long key[MAX_KEYS] = {address, endpoint, direction};
     231
     232        fibril_mutex_lock(&instance->guard);
     233        const link_t *item = hash_table_find(&instance->ep_table, key);
     234        if (item == NULL) {
     235                fibril_mutex_unlock(&instance->guard);
     236                return NULL;
     237        }
     238        const node_t *node = hash_table_get_instance(item, node_t, link);
     239        if (bw)
     240                *bw = node->bw;
     241
     242        fibril_mutex_unlock(&instance->guard);
     243        return node->ep;
     244}
     245/*----------------------------------------------------------------------------*/
    164246/** Check setup packet data for signs of toggle reset.
    165247 *
    166  * @param[in] instance usb_endpoint_manager structure, non-null.
     248 * @param[in] instance Device keeper structure to use.
    167249 * @param[in] target Device to receive setup packet.
    168250 * @param[in] data Setup packet data.
    169251 *
    170  * Really ugly one. Resets toggle bit on all endpoints that need it.
     252 * Really ugly one.
    171253 */
    172 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance,
    173     usb_target_t target, const uint8_t data[8])
     254void usb_endpoint_manager_reset_if_need(
     255    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data)
    174256{
    175257        assert(instance);
     
    185267                /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */
    186268                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
     269                        /* endpoint number is < 16, thus first byte is enough */
     270                        usb_target_t reset_target =
     271                            { .address = target.address, data[4] };
    187272                        fibril_mutex_lock(&instance->guard);
    188                         /* endpoint number is < 16, thus first byte is enough */
    189                         list_foreach(*get_list(instance, target.address), it) {
    190                                 endpoint_t *ep = endpoint_get_instance(it);
    191                                 if ((ep->address == target.address)
    192                                     && (ep->endpoint = data[4])) {
    193                                         endpoint_toggle_set(ep,0);
    194                                 }
    195                         }
     273                        hash_table_apply(&instance->ep_table,
     274                            node_toggle_reset_filtered, &reset_target);
    196275                        fibril_mutex_unlock(&instance->guard);
    197276                }
     
    200279        case 0x9: /* Set Configuration */
    201280        case 0x11: /* Set Interface */
    202                 /* Recipient must be device, this resets all endpoints,
    203                  * In fact there should be no endpoints but EP 0 registered
    204                  * as different interfaces use different endpoints. */
     281                /* Recipient must be device */
    205282                if ((data[0] & 0xf) == 0) {
     283                        usb_target_t reset_target =
     284                            { .address = target.address, 0 };
    206285                        fibril_mutex_lock(&instance->guard);
    207                         list_foreach(*get_list(instance, target.address), it) {
    208                                 endpoint_t *ep = endpoint_get_instance(it);
    209                                 if (ep->address == target.address) {
    210                                         endpoint_toggle_set(ep,0);
    211                                 }
    212                         }
     286                        hash_table_apply(&instance->ep_table,
     287                            node_toggle_reset_filtered, &reset_target);
    213288                        fibril_mutex_unlock(&instance->guard);
    214289                }
     
    216291        }
    217292}
    218 /*----------------------------------------------------------------------------*/
    219 /** Register endpoint structure.
    220  * Checks for duplicates.
    221  * @param instance usb_endpoint_manager, non-null.
    222  * @param ep endpoint_t to register.
    223  * @param data_size Size of data to transfer.
    224  * @return Error code.
    225  */
    226 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance,
    227     endpoint_t *ep, size_t data_size)
    228 {
    229         assert(instance);
    230         if (ep == NULL || ep->address < 0)
    231                 return EINVAL;
    232 
    233         fibril_mutex_lock(&instance->guard);
    234         /* Check for available bandwidth */
    235         if (ep->bandwidth > instance->free_bw) {
    236                 fibril_mutex_unlock(&instance->guard);
    237                 return ENOSPC;
    238         }
    239 
    240         /* Check for existence */
    241         const endpoint_t *endpoint =
    242             find_locked(instance, ep->address, ep->endpoint, ep->direction);
    243         if (endpoint != NULL) {
    244                 fibril_mutex_unlock(&instance->guard);
    245                 return EEXISTS;
    246         }
    247         list_append(&ep->link, get_list(instance, ep->address));
    248 
    249         instance->free_bw -= ep->bandwidth;
    250         fibril_mutex_unlock(&instance->guard);
    251         return EOK;
    252 }
    253 /*----------------------------------------------------------------------------*/
    254 /** Unregister endpoint structure.
    255  * Checks for duplicates.
    256  * @param instance usb_endpoint_manager, non-null.
    257  * @param ep endpoint_t to unregister.
    258  * @return Error code.
    259  */
    260 int usb_endpoint_manager_unregister_ep(
    261     usb_endpoint_manager_t *instance, endpoint_t *ep)
    262 {
    263         assert(instance);
    264         if (ep == NULL || ep->address < 0)
    265                 return EINVAL;
    266 
    267         fibril_mutex_lock(&instance->guard);
    268         if (!list_member(&ep->link, get_list(instance, ep->address))) {
    269                 fibril_mutex_unlock(&instance->guard);
    270                 return ENOENT;
    271         }
    272         list_remove(&ep->link);
    273         instance->free_bw += ep->bandwidth;
    274         fibril_mutex_unlock(&instance->guard);
    275         return EOK;
    276 }
    277 /*----------------------------------------------------------------------------*/
    278 /** Find endpoint_t representing the given communication route.
    279  * @param instance usb_endpoint_manager, non-null.
    280  * @param address
    281  */
    282 endpoint_t * usb_endpoint_manager_find_ep(usb_endpoint_manager_t *instance,
    283     usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
    284 {
    285         assert(instance);
    286 
    287         fibril_mutex_lock(&instance->guard);
    288         endpoint_t *ep = find_locked(instance, address, endpoint, direction);
    289         fibril_mutex_unlock(&instance->guard);
    290         return ep;
    291 }
    292 /*----------------------------------------------------------------------------*/
    293 /** Create and register new endpoint_t structure.
    294  * @param instance usb_endpoint_manager structure, non-null.
    295  * @param address USB address.
    296  * @param endpoint USB endpoint number.
    297  * @param direction Communication direction.
    298  * @param type USB transfer type.
    299  * @param speed USB Communication speed.
    300  * @param max_packet_size Maximum size of data packets.
    301  * @param data_size Expected communication size.
    302  * @param callback function to call just after registering.
    303  * @param arg Argument to pass to the callback function.
    304  * @return Error code.
    305  */
    306 int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
    307     usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
    308     usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size,
    309     size_t data_size, int (*callback)(endpoint_t *, void *), void *arg)
    310 {
    311         assert(instance);
    312         if (instance->bw_count == NULL)
    313                 return ENOTSUP;
    314         if (address < 0)
    315                 return EINVAL;
    316 
    317         const size_t bw =
    318             instance->bw_count(speed, type, data_size, max_packet_size);
    319 
    320         fibril_mutex_lock(&instance->guard);
    321         /* Check for available bandwidth */
    322         if (bw > instance->free_bw) {
    323                 fibril_mutex_unlock(&instance->guard);
    324                 return ENOSPC;
    325         }
    326 
    327         /* Check for existence */
    328         endpoint_t *ep = find_locked(instance, address, endpoint, direction);
    329         if (ep != NULL) {
    330                 fibril_mutex_unlock(&instance->guard);
    331                 return EEXISTS;
    332         }
    333 
    334         ep = endpoint_create(
    335             address, endpoint, direction, type, speed, max_packet_size, bw);
    336         if (!ep) {
    337                 fibril_mutex_unlock(&instance->guard);
    338                 return ENOMEM;
    339         }
    340 
    341         if (callback) {
    342                 const int ret = callback(ep, arg);
    343                 if (ret != EOK) {
    344                         fibril_mutex_unlock(&instance->guard);
    345                         endpoint_destroy(ep);
    346                         return ret;
    347                 }
    348         }
    349         list_append(&ep->link, get_list(instance, ep->address));
    350 
    351         instance->free_bw -= ep->bandwidth;
    352         fibril_mutex_unlock(&instance->guard);
    353         return EOK;
    354 }
    355 /*----------------------------------------------------------------------------*/
    356 /** Unregister and destroy endpoint_t structure representing given route.
    357  * @param instance usb_endpoint_manager structure, non-null.
    358  * @param address USB address.
    359  * @param endpoint USB endpoint number.
    360  * @param direction Communication direction.
    361  * @param callback Function to call after unregister, before destruction.
    362  * @arg Argument to pass to the callback function.
    363  * @return Error code.
    364  */
    365 int usb_endpoint_manager_remove_ep(usb_endpoint_manager_t *instance,
    366     usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
    367     void (*callback)(endpoint_t *, void *), void *arg)
    368 {
    369         assert(instance);
    370         fibril_mutex_lock(&instance->guard);
    371         endpoint_t *ep = find_locked(instance, address, endpoint, direction);
    372         if (ep != NULL) {
    373                 list_remove(&ep->link);
    374                 instance->free_bw += ep->bandwidth;
    375         }
    376         fibril_mutex_unlock(&instance->guard);
    377         if (ep == NULL)
    378                 return ENOENT;
    379 
    380         if (callback) {
    381                 callback(ep, arg);
    382         }
    383         endpoint_destroy(ep);
    384         return EOK;
    385 }
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    r45bf63c r1737bfb  
    3737#include <usb/usb.h>
    3838#include <usb/debug.h>
    39 
    4039#include <usb/host/usb_transfer_batch.h>
    4140#include <usb/host/hcd.h>
    4241
    43 /** Allocate and initialize usb_transfer_batch structure.
    44  * @param ep endpoint used by the transfer batch.
    45  * @param buffer data to send/recieve.
    46  * @param buffer_size Size of data buffer.
    47  * @param setup_buffer Data to send in SETUP stage of control transfer.
    48  * @param func_in callback on IN transfer completion.
    49  * @param func_out callback on OUT transfer completion.
    50  * @param arg Argument to pass to the callback function.
    51  * @param private_data driver specific per batch data.
    52  * @param private_data_dtor Function to properly destroy private_data.
    53  * @return Pointer to valid usb_transfer_batch_t structure, NULL on failure.
    54  */
    55 usb_transfer_batch_t * usb_transfer_batch_create(
     42usb_transfer_batch_t * usb_transfer_batch_get(
    5643    endpoint_t *ep,
    5744    char *buffer,
     
    6653    )
    6754{
    68         if (func_in == NULL && func_out == NULL)
    69                 return NULL;
    70         if (func_in != NULL && func_out != NULL)
    71                 return NULL;
    72 
    7355        usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
    7456        if (instance) {
     
    9678}
    9779/*----------------------------------------------------------------------------*/
     80/** Mark batch as finished and run callback.
     81 *
     82 * @param[in] instance Batch structure to use.
     83 * @param[in] data Data to copy to the output buffer.
     84 * @param[in] size Size of @p data.
     85 */
     86void usb_transfer_batch_finish(
     87    usb_transfer_batch_t *instance, const void *data, size_t size)
     88{
     89        assert(instance);
     90        assert(instance->ep);
     91        /* we care about the data and there are some to copy */
     92        if (instance->ep->direction != USB_DIRECTION_OUT
     93            && data) {
     94                const size_t min_size =
     95                    size < instance->buffer_size ? size : instance->buffer_size;
     96                memcpy(instance->buffer, data, min_size);
     97        }
     98        if (instance->callback_out)
     99                usb_transfer_batch_call_out(instance);
     100        if (instance->callback_in)
     101                usb_transfer_batch_call_in(instance);
     102
     103}
     104/*----------------------------------------------------------------------------*/
     105/** Prepare data, get error status and call callback in.
     106 *
     107 * @param[in] instance Batch structure to use.
     108 * Copies data from transport buffer, and calls callback with appropriate
     109 * parameters.
     110 */
     111void usb_transfer_batch_call_in(usb_transfer_batch_t *instance)
     112{
     113        assert(instance);
     114        assert(instance->callback_in);
     115
     116        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n",
     117            instance, USB_TRANSFER_BATCH_ARGS(*instance),
     118            instance->transfered_size, str_error(instance->error));
     119
     120        instance->callback_in(instance->fun, instance->error,
     121            instance->transfered_size, instance->arg);
     122}
     123/*----------------------------------------------------------------------------*/
     124/** Get error status and call callback out.
     125 *
     126 * @param[in] instance Batch structure to use.
     127 */
     128void usb_transfer_batch_call_out(usb_transfer_batch_t *instance)
     129{
     130        assert(instance);
     131        assert(instance->callback_out);
     132
     133        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed: %s.\n",
     134            instance, USB_TRANSFER_BATCH_ARGS(*instance),
     135            str_error(instance->error));
     136
     137        if (instance->ep->transfer_type == USB_TRANSFER_CONTROL
     138            && instance->error == EOK) {
     139                const usb_target_t target =
     140                    {{ instance->ep->address, instance->ep->endpoint }};
     141                reset_ep_if_need(
     142                    fun_to_hcd(instance->fun), target, instance->setup_buffer);
     143        }
     144
     145        instance->callback_out(instance->fun,
     146            instance->error, instance->arg);
     147}
     148/*----------------------------------------------------------------------------*/
    98149/** Correctly dispose all used data structures.
    99150 *
    100151 * @param[in] instance Batch structure to use.
    101152 */
    102 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance)
     153void usb_transfer_batch_dispose(usb_transfer_batch_t *instance)
    103154{
    104155        if (!instance)
     
    115166        free(instance);
    116167}
    117 /*----------------------------------------------------------------------------*/
    118 /** Prepare data and call the right callback.
    119  *
    120  * @param[in] instance Batch structure to use.
    121  * @param[in] data Data to copy to the output buffer.
    122  * @param[in] size Size of @p data.
    123  */
    124 void usb_transfer_batch_finish(
    125     const usb_transfer_batch_t *instance, const void *data, size_t size)
    126 {
    127         assert(instance);
    128         usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " finishing.\n",
    129             instance, USB_TRANSFER_BATCH_ARGS(*instance));
    130 
    131         /* NOTE: Only one of these pointers should be set. */
    132         if (instance->callback_out) {
    133                 /* Check for commands that reset toggle bit */
    134                 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL
    135                     && instance->error == EOK) {
    136                         const usb_target_t target =
    137                             {{ instance->ep->address, instance->ep->endpoint }};
    138                         reset_ep_if_need(fun_to_hcd(instance->fun), target,
    139                             instance->setup_buffer);
    140                 }
    141                 instance->callback_out(instance->fun,
    142                     instance->error, instance->arg);
    143         }
    144 
    145         if (instance->callback_in) {
    146                 /* We care about the data and there are some to copy */
    147                 if (data) {
    148                         const size_t min_size = size < instance->buffer_size
    149                             ? size : instance->buffer_size;
    150                         memcpy(instance->buffer, data, min_size);
    151                 }
    152                 instance->callback_in(instance->fun, instance->error,
    153                     instance->transfered_size, instance->arg);
    154         }
    155 }
    156168/**
    157169 * @}
Note: See TracChangeset for help on using the changeset viewer.