Ignore:
File:
1 edited

Legend:

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

    r0ede0c3 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         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;
     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);
    8162        return EOK;
    8263}
    8364/*----------------------------------------------------------------------------*/
    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.
     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.
    8985 * @return Error code.
    9086 */
     
    105101}
    106102/*----------------------------------------------------------------------------*/
    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.
     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.
    112108 * @return Error code.
    113109 */
    114110static int bind_address(
    115   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)
    116112{
    117113        assert(fun);
     
    123119}
    124120/*----------------------------------------------------------------------------*/
    125 /** Release address interface function
    126  *
    127  * @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.
    128124 * @param[in] address USB address to be released.
    129125 * @return Error code.
     
    156152    size_t max_packet_size, unsigned int interval)
    157153{
    158         hc_t *hc = fun_to_hc(fun);
    159         assert(hc);
    160 
     154        assert(fun);
     155        hc_t *hc = fun_to_hc(fun);
     156        assert(hc);
     157        if (address == hc->rh.address)
     158                return EOK;
    161159        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
    162160        if (speed >= USB_SPEED_MAX) {
     
    164162        }
    165163        const size_t size = max_packet_size;
    166         int ret;
    167 
    168164        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    169165            address, endpoint, usb_str_transfer_type(transfer_type),
    170166            usb_str_speed(speed), direction, size, max_packet_size, interval);
    171 
    172         endpoint_t *ep = malloc(sizeof(endpoint_t));
    173         if (ep == NULL)
    174                 return ENOMEM;
    175         ret = endpoint_init(ep, address, endpoint, direction,
    176             transfer_type, speed, max_packet_size);
    177         if (ret != EOK) {
    178                 free(ep);
    179                 return ret;
    180         }
    181 
    182         ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    183         if (ret != EOK) {
    184                 endpoint_destroy(ep);
    185         }
    186         return ret;
    187 }
    188 /*----------------------------------------------------------------------------*/
     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 */
    189179static int unregister_endpoint(
    190180    ddf_fun_t *fun, usb_address_t address,
    191181    usb_endpoint_t endpoint, usb_direction_t direction)
    192182{
     183        assert(fun);
    193184        hc_t *hc = fun_to_hc(fun);
    194185        assert(hc);
    195186        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    196187            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        }
    197193        return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    198194            endpoint, direction);
     
    219215    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    220216{
    221         usb_transfer_batch_t *batch = NULL;
    222         hc_t *hc = NULL;
    223         int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
    224             NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
    225         if (ret != EOK)
    226                 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;
    227235        batch_interrupt_out(batch);
    228         ret = hc_schedule(hc, batch);
     236        const int ret = hc_schedule(hc, batch);
    229237        if (ret != EOK) {
    230238                batch_dispose(batch);
     
    253261    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    254262{
    255         usb_transfer_batch_t *batch = NULL;
    256         hc_t *hc = NULL;
    257         int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
    258             NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
    259         if (ret != EOK)
    260                 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;
    261280        batch_interrupt_in(batch);
    262         ret = hc_schedule(hc, batch);
     281        const int ret = hc_schedule(hc, batch);
    263282        if (ret != EOK) {
    264283                batch_dispose(batch);
     
    287306    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
    288307{
    289         usb_transfer_batch_t *batch = NULL;
    290         hc_t *hc = NULL;
    291         int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
    292             NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
    293         if (ret != EOK)
    294                 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;
    295326        batch_bulk_out(batch);
    296         ret = hc_schedule(hc, batch);
     327        const int ret = hc_schedule(hc, batch);
    297328        if (ret != EOK) {
    298329                batch_dispose(batch);
     
    321352    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
    322353{
    323         usb_transfer_batch_t *batch = NULL;
    324         hc_t *hc = NULL;
    325         int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
    326             NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
    327         if (ret != EOK)
    328                 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;
    329371        batch_bulk_in(batch);
    330         ret = hc_schedule(hc, batch);
     372        const int ret = hc_schedule(hc, batch);
    331373        if (ret != EOK) {
    332374                batch_dispose(batch);
     
    359401    usbhc_iface_transfer_out_callback_t callback, void *arg)
    360402{
    361         usb_transfer_batch_t *batch = NULL;
    362         hc_t *hc = NULL;
    363         int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
    364             setup_data, setup_size, NULL, callback, arg, "Control WRITE",
    365             &hc, &batch);
    366         if (ret != EOK)
    367                 return ret;
    368         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);
    369425        batch_control_write(batch);
    370         ret = hc_schedule(hc, batch);
     426        const int ret = hc_schedule(hc, batch);
    371427        if (ret != EOK) {
    372428                batch_dispose(batch);
     
    399455    usbhc_iface_transfer_in_callback_t callback, void *arg)
    400456{
    401         usb_transfer_batch_t *batch = NULL;
    402         hc_t *hc = NULL;
    403         int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
    404             setup_data, setup_size, callback, NULL, arg, "Control READ",
    405             &hc, &batch);
    406         if (ret != EOK)
    407                 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;
    408475        batch_control_read(batch);
    409         ret = hc_schedule(hc, batch);
     476        const int ret = hc_schedule(hc, batch);
    410477        if (ret != EOK) {
    411478                batch_dispose(batch);
     
    414481}
    415482/*----------------------------------------------------------------------------*/
     483/** Host controller interface implementation for OHCI. */
    416484usbhc_iface_t hc_iface = {
     485        .reserve_default_address = reserve_default_address,
     486        .release_default_address = release_default_address,
    417487        .request_address = request_address,
    418488        .bind_address = bind_address,
     
    431501        .control_read = control_read,
    432502};
     503
    433504/**
    434505 * @}
Note: See TracChangeset for help on using the changeset viewer.