Ignore:
File:
1 edited

Legend:

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

    r8b54fe6 r77ad86c  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
     28
    2829/** @addtogroup libusbhost
    2930 * @{
     
    3233 * @brief HCD DDF interface implementation
    3334 */
     35
    3436#include <ddf/driver.h>
    3537#include <errno.h>
     
    3941#include <usb/host/hcd.h>
    4042
     43/** Prepare generic usb_transfer_batch and schedule it.
     44 * @param fun DDF fun
     45 * @param target address and endpoint number.
     46 * @param setup_data Data to use in setup stage (Control communication type)
     47 * @param in Callback for device to host communication.
     48 * @param out Callback for host to device communication.
     49 * @param arg Callback parameter.
     50 * @param name Communication identifier (for nicer output).
     51 * @return Error code.
     52 */
    4153static inline int send_batch(
    4254    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
     
    4961        assert(hcd);
    5062
    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);
     63        endpoint_t *ep = usb_endpoint_manager_find_ep(&hcd->ep_manager,
     64            target.address, target.endpoint, direction);
    5665        if (ep == NULL) {
    5766                usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
     
    6574        const size_t bw = bandwidth_count_usb11(
    6675            ep->speed, ep->transfer_type, size, ep->max_packet_size);
    67         if (res_bw < bw) {
     76        /* Check if we have enough bandwidth reserved */
     77        if (ep->bandwidth < bw) {
    6878                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
    6979                    "but only %zu is reserved.\n",
    70                     target.address, target.endpoint, name, bw, res_bw);
     80                    ep->address, ep->endpoint, name, bw, ep->bandwidth);
    7181                return ENOSPC;
    7282        }
     
    7888        /* No private data and no private data dtor */
    7989        usb_transfer_batch_t *batch =
    80             usb_transfer_batch_get(ep, data, size, setup_data,
     90            usb_transfer_batch_create(ep, data, size, setup_data,
    8191            in, out, arg, fun, NULL, NULL);
    8292        if (!batch) {
     
    8494        }
    8595
    86         ret = hcd->schedule(hcd, batch);
     96        const int ret = hcd->schedule(hcd, batch);
    8797        if (ret != EOK)
    88                 usb_transfer_batch_dispose(batch);
     98                usb_transfer_batch_destroy(batch);
    8999
    90100        return ret;
    91101}
    92 /*----------------------------------------------------------------------------*/
    93 /** Request address interface function
     102
     103/** Calls ep_add_hook upon endpoint registration.
     104 * @param ep Endpoint to be registered.
     105 * @param arg hcd_t in disguise.
     106 * @return Error code.
     107 */
     108static int register_helper(endpoint_t *ep, void *arg)
     109{
     110        hcd_t *hcd = arg;
     111        assert(ep);
     112        assert(hcd);
     113        if (hcd->ep_add_hook)
     114                return hcd->ep_add_hook(hcd, ep);
     115        return EOK;
     116}
     117
     118/** Calls ep_remove_hook upon endpoint removal.
     119 * @param ep Endpoint to be unregistered.
     120 * @param arg hcd_t in disguise.
     121 */
     122static void unregister_helper(endpoint_t *ep, void *arg)
     123{
     124        hcd_t *hcd = arg;
     125        assert(ep);
     126        assert(hcd);
     127        if (hcd->ep_remove_hook)
     128                hcd->ep_remove_hook(hcd, ep);
     129}
     130
     131/** Calls ep_remove_hook upon endpoint removal. Prints warning.
     132 * @param ep Endpoint to be unregistered.
     133 * @param arg hcd_t in disguise.
     134 */
     135static void unregister_helper_warn(endpoint_t *ep, void *arg)
     136{
     137        hcd_t *hcd = arg;
     138        assert(ep);
     139        assert(hcd);
     140        usb_log_warning("Endpoint %d:%d %s was left behind, removing.\n",
     141            ep->address, ep->endpoint, usb_str_direction(ep->direction));
     142        if (hcd->ep_remove_hook)
     143                hcd->ep_remove_hook(hcd, ep);
     144}
     145
     146/** Request address interface function.
    94147 *
    95148 * @param[in] fun DDF function that was called.
     149 * @param[in] address Pointer to preferred USB address.
     150 * @param[out] address Place to write a new address.
     151 * @param[in] strict Fail if the preferred address is not available.
    96152 * @param[in] speed Speed to associate with the new default address.
    97  * @param[out] address Place to write a new address.
    98153 * @return Error code.
    99154 */
    100155static int request_address(
    101     ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
     156    ddf_fun_t *fun, usb_address_t *address, bool strict, usb_speed_t speed)
    102157{
    103158        assert(fun);
     
    106161        assert(address);
    107162
    108         usb_log_debug("Address request speed: %s.\n", usb_str_speed(speed));
    109         *address =
    110             usb_device_manager_get_free_address(&hcd->dev_manager, speed);
    111         usb_log_debug("Address request with result: %d.\n", *address);
    112         if (*address <= 0)
    113                 return *address;
    114         return EOK;
    115 }
    116 /*----------------------------------------------------------------------------*/
    117 /** Bind address interface function
     163        usb_log_debug("Address request: speed: %s, address: %d, strict: %s.\n",
     164            usb_str_speed(speed), *address, strict ? "YES" : "NO");
     165        return usb_device_manager_request_address(
     166            &hcd->dev_manager, address, strict, speed);
     167}
     168
     169/** Bind address interface function.
    118170 *
    119171 * @param[in] fun DDF function that was called.
     
    123175 */
    124176static int bind_address(
    125   ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
     177    ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
    126178{
    127179        assert(fun);
     
    130182
    131183        usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
    132         usb_device_manager_bind(&hcd->dev_manager, address, handle);
    133         return EOK;
    134 }
    135 /*----------------------------------------------------------------------------*/
     184        return usb_device_manager_bind_address(
     185            &hcd->dev_manager, address, handle);
     186}
     187
    136188/** Find device handle by address interface function.
    137189 *
     
    147199        hcd_t *hcd = fun_to_hcd(fun);
    148200        assert(hcd);
    149         const bool found =
    150             usb_device_manager_find_by_address(&hcd->dev_manager, address, handle);
    151         return found ? EOK : ENOENT;
    152 }
    153 /*----------------------------------------------------------------------------*/
    154 /** Release address interface function
     201        return usb_device_manager_get_info_by_address(
     202            &hcd->dev_manager, address, handle, NULL);
     203}
     204
     205/** Release address interface function.
    155206 *
    156207 * @param[in] fun DDF function that was called.
     
    164215        assert(hcd);
    165216        usb_log_debug("Address release %d.\n", address);
    166         usb_device_manager_release(&hcd->dev_manager, address);
     217        usb_device_manager_release_address(&hcd->dev_manager, address);
     218        usb_endpoint_manager_remove_address(&hcd->ep_manager, address,
     219            unregister_helper_warn, hcd);
    167220        return EOK;
    168221}
    169 /*----------------------------------------------------------------------------*/
     222
     223/** Register endpoint interface function.
     224 * @param fun DDF function.
     225 * @param address USB address of the device.
     226 * @param endpoint USB endpoint number to be registered.
     227 * @param transfer_type Endpoint's transfer type.
     228 * @param direction USB communication direction the endpoint is capable of.
     229 * @param max_packet_size Maximu size of packets the endpoint accepts.
     230 * @param interval Preferred timeout between communication.
     231 * @return Error code.
     232 */
    170233static int register_endpoint(
    171     ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
    172     usb_endpoint_t endpoint,
     234    ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
    173235    usb_transfer_type_t transfer_type, usb_direction_t direction,
    174     size_t max_packet_size, unsigned int interval)
     236    size_t max_packet_size, unsigned interval)
    175237{
    176238        assert(fun);
     
    178240        assert(hcd);
    179241        const size_t size = max_packet_size;
    180         /* Default address is not bound or registered,
    181          * thus it does not provide speed info. */
    182         const usb_speed_t speed = (address == 0) ? ep_speed :
    183             usb_device_manager_get_speed(&hcd->dev_manager, address);
     242        usb_speed_t speed = USB_SPEED_MAX;
     243        const int ret = usb_device_manager_get_info_by_address(
     244            &hcd->dev_manager, address, NULL, &speed);
     245        if (ret != EOK) {
     246                return ret;
     247        }
    184248
    185249        usb_log_debug("Register endpoint %d:%d %s-%s %s %zuB %ums.\n",
     
    188252            max_packet_size, interval);
    189253
    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;
    209 }
    210 /*----------------------------------------------------------------------------*/
     254        return usb_endpoint_manager_add_ep(&hcd->ep_manager, address, endpoint,
     255            direction, transfer_type, speed, max_packet_size, size,
     256            register_helper, hcd);
     257}
     258
     259/** Unregister endpoint interface function.
     260 * @param fun DDF function.
     261 * @param address USB address of the endpoint.
     262 * @param endpoint USB endpoint number.
     263 * @param direction Communication direction of the enpdoint to unregister.
     264 * @return Error code.
     265 */
    211266static int unregister_endpoint(
    212267    ddf_fun_t *fun, usb_address_t address,
     
    218273        usb_log_debug("Unregister endpoint %d:%d %s.\n",
    219274            address, endpoint, usb_str_direction(direction));
    220         return usb_endpoint_manager_unregister_ep(&hcd->ep_manager, address,
    221             endpoint, direction);
    222 }
    223 /*----------------------------------------------------------------------------*/
     275        return usb_endpoint_manager_remove_ep(&hcd->ep_manager, address,
     276            endpoint, direction, unregister_helper, hcd);
     277}
     278
     279/** Inbound communication interface function.
     280 * @param fun DDF function.
     281 * @param target Communication target.
     282 * @param setup_data Data to use in setup stage (control transfers).
     283 * @param data Pointer to data buffer.
     284 * @param size Size of the data buffer.
     285 * @param callback Function to call on communication end.
     286 * @param arg Argument passed to the callback function.
     287 * @return Error code.
     288 */
    224289static int usb_read(ddf_fun_t *fun, usb_target_t target, uint64_t setup_data,
    225290    uint8_t *data, size_t size, usbhc_iface_transfer_in_callback_t callback,
     
    229294            setup_data, callback, NULL, arg, "READ");
    230295}
    231 /*----------------------------------------------------------------------------*/
     296
     297/** Outbound communication interface function.
     298 * @param fun DDF function.
     299 * @param target Communication target.
     300 * @param setup_data Data to use in setup stage (control transfers).
     301 * @param data Pointer to data buffer.
     302 * @param size Size of the data buffer.
     303 * @param callback Function to call on communication end.
     304 * @param arg Argument passed to the callback function.
     305 * @return Error code.
     306 */
    232307static int usb_write(ddf_fun_t *fun, usb_target_t target, uint64_t setup_data,
    233308    const uint8_t *data, size_t size,
     
    237312            setup_data, NULL, callback, arg, "WRITE");
    238313}
    239 /*----------------------------------------------------------------------------*/
     314
     315/** usbhc Interface implementation using hcd_t from libusbhost library. */
    240316usbhc_iface_t hcd_iface = {
    241317        .request_address = request_address,
    242318        .bind_address = bind_address,
    243         .find_by_address = find_by_address,
     319        .get_handle = find_by_address,
    244320        .release_address = release_address,
    245321
     
    250326        .write = usb_write,
    251327};
     328
    252329/**
    253330 * @}
Note: See TracChangeset for help on using the changeset viewer.