Ignore:
File:
1 edited

Legend:

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

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