Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/ohci/iface.c

    r1998bcd ra19a2d7  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky
     2 * Copyright (c) 2011 Vojtech Horky, Jan Vesely
    33 * All rights reserved.
    44 *
     
    3030 */
    3131/** @file
    32  * USB-HC interface implementation.
     32 * @brief OHCI driver hc interface implementation
    3333 */
    3434#include <ddf/driver.h>
     
    3636
    3737#include <usb/debug.h>
     38#include <usb/host/endpoint.h>
    3839
    3940#include "iface.h"
    4041#include "hc.h"
    4142
    42 #define UNSUPPORTED(methodname) \
    43         usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \
    44             methodname, __FILE__, __LINE__)
    45 
    46 /** Reserve default address.
    47  *
    48  * This function may block the caller.
    49  *
    50  * @param[in] fun Device function the action was invoked on.
    51  * @param[in] speed Speed of the device for which the default address is
    52  *      reserved.
    53  * @return Error code.
    54  */
    55 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    56 {
     43static inline int setup_batch(
     44    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
     45    void *data, size_t size, void * setup_data, size_t setup_size,
     46    usbhc_iface_transfer_in_callback_t in,
     47    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
     48    hc_t **hc, usb_transfer_batch_t **batch)
     49{
     50        assert(hc);
     51        assert(batch);
    5752        assert(fun);
    58         hc_t *hc = fun_to_hc(fun);
    59         assert(hc);
    60         usb_log_debug("Default address request with speed %d.\n", speed);
    61         usb_device_keeper_reserve_default_address(&hc->manager, speed);
     53        *hc = fun_to_hc(fun);
     54        assert(*hc);
     55
     56        size_t res_bw;
     57        endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
     58            target.address, target.endpoint, direction, &res_bw);
     59        if (ep == NULL) {
     60                usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
     61                    target.address, target.endpoint, name);
     62                return ENOENT;
     63        }
     64
     65        const size_t bw = bandwidth_count_usb11(
     66            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     67        if (res_bw < bw) {
     68                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
     69                    "but only %zu is reserved.\n",
     70                    name, target.address, target.endpoint, bw, res_bw);
     71                return ENOSPC;
     72        }
     73        usb_log_debug("%s %d:%d %zu(%zu).\n",
     74            name, target.address, target.endpoint, size, ep->max_packet_size);
     75
     76        *batch = batch_get(
     77            fun, ep, data, size, setup_data, setup_size, in, out, arg);
     78        if (!*batch)
     79                return ENOMEM;
    6280        return EOK;
    6381}
    6482/*----------------------------------------------------------------------------*/
    65 /** Release default address.
    66  *
    67  * @param[in] fun Device function the action was invoked on.
    68  * @return Error code.
    69  */
    70 static int release_default_address(ddf_fun_t *fun)
    71 {
    72         assert(fun);
    73         hc_t *hc = fun_to_hc(fun);
    74         assert(hc);
    75         usb_log_debug("Default address release.\n");
    76         usb_device_keeper_release_default_address(&hc->manager);
    77         return EOK;
    78 }
    79 /*----------------------------------------------------------------------------*/
    80 /** Found free USB address.
    81  *
    82  * @param[in] fun Device function the action was invoked on.
    83  * @param[in] speed Speed of the device that will get this address.
    84  * @param[out] address Non-null pointer where to store the free address.
     83/** Request address interface function
     84 *
     85 * @param[in] fun DDF function that was called.
     86 * @param[in] speed Speed to associate with the new default address.
     87 * @param[out] address Place to write a new address.
    8588 * @return Error code.
    8689 */
     
    101104}
    102105/*----------------------------------------------------------------------------*/
    103 /** Bind USB address with device devman handle.
    104  *
    105  * @param[in] fun Device function the action was invoked on.
    106  * @param[in] address USB address of the device.
    107  * @param[in] handle Devman handle of the device.
     106/** Bind address interface function
     107 *
     108 * @param[in] fun DDF function that was called.
     109 * @param[in] address Address of the device
     110 * @param[in] handle Devman handle of the device driver.
    108111 * @return Error code.
    109112 */
    110113static int bind_address(
    111     ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
     114  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
    112115{
    113116        assert(fun);
     
    119122}
    120123/*----------------------------------------------------------------------------*/
    121 /** Release previously requested address.
    122  *
    123  * @param[in] fun Device function the action was invoked on.
     124/** Release address interface function
     125 *
     126 * @param[in] fun DDF function that was called.
    124127 * @param[in] address USB address to be released.
    125128 * @return Error code.
     
    152155    size_t max_packet_size, unsigned int interval)
    153156{
    154         assert(fun);
    155157        hc_t *hc = fun_to_hc(fun);
    156158        assert(hc);
     
    161163                speed = ep_speed;
    162164        }
    163         const size_t size = max_packet_size;
     165        const size_t size =
     166            (transfer_type == USB_TRANSFER_INTERRUPT
     167            || transfer_type == USB_TRANSFER_ISOCHRONOUS) ?
     168            max_packet_size : 0;
     169        int ret;
     170
     171        endpoint_t *ep = malloc(sizeof(endpoint_t));
     172        if (ep == NULL)
     173                return ENOMEM;
     174        ret = endpoint_init(ep, address, endpoint, direction,
     175            transfer_type, speed, max_packet_size);
     176        if (ret != EOK) {
     177                free(ep);
     178                return ret;
     179        }
     180
    164181        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    165182            address, endpoint, usb_str_transfer_type(transfer_type),
    166183            usb_str_speed(speed), direction, size, max_packet_size, interval);
    167         // TODO use real endpoint here!
    168         return usb_endpoint_manager_register_ep(&hc->ep_manager,NULL, 0);
    169 }
    170 /*----------------------------------------------------------------------------*/
    171 /** Unregister endpoint (free some bandwidth reservation).
    172  *
    173  * @param[in] fun Device function the action was invoked on.
    174  * @param[in] address USB address of the device.
    175  * @param[in] endpoint Endpoint number.
    176  * @param[in] direction Endpoint data direction.
    177  * @return Error code.
    178  */
     184
     185        ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
     186        if (ret != EOK) {
     187                endpoint_destroy(ep);
     188        }
     189        return ret;
     190}
     191/*----------------------------------------------------------------------------*/
    179192static int unregister_endpoint(
    180193    ddf_fun_t *fun, usb_address_t address,
    181194    usb_endpoint_t endpoint, usb_direction_t direction)
    182195{
    183         assert(fun);
    184196        hc_t *hc = fun_to_hc(fun);
    185197        assert(hc);
    186198        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    187199            address, endpoint, direction);
    188         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    189             address, endpoint, direction, NULL);
    190         if (ep != NULL) {
    191                 usb_device_keeper_del_ep(&hc->manager, address, ep);
    192         }
    193200        return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    194201            endpoint, direction);
     
    215222    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    216223{
    217         assert(fun);
    218 
    219         // FIXME: get from endpoint manager
    220         size_t max_packet_size = 8;
    221 
    222         hc_t *hc = fun_to_hc(fun);
    223         assert(hc);
    224         usb_speed_t speed =
    225             usb_device_keeper_get_speed(&hc->manager, target.address);
    226 
    227         usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n",
    228             target.address, target.endpoint, size, max_packet_size);
    229 
    230         usb_transfer_batch_t *batch =
    231             batch_get(fun, target, USB_TRANSFER_INTERRUPT, max_packet_size,
    232                 speed, data, size, NULL, 0, NULL, callback, arg, &hc->manager);
    233         if (!batch)
    234                 return ENOMEM;
     224        usb_transfer_batch_t *batch = NULL;
     225        hc_t *hc = NULL;
     226        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     227            NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
     228        if (ret != EOK)
     229                return ret;
    235230        batch_interrupt_out(batch);
    236         const int ret = hc_schedule(hc, batch);
     231        ret = hc_schedule(hc, batch);
    237232        if (ret != EOK) {
    238233                batch_dispose(batch);
     
    261256    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    262257{
    263         assert(fun);
    264 
    265         // FIXME: get from endpoint manager
    266         size_t max_packet_size = 8;
    267 
    268         hc_t *hc = fun_to_hc(fun);
    269         assert(hc);
    270         usb_speed_t speed =
    271             usb_device_keeper_get_speed(&hc->manager, target.address);
    272         usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n",
    273             target.address, target.endpoint, size, max_packet_size);
    274 
    275         usb_transfer_batch_t *batch =
    276             batch_get(fun, target, USB_TRANSFER_INTERRUPT, max_packet_size,
    277                 speed, data, size, NULL, 0, callback, NULL, arg, &hc->manager);
    278         if (!batch)
    279                 return ENOMEM;
     258        usb_transfer_batch_t *batch = NULL;
     259        hc_t *hc = NULL;
     260        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     261            NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
     262        if (ret != EOK)
     263                return ret;
    280264        batch_interrupt_in(batch);
    281         const int ret = hc_schedule(hc, batch);
     265        ret = hc_schedule(hc, batch);
    282266        if (ret != EOK) {
    283267                batch_dispose(batch);
     
    306290    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    307291{
    308         assert(fun);
    309 
    310         // FIXME: get from endpoint manager
    311         size_t max_packet_size = 8;
    312 
    313         hc_t *hc = fun_to_hc(fun);
    314         assert(hc);
    315         usb_speed_t speed =
    316             usb_device_keeper_get_speed(&hc->manager, target.address);
    317 
    318         usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
    319             target.address, target.endpoint, size, max_packet_size);
    320 
    321         usb_transfer_batch_t *batch =
    322             batch_get(fun, target, USB_TRANSFER_BULK, max_packet_size, speed,
    323                 data, size, NULL, 0, NULL, callback, arg, &hc->manager);
    324         if (!batch)
    325                 return ENOMEM;
     292        usb_transfer_batch_t *batch = NULL;
     293        hc_t *hc = NULL;
     294        int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
     295            NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
     296        if (ret != EOK)
     297                return ret;
    326298        batch_bulk_out(batch);
    327         const int ret = hc_schedule(hc, batch);
     299        ret = hc_schedule(hc, batch);
    328300        if (ret != EOK) {
    329301                batch_dispose(batch);
     
    352324    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    353325{
    354         assert(fun);
    355 
    356         // FIXME: get from endpoint manager
    357         size_t max_packet_size = 8;
    358 
    359         hc_t *hc = fun_to_hc(fun);
    360         assert(hc);
    361         usb_speed_t speed =
    362             usb_device_keeper_get_speed(&hc->manager, target.address);
    363         usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
    364             target.address, target.endpoint, size, max_packet_size);
    365 
    366         usb_transfer_batch_t *batch =
    367             batch_get(fun, target, USB_TRANSFER_BULK, max_packet_size, speed,
    368                 data, size, NULL, 0, callback, NULL, arg, &hc->manager);
    369         if (!batch)
    370                 return ENOMEM;
     326        usb_transfer_batch_t *batch = NULL;
     327        hc_t *hc = NULL;
     328        int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
     329            NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
     330        if (ret != EOK)
     331                return ret;
    371332        batch_bulk_in(batch);
    372         const int ret = hc_schedule(hc, batch);
     333        ret = hc_schedule(hc, batch);
    373334        if (ret != EOK) {
    374335                batch_dispose(batch);
     
    401362    usbhc_iface_transfer_out_callback_t callback, void *arg)
    402363{
    403         assert(fun);
    404 
    405         // FIXME: get from endpoint manager
    406         size_t max_packet_size = 8;
    407 
    408         hc_t *hc = fun_to_hc(fun);
    409         assert(hc);
    410         usb_speed_t speed =
    411             usb_device_keeper_get_speed(&hc->manager, target.address);
    412         usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n",
    413             speed, target.address, target.endpoint, size, max_packet_size);
    414 
    415         if (setup_size != 8)
    416                 return EINVAL;
    417 
    418         usb_transfer_batch_t *batch =
    419             batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size,
    420                 speed, data, size, setup_data, setup_size, NULL, callback, arg,
    421                 &hc->manager);
    422         if (!batch)
    423                 return ENOMEM;
    424         usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
     364        usb_transfer_batch_t *batch = NULL;
     365        hc_t *hc = NULL;
     366        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     367            setup_data, setup_size, NULL, callback, arg, "Control WRITE",
     368            &hc, &batch);
     369        if (ret != EOK)
     370                return ret;
     371        usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
    425372        batch_control_write(batch);
    426         const int ret = hc_schedule(hc, batch);
     373        ret = hc_schedule(hc, batch);
    427374        if (ret != EOK) {
    428375                batch_dispose(batch);
     
    455402    usbhc_iface_transfer_in_callback_t callback, void *arg)
    456403{
    457         assert(fun);
    458 
    459         // FIXME: get from endpoint manager
    460         size_t max_packet_size = 8;
    461 
    462         hc_t *hc = fun_to_hc(fun);
    463         assert(hc);
    464         usb_speed_t speed =
    465             usb_device_keeper_get_speed(&hc->manager, target.address);
    466 
    467         usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n",
    468             speed, target.address, target.endpoint, size, max_packet_size);
    469         usb_transfer_batch_t *batch =
    470             batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size,
    471                 speed, data, size, setup_data, setup_size, callback, NULL, arg,
    472                 &hc->manager);
    473         if (!batch)
    474                 return ENOMEM;
     404        usb_transfer_batch_t *batch = NULL;
     405        hc_t *hc = NULL;
     406        int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
     407            setup_data, setup_size, callback, NULL, arg, "Control READ",
     408            &hc, &batch);
     409        if (ret != EOK)
     410                return ret;
    475411        batch_control_read(batch);
    476         const int ret = hc_schedule(hc, batch);
    477         if (ret != EOK) {
    478                 batch_dispose(batch);
    479         }
    480         return ret;
    481 }
    482 /*----------------------------------------------------------------------------*/
    483 /** Host controller interface implementation for OHCI. */
     412        ret = hc_schedule(hc, batch);
     413        if (ret != EOK) {
     414                batch_dispose(batch);
     415        }
     416        return ret;
     417}
     418/*----------------------------------------------------------------------------*/
    484419usbhc_iface_t hc_iface = {
    485         .reserve_default_address = reserve_default_address,
    486         .release_default_address = release_default_address,
    487420        .request_address = request_address,
    488421        .bind_address = bind_address,
     
    501434        .control_read = control_read,
    502435};
    503 
    504436/**
    505437 * @}
Note: See TracChangeset for help on using the changeset viewer.