Changeset 1affef2f in mainline


Ignore:
Timestamp:
2012-12-22T23:20:45Z (11 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3c4663e
Parents:
a6a9910
Message:

libusbhost: Use callback wrapper for toggle handling.

Location:
uspace/lib/usbhost
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbhost/include/usb/host/hcd.h

    ra6a9910 r1affef2f  
    8282}
    8383
    84 /** Check registered endpoints and reset toggle bit if necessary.
    85  * @param hcd hcd_t structure, non-null.
    86  * @param target Control communication target.
    87  * @param setup_data Setup packet of the control communication.
    88  */
    89 static inline void reset_ep_if_need(hcd_t *hcd, usb_target_t target,
    90     const char setup_data[8])
    91 {
    92         assert(hcd);
    93         usb_endpoint_manager_reset_eps_if_need(
    94             &hcd->ep_manager, target, (const uint8_t *)setup_data);
    95 }
    96 
    9784int hcd_send_batch(
    9885    hcd_t *hcd, ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
     
    10087    usbhc_iface_transfer_in_callback_t in,
    10188    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name);
    102 
    10389
    10490/** Data retrieve wrapper.
  • uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h

    ra6a9910 r1affef2f  
    7676    size_t available_bandwidth, bw_count_func_t bw_count);
    7777
    78 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance,
    79     usb_target_t target, const uint8_t data[8]);
    80 
    8178int usb_endpoint_manager_register_ep(
    8279    usb_endpoint_manager_t *instance, endpoint_t *ep, size_t data_size);
     80
    8381int usb_endpoint_manager_unregister_ep(
    8482    usb_endpoint_manager_t *instance, endpoint_t *ep);
  • uspace/lib/usbhost/src/hcd.c

    ra6a9910 r1affef2f  
    3838#include <usb_iface.h>
    3939#include <usb/debug.h>
     40#include <usb/request.h>
    4041
    4142#include <usb/host/hcd.h>
     
    6061        hcd->ep_add_hook = NULL;
    6162        hcd->ep_remove_hook = NULL;
     63}
     64
     65typedef struct {
     66        void *original_data;
     67        usbhc_iface_transfer_out_callback_t original_callback;
     68        usb_target_t target;
     69        hcd_t *hcd;
     70} toggle_t;
     71
     72static void toggle_reset_callback(int retval, void *arg)
     73{
     74        assert(arg);
     75        toggle_t *toggle = arg;
     76        if (retval == EOK) {
     77                usb_log_debug2("Reseting toggle on %d:%d.\n",
     78                    toggle->target.address, toggle->target.endpoint);
     79                usb_endpoint_manager_reset_toggle(&toggle->hcd->ep_manager,
     80                    toggle->target, toggle->target.endpoint == 0);
     81        }
     82
     83        toggle->original_callback(retval, toggle->original_data);
    6284}
    6385
     
    106128        }
    107129
    108         /* No private data and no private data dtor */
    109         usb_transfer_batch_t *batch =
    110             usb_transfer_batch_create(ep, data, size, setup_data,
    111             in, out, arg, fun);
     130        /* Check for commands that reset toggle bit */
     131        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     132                const int reset_toggle = usb_request_needs_toggle_reset(
     133                    (usb_device_request_setup_packet_t *) &setup_data);
     134                if (reset_toggle >= 0) {
     135                        assert(out);
     136                        toggle_t *toggle = malloc(sizeof(toggle_t));
     137                        if (!toggle)
     138                                return ENOMEM;
     139                        toggle->target.address = target.address;
     140                        toggle->target.endpoint = reset_toggle;
     141                        toggle->original_callback = out;
     142                        toggle->original_data = arg;
     143                        toggle->hcd = hcd;
     144
     145                        arg = toggle;
     146                        out = toggle_reset_callback;
     147                }
     148        }
     149
     150        usb_transfer_batch_t *batch = usb_transfer_batch_create(
     151            ep, data, size, setup_data, in, out, arg, fun);
    112152        if (!batch) {
    113153                return ENOMEM;
  • uspace/lib/usbhost/src/usb_endpoint_manager.c

    ra6a9910 r1affef2f  
    168168}
    169169
    170 /** Check setup packet data for signs of toggle reset.
    171  *
    172  * @param[in] instance usb_endpoint_manager structure, non-null.
    173  * @param[in] target Device to receive setup packet.
    174  * @param[in] data Setup packet data.
    175  *
    176  * Really ugly one. Resets toggle bit on all endpoints that need it.
    177  * @TODO Use tools from libusbdev requests.h
    178  */
    179 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance,
    180     usb_target_t target, const uint8_t data[8])
    181 {
    182         assert(instance);
    183         if (!usb_target_is_valid(target)) {
    184                 usb_log_error("Invalid data when checking for toggle reset.\n");
    185                 return;
    186         }
    187 
    188         assert(data);
    189         switch (data[1])
    190         {
    191         case 0x01: /* Clear Feature -- resets only cleared ep */
    192                 /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */
    193                 // TODO Use macros in libusbdev requests.h
    194                 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    195                         fibril_mutex_lock(&instance->guard);
    196                         /* endpoint number is < 16, thus first byte is enough */
    197                         list_foreach(*get_list(instance, target.address), it) {
    198                                 endpoint_t *ep = endpoint_get_instance(it);
    199                                 if ((ep->address == target.address)
    200                                     && (ep->endpoint = data[4])) {
    201                                         endpoint_toggle_set(ep,0);
    202                                 }
    203                         }
    204                         fibril_mutex_unlock(&instance->guard);
    205                 }
    206         break;
    207 
    208         case 0x9: /* Set Configuration */
    209         case 0x11: /* Set Interface */
    210                 /* Recipient must be device, this resets all endpoints,
    211                  * In fact there should be no endpoints but EP 0 registered
    212                  * as different interfaces use different endpoints,
    213                  * unless you're changing configuration or alternative
    214                  * interface of an already setup device. */
    215                 if ((data[0] & 0xf) == 0) {
    216                         fibril_mutex_lock(&instance->guard);
    217                         list_foreach(*get_list(instance, target.address), it) {
    218                                 endpoint_t *ep = endpoint_get_instance(it);
    219                                 if (ep->address == target.address) {
    220                                         endpoint_toggle_set(ep,0);
    221                                 }
    222                         }
    223                         fibril_mutex_unlock(&instance->guard);
    224                 }
    225         break;
    226         }
    227 }
    228 
    229170/** Register endpoint structure.
    230171 * Checks for duplicates.
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    ra6a9910 r1affef2f  
    125125        /* NOTE: Only one of these pointers should be set. */
    126126        if (instance->callback_out) {
    127                 /* Check for commands that reset toggle bit */
    128                 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL
    129                     && error == EOK) {
    130                         const usb_target_t target =
    131                             {{ instance->ep->address, instance->ep->endpoint }};
    132                         reset_ep_if_need(fun_to_hcd(instance->fun), target,
    133                             instance->setup_buffer);
    134                 }
    135127                instance->callback_out(error, instance->arg);
    136128        }
Note: See TracChangeset for help on using the changeset viewer.