Ignore:
File:
1 edited

Legend:

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

    ra19a2d7 r1998bcd  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky, Jan Vesely
     2 * Copyright (c) 2011 Vojtech Horky
    33 * All rights reserved.
    44 *
     
    3030 */
    3131/** @file
    32  * @brief OHCI driver hc interface implementation
     32 * USB-HC interface implementation.
    3333 */
    3434#include <ddf/driver.h>
     
    3636
    3737#include <usb/debug.h>
    38 #include <usb/host/endpoint.h>
    3938
    4039#include "iface.h"
    4140#include "hc.h"
    4241
    43 static 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);
    52         assert(fun);
    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;
     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 */
     55static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
     56{
     57        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);
    8062        return EOK;
    8163}
    8264/*----------------------------------------------------------------------------*/
    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.
     65/** Release default address.
     66 *
     67 * @param[in] fun Device function the action was invoked on.
     68 * @return Error code.
     69 */
     70static 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.
    8885 * @return Error code.
    8986 */
     
    104101}
    105102/*----------------------------------------------------------------------------*/
    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.
     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.
    111108 * @return Error code.
    112109 */
    113110static int bind_address(
    114   ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
     111    ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
    115112{
    116113        assert(fun);
     
    122119}
    123120/*----------------------------------------------------------------------------*/
    124 /** Release address interface function
    125  *
    126  * @param[in] fun DDF function that was called.
     121/** Release previously requested address.
     122 *
     123 * @param[in] fun Device function the action was invoked on.
    127124 * @param[in] address USB address to be released.
    128125 * @return Error code.
     
    155152    size_t max_packet_size, unsigned int interval)
    156153{
     154        assert(fun);
    157155        hc_t *hc = fun_to_hc(fun);
    158156        assert(hc);
     
    163161                speed = ep_speed;
    164162        }
    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 
     163        const size_t size = max_packet_size;
    181164        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    182165            address, endpoint, usb_str_transfer_type(transfer_type),
    183166            usb_str_speed(speed), direction, size, max_packet_size, interval);
    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 /*----------------------------------------------------------------------------*/
     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 */
    192179static int unregister_endpoint(
    193180    ddf_fun_t *fun, usb_address_t address,
    194181    usb_endpoint_t endpoint, usb_direction_t direction)
    195182{
     183        assert(fun);
    196184        hc_t *hc = fun_to_hc(fun);
    197185        assert(hc);
    198186        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    199187            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        }
    200193        return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    201194            endpoint, direction);
     
    222215    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    223216{
    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;
     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;
    230235        batch_interrupt_out(batch);
    231         ret = hc_schedule(hc, batch);
     236        const int ret = hc_schedule(hc, batch);
    232237        if (ret != EOK) {
    233238                batch_dispose(batch);
     
    256261    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    257262{
    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;
     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;
    264280        batch_interrupt_in(batch);
    265         ret = hc_schedule(hc, batch);
     281        const int ret = hc_schedule(hc, batch);
    266282        if (ret != EOK) {
    267283                batch_dispose(batch);
     
    290306    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    291307{
    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;
     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;
    298326        batch_bulk_out(batch);
    299         ret = hc_schedule(hc, batch);
     327        const int ret = hc_schedule(hc, batch);
    300328        if (ret != EOK) {
    301329                batch_dispose(batch);
     
    324352    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    325353{
    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;
     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;
    332371        batch_bulk_in(batch);
    333         ret = hc_schedule(hc, batch);
     372        const int ret = hc_schedule(hc, batch);
    334373        if (ret != EOK) {
    335374                batch_dispose(batch);
     
    362401    usbhc_iface_transfer_out_callback_t callback, void *arg)
    363402{
    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);
     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);
    372425        batch_control_write(batch);
    373         ret = hc_schedule(hc, batch);
     426        const int ret = hc_schedule(hc, batch);
    374427        if (ret != EOK) {
    375428                batch_dispose(batch);
     
    402455    usbhc_iface_transfer_in_callback_t callback, void *arg)
    403456{
    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;
     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;
    411475        batch_control_read(batch);
    412         ret = hc_schedule(hc, batch);
     476        const int ret = hc_schedule(hc, batch);
    413477        if (ret != EOK) {
    414478                batch_dispose(batch);
     
    417481}
    418482/*----------------------------------------------------------------------------*/
     483/** Host controller interface implementation for OHCI. */
    419484usbhc_iface_t hc_iface = {
     485        .reserve_default_address = reserve_default_address,
     486        .release_default_address = release_default_address,
    420487        .request_address = request_address,
    421488        .bind_address = bind_address,
     
    434501        .control_read = control_read,
    435502};
     503
    436504/**
    437505 * @}
Note: See TracChangeset for help on using the changeset viewer.