Changeset df6ded8 in mainline for uspace/lib/usbhost/include


Ignore:
Timestamp:
2018-02-28T16:37:50Z (8 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1b20da0
Parents:
f5e5f73 (diff), b2dca8de (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Jakub Jermar <jakub@…> (2018-02-28 16:06:42)
git-committer:
Jakub Jermar <jakub@…> (2018-02-28 16:37:50)
Message:

Merge github.com:helenos-xhci-team/helenos

This commit merges support for USB 3 and generally refactors, fixes,
extends and cleans up the existing USB framework.

Notable additions and features:

  • new host controller driver has been implemented to control various xHC models (among others, NEC Renesas uPD720200)
  • isochronous data transfer mode
  • support for explicit USB device removal
  • USB tablet driver
Location:
uspace/lib/usbhost/include/usb/host
Files:
4 added
1 deleted
4 edited

Legend:

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

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2012 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    3738#define LIBUSBHOST_HOST_DDF_HELPERS_H
    3839
    39 #include <usb/host/hcd.h>
    40 #include <usb/host/usb_bus.h>
     40#include <ddf/driver.h>
     41#include <ddf/interrupt.h>
    4142#include <usb/usb.h>
    4243
    43 #include <ddf/driver.h>
    44 #include <ddf/interrupt.h>
    45 #include <device/hw_res_parsed.h>
     44#include <usb/host/hcd.h>
     45#include <usb/descriptor.h>
    4646
    47 typedef errno_t (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, bool);
    48 typedef void (*driver_fini_t)(hcd_t *);
    49 typedef errno_t (*claim_t)(ddf_dev_t *);
    50 typedef errno_t (*irq_code_gen_t)(irq_code_t *, const hw_res_list_parsed_t *, int *);
    5147
    52 typedef struct {
    53         hcd_ops_t ops;
    54         claim_t claim;
    55         usb_speed_t hc_speed;
    56         driver_init_t init;
    57         driver_fini_t fini;
    58         interrupt_handler_t *irq_handler;
    59         irq_code_gen_t irq_code_gen;
    60         const char *name;
    61 } ddf_hc_driver_t;
     48errno_t hcd_ddf_setup_hc(ddf_dev_t *, size_t);
     49void hcd_ddf_clean_hc(hc_device_t *);
    6250
    63 errno_t hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver);
    6451
    65 errno_t hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed,
    66     size_t bw, bw_count_func_t bw_count);
    67 void hcd_ddf_clean_hc(ddf_dev_t *device);
    68 errno_t hcd_ddf_setup_root_hub(ddf_dev_t *device);
     52device_t *hcd_ddf_fun_create(hc_device_t *, usb_speed_t);
     53void hcd_ddf_fun_destroy(device_t *);
    6954
    70 hcd_t *dev_to_hcd(ddf_dev_t *dev);
     55errno_t hcd_ddf_setup_match_ids(device_t *, usb_standard_device_descriptor_t *);
    7156
    72 errno_t hcd_ddf_enable_interrupt(ddf_dev_t *device, int);
    73 errno_t hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res);
    74 errno_t hcd_ddf_setup_interrupts(ddf_dev_t *device,
    75     const hw_res_list_parsed_t *hw_res,
    76     interrupt_handler_t handler,
    77     errno_t (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *, int *),
    78     cap_handle_t *handle);
    79 void ddf_hcd_gen_irq_handler(ipc_call_t *call, ddf_dev_t *dev);
     57errno_t hcd_ddf_enable_interrupt(hc_device_t *hcd, int);
     58errno_t hcd_ddf_get_registers(hc_device_t *hcd, hw_res_list_parsed_t *hw_res);
     59
     60void hcd_ddf_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev);
    8061
    8162#endif
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    3233/** @file
    3334 *
     35 * Endpoint structure is tightly coupled to the bus. The bus controls the
     36 * life-cycle of endpoint. In order to keep endpoints lightweight, operations
     37 * on endpoints are part of the bus structure.
     38 *
    3439 */
    3540#ifndef LIBUSBHOST_HOST_ENDPOINT_H
    3641#define LIBUSBHOST_HOST_ENDPOINT_H
    3742
     43#include <adt/list.h>
     44#include <atomic.h>
     45#include <fibril_synch.h>
    3846#include <stdbool.h>
    39 #include <adt/list.h>
    40 #include <fibril_synch.h>
     47#include <sys/time.h>
    4148#include <usb/usb.h>
    42 #include <atomic.h>
     49#include <usb/host/bus.h>
     50#include <usbhc_iface.h>
    4351
    44 /** Host controller side endpoint structure. */
     52typedef struct bus bus_t;
     53typedef struct device device_t;
     54typedef struct transfer_request transfer_request_t;
     55typedef struct usb_transfer_batch usb_transfer_batch_t;
     56
     57/**
     58 * Host controller side endpoint structure.
     59 *
     60 * This structure, though reference-counted, is very fragile. It is responsible
     61 * for synchronizing transfer batch scheduling and completion.
     62 *
     63 * To avoid situations, in which two locks must be obtained to schedule/finish
     64 * a transfer, the endpoint inherits a lock from the outside. Because the
     65 * concrete instance of mutex can be unknown at the time of initialization,
     66 * the HC shall pass the right lock at the time of onlining the endpoint.
     67 *
     68 * The fields used for scheduling (online, active_batch) are to be used only
     69 * under that guard and by functions designed for this purpose. The driver can
     70 * also completely avoid using this mechanism, in which case it is on its own in
     71 * question of transfer aborting.
     72 *
     73 * Relevant information can be found in the documentation of HelenOS xHCI
     74 * project.
     75 */
    4576typedef struct endpoint {
     77        /** USB device */
     78        device_t *device;
    4679        /** Reference count. */
    47         atomic_t refcnt;       
    48         /** Part of linked list. */
    49         link_t link;
    50         /** USB address. */
    51         usb_address_t address;
    52         /** USB endpoint number. */
     80        atomic_t refcnt;
     81
     82        /** An inherited guard */
     83        fibril_mutex_t *guard;
     84        /** Whether it's allowed to schedule on this endpoint */
     85        bool online;
     86        /** The currently active transfer batch. */
     87        usb_transfer_batch_t *active_batch;
     88        /** Signals change of active status. */
     89        fibril_condvar_t avail;
     90
     91        /** Endpoint number */
    5392        usb_endpoint_t endpoint;
    5493        /** Communication direction. */
     
    5695        /** USB transfer type. */
    5796        usb_transfer_type_t transfer_type;
    58         /** Communication speed. */
    59         usb_speed_t speed;
    60         /** Maximum size of data packets. */
     97        /** Maximum size of one packet */
    6198        size_t max_packet_size;
    62         /** Additional opportunities per uframe */
    63         unsigned packets;
    64         /** Necessary bandwidth. */
    65         size_t bandwidth;
    66         /** Value of the toggle bit. */
    67         unsigned toggle:1;
    68         /** True if there is a batch using this scheduled for this endpoint. */
    69         volatile bool active;
    70         /** Protects resources and active status changes. */
    71         fibril_mutex_t guard;
    72         /** Signals change of active status. */
    73         fibril_condvar_t avail;
    74         /** High speed TT data */
    75         struct {
    76                 usb_address_t address;
    77                 unsigned port;
    78         } tt;
    79         /** Optional device specific data. */
    80         struct {
    81                 /** Device specific data. */
    82                 void *data;
    83                 /** Callback to get the value of toggle bit. */
    84                 int (*toggle_get)(void *);
    85                 /** Callback to set the value of toggle bit. */
    86                 void (*toggle_set)(void *, int);
    87         } hc_data;
     99
     100        /** Maximum size of one transfer */
     101        size_t max_transfer_size;
     102
     103        /* Policies for transfer buffers */
     104        /** A hint for optimal performance. */
     105        dma_policy_t transfer_buffer_policy;
     106        /** Enforced by the library. */
     107        dma_policy_t required_transfer_buffer_policy;
     108
     109        /**
     110         * Number of packets that can be sent in one service interval
     111         * (not necessarily uframe, despite its name)
     112         */
     113        unsigned packets_per_uframe;
     114
     115        /* This structure is meant to be extended by overriding. */
    88116} endpoint_t;
    89117
    90 extern endpoint_t *endpoint_create(usb_address_t, usb_endpoint_t,
    91     usb_direction_t, usb_transfer_type_t, usb_speed_t, size_t, unsigned int,
    92     size_t, usb_address_t, unsigned int);
    93 extern void endpoint_destroy(endpoint_t *);
     118extern void endpoint_init(endpoint_t *, device_t *,
     119    const usb_endpoint_descriptors_t *);
    94120
    95121extern void endpoint_add_ref(endpoint_t *);
    96122extern void endpoint_del_ref(endpoint_t *);
    97123
    98 extern void endpoint_set_hc_data(endpoint_t *, void *, int (*)(void *),
    99     void (*)(void *, int));
    100 extern void endpoint_clear_hc_data(endpoint_t *);
     124extern void endpoint_set_online(endpoint_t *, fibril_mutex_t *);
     125extern void endpoint_set_offline_locked(endpoint_t *);
    101126
    102 extern void endpoint_use(endpoint_t *);
    103 extern void endpoint_release(endpoint_t *);
     127extern void endpoint_wait_timeout_locked(endpoint_t *ep, suseconds_t);
     128extern int endpoint_activate_locked(endpoint_t *, usb_transfer_batch_t *);
     129extern void endpoint_deactivate_locked(endpoint_t *);
    104130
    105 extern int endpoint_toggle_get(endpoint_t *);
    106 extern void endpoint_toggle_set(endpoint_t *, int);
     131int endpoint_send_batch(endpoint_t *, const transfer_request_t *);
    107132
    108 /** list_get_instance wrapper.
    109  *
    110  * @param item Pointer to link member.
    111  *
    112  * @return Pointer to endpoint_t structure.
    113  *
    114  */
    115 static inline endpoint_t * endpoint_get_instance(link_t *item)
     133static inline bus_t *endpoint_get_bus(endpoint_t *ep)
    116134{
    117         return item ? list_get_instance(item, endpoint_t, link) : NULL;
     135        device_t * const device = ep->device;
     136        return device ? device->bus : NULL;
    118137}
     138
    119139#endif
    120140
  • uspace/lib/usbhost/include/usb/host/hcd.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    3738#define LIBUSBHOST_HOST_HCD_H
    3839
    39 #include <usb/host/endpoint.h>
    40 #include <usb/host/usb_bus.h>
    41 #include <usb/host/usb_transfer_batch.h>
    42 #include <usb/usb.h>
     40#include <ddf/driver.h>
     41#include <usb/request.h>
    4342
    44 #include <assert.h>
    45 #include <usbhc_iface.h>
    46 #include <stddef.h>
    47 #include <stdint.h>
     43typedef struct hw_resource_list_parsed hw_res_list_parsed_t;
     44typedef struct bus bus_t;
     45typedef struct device device_t;
    4846
    49 typedef struct hcd hcd_t;
     47/* Treat this header as read-only in driver code.
     48 * It could be opaque, but why to complicate matters.
     49 */
     50typedef struct hc_device {
     51        /* Bus instance */
     52        bus_t *bus;
    5053
    51 typedef errno_t (*schedule_hook_t)(hcd_t *, usb_transfer_batch_t *);
    52 typedef errno_t (*ep_add_hook_t)(hcd_t *, endpoint_t *);
    53 typedef void (*ep_remove_hook_t)(hcd_t *, endpoint_t *);
    54 typedef void (*interrupt_hook_t)(hcd_t *, uint32_t);
    55 typedef errno_t (*status_hook_t)(hcd_t *, uint32_t *);
     54        /* Managed DDF device */
     55        ddf_dev_t *ddf_dev;
    5656
    57 typedef struct {
    58         /** Transfer scheduling, implement in device driver. */
    59         schedule_hook_t schedule;
    60         /** Hook called upon registering new endpoint. */
    61         ep_add_hook_t ep_add_hook;
    62         /** Hook called upon removing of an endpoint. */
    63         ep_remove_hook_t ep_remove_hook;
    64         /** Hook to be called on device interrupt, passes ARG1 */
    65         interrupt_hook_t irq_hook;
    66         /** Periodic polling hook */
    67         status_hook_t status_hook;
    68 } hcd_ops_t;
     57        /* Control function */
     58        ddf_fun_t *ctl_fun;
    6959
    70 /** Generic host controller driver structure. */
    71 struct hcd {
    72         /** Endpoint manager. */
    73         usb_bus_t bus;
     60        /* Result of enabling HW IRQs */
     61        int irq_cap;
    7462
    7563        /** Interrupt replacement fibril */
    7664        fid_t polling_fibril;
    7765
    78         /** Driver implementation */
    79         hcd_ops_t ops;
    80         /** Device specific driver data. */
    81         void * driver_data;
    82 };
     66        /* This structure is meant to be extended by driver code. */
     67} hc_device_t;
    8368
    84 extern void hcd_init(hcd_t *, usb_speed_t, size_t, bw_count_func_t);
     69typedef struct hc_driver {
     70        const char *name;
    8571
    86 static inline void hcd_set_implementation(hcd_t *hcd, void *data,
    87     const hcd_ops_t *ops)
     72        /** Size of the device data to be allocated, and passed as the
     73         * hc_device_t. */
     74        size_t hc_device_size;
     75
     76        /** Initialize device structures. */
     77        int (*hc_add)(hc_device_t *, const hw_res_list_parsed_t *);
     78
     79        /** Generate IRQ code to handle interrupts. */
     80        int (*irq_code_gen)(irq_code_t *, hc_device_t *,
     81            const hw_res_list_parsed_t *, int *);
     82
     83        /** Claim device from BIOS. */
     84        int (*claim)(hc_device_t *);
     85
     86        /** Start the host controller. */
     87        int (*start)(hc_device_t *);
     88
     89        /** Setup the virtual roothub. */
     90        int (*setup_root_hub)(hc_device_t *);
     91
     92        /** Stop the host controller (after start has been called) */
     93        int (*stop)(hc_device_t *);
     94
     95        /** HC was asked to be removed (after hc_add has been called) */
     96        int (*hc_remove)(hc_device_t *);
     97
     98        /** HC is gone. */
     99        int (*hc_gone)(hc_device_t *);
     100} hc_driver_t;
     101
     102/* Drivers should call this before leaving hc_add */
     103static inline void hc_device_setup(hc_device_t *hcd, bus_t *bus)
    88104{
    89         assert(hcd);
    90         if (ops) {
    91                 hcd->driver_data = data;
    92                 hcd->ops = *ops;
    93         } else {
    94                 memset(&hcd->ops, 0, sizeof(hcd->ops));
    95         }
     105        hcd->bus = bus;
    96106}
    97107
    98 static inline void * hcd_get_driver_data(hcd_t *hcd)
     108static inline hc_device_t *dev_to_hcd(ddf_dev_t *dev)
    99109{
    100         assert(hcd);
    101         return hcd->driver_data;
     110        return ddf_dev_data_get(dev);
    102111}
    103112
    104 extern errno_t hcd_request_address(hcd_t *, usb_speed_t, usb_address_t *);
    105 
    106 extern errno_t hcd_release_address(hcd_t *, usb_address_t);
    107 
    108 extern errno_t hcd_reserve_default_address(hcd_t *, usb_speed_t);
    109 
    110 static inline errno_t hcd_release_default_address(hcd_t *hcd)
    111 {
    112         return hcd_release_address(hcd, USB_ADDRESS_DEFAULT);
    113 }
    114 
    115 extern errno_t hcd_add_ep(hcd_t *, usb_target_t, usb_direction_t,
    116     usb_transfer_type_t, size_t, unsigned int, size_t, usb_address_t,
    117     unsigned int);
    118 
    119 extern errno_t hcd_remove_ep(hcd_t *, usb_target_t, usb_direction_t);
    120 
    121 extern errno_t hcd_send_batch(hcd_t *, usb_target_t, usb_direction_t, void *,
    122     size_t, uint64_t, usbhc_iface_transfer_in_callback_t,
    123     usbhc_iface_transfer_out_callback_t, void *, const char *);
    124 
    125 extern errno_t hcd_send_batch_sync(hcd_t *, usb_target_t, usb_direction_t,
    126     void *, size_t, uint64_t, const char *, size_t *);
     113extern errno_t hc_driver_main(const hc_driver_t *);
    127114
    128115#endif
  • uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h

    rf5e5f73 rdf6ded8  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
     3 * Copyright (c) 2018 Ondrej Hlavaty
    34 * All rights reserved.
    45 *
     
    3738#define LIBUSBHOST_HOST_USB_TRANSFER_BATCH_H
    3839
    39 #include <usb/host/endpoint.h>
    40 #include <usb/usb.h>
    41 
    42 #include <assert.h>
     40#include <atomic.h>
     41#include <errno.h>
    4342#include <stddef.h>
    4443#include <stdint.h>
     44#include <usb/dma_buffer.h>
     45#include <usb/request.h>
     46#include <usb/usb.h>
    4547#include <usbhc_iface.h>
    4648
    47 #define USB_SETUP_PACKET_SIZE 8
     49#include <usb/host/hcd.h>
     50#include <usb/host/endpoint.h>
     51#include <usb/host/bus.h>
     52
     53typedef struct endpoint endpoint_t;
     54typedef struct bus bus_t;
    4855
    4956/** Structure stores additional data needed for communication with EP */
    5057typedef struct usb_transfer_batch {
     58        /** Target for communication */
     59        usb_target_t target;
     60        /** Direction of the transfer */
     61        usb_direction_t dir;
     62
    5163        /** Endpoint used for communication */
    5264        endpoint_t *ep;
    53         /** Function called on completion (IN version) */
    54         usbhc_iface_transfer_in_callback_t callback_in;
    55         /** Function called on completion (OUT version) */
    56         usbhc_iface_transfer_out_callback_t callback_out;
    57         /** Argument to pass to the completion function */
    58         void *arg;
    59         /** Place for data to send/receive */
    60         char *buffer;
    61         /** Size of memory pointed to by buffer member */
    62         size_t buffer_size;
     65
    6366        /** Place to store SETUP data needed by control transfers */
    64         char setup_buffer[USB_SETUP_PACKET_SIZE];
    65         /** Used portion of setup_buffer member
    66          *
    67          * SETUP buffer must be 8 bytes for control transfers and is left
    68          * unused for all other transfers. Thus, this field is either 0 or 8.
     67        union {
     68                char buffer [USB_SETUP_PACKET_SIZE];
     69                usb_device_request_setup_packet_t packet;
     70                uint64_t packed;
     71        } setup;
     72
     73        /** DMA buffer with enforced policy */
     74        dma_buffer_t dma_buffer;
     75        /** Size of memory buffer */
     76        size_t offset, size;
     77
     78        /**
     79         * In case a bounce buffer is allocated, the original buffer must to be
     80         * stored to be filled after the IN transaction is finished.
    6981         */
    70         size_t setup_size;
     82        char *original_buffer;
     83        bool is_bounced;
    7184
    72         /** Actually used portion of the buffer
    73          * This member is never accessed by functions provided in this header,
    74          * with the exception of usb_transfer_batch_finish. For external use.
    75          */
    76         size_t transfered_size;
    77         /** Indicates success/failure of the communication
    78          * This member is never accessed by functions provided in this header,
    79          * with the exception of usb_transfer_batch_finish. For external use.
    80          */
     85        /** Indicates success/failure of the communication */
    8186        errno_t error;
     87        /** Actually used portion of the buffer */
     88        size_t transferred_size;
     89
     90        /** Function called on completion */
     91        usbhc_iface_transfer_callback_t on_complete;
     92        /** Arbitrary data for the handler */
     93        void *on_complete_data;
    8294} usb_transfer_batch_t;
    8395
    84 /** Printf formatting string for dumping usb_transfer_batch_t. */
     96/**
     97 * Printf formatting string for dumping usb_transfer_batch_t.
     98 *  [address:endpoint speed transfer_type-direction buffer_sizeB/max_packet_size]
     99 * */
    85100#define USB_TRANSFER_BATCH_FMT "[%d:%d %s %s-%s %zuB/%zu]"
    86101
     
    89104 */
    90105#define USB_TRANSFER_BATCH_ARGS(batch) \
    91         (batch).ep->address, (batch).ep->endpoint, \
    92         usb_str_speed((batch).ep->speed), \
     106        ((batch).ep->device->address), ((batch).ep->endpoint), \
     107        usb_str_speed((batch).ep->device->speed), \
    93108        usb_str_transfer_type_short((batch).ep->transfer_type), \
    94         usb_str_direction((batch).ep->direction), \
    95         (batch).buffer_size, (batch).ep->max_packet_size
     109        usb_str_direction((batch).dir), \
     110        (batch).size, (batch).ep->max_packet_size
    96111
     112/** Wrapper for bus operation. */
     113usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *);
    97114
    98 usb_transfer_batch_t * usb_transfer_batch_create(
    99     endpoint_t *ep,
    100     char *buffer,
    101     size_t buffer_size,
    102     uint64_t setup_buffer,
    103     usbhc_iface_transfer_in_callback_t func_in,
    104     usbhc_iface_transfer_out_callback_t func_out,
    105     void *arg
    106 );
    107 void usb_transfer_batch_destroy(usb_transfer_batch_t *instance);
     115/** Batch initializer. */
     116void usb_transfer_batch_init(usb_transfer_batch_t *, endpoint_t *);
    108117
    109 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance,
    110     const void* data, size_t size, errno_t error);
     118/** Buffer handling */
     119bool usb_transfer_batch_bounce_required(usb_transfer_batch_t *);
     120errno_t usb_transfer_batch_bounce(usb_transfer_batch_t *);
    111121
    112 /** Finish batch using stored error value and transferred size.
    113  *
    114  * @param[in] instance Batch structure to use.
    115  * @param[in] data Data to copy to the output buffer.
     122/** Batch finalization. */
     123void usb_transfer_batch_finish(usb_transfer_batch_t *);
     124
     125/** To be called from outside only when the transfer is not going to be finished
     126 * (i.o.w. until successfuly scheduling)
    116127 */
    117 static inline void usb_transfer_batch_finish(
    118     const usb_transfer_batch_t *instance, const void* data)
    119 {
    120         assert(instance);
    121         usb_transfer_batch_finish_error(
    122             instance, data, instance->transfered_size, instance->error);
    123 }
    124 
    125 /** Determine batch direction based on the callbacks present
    126  * @param[in] instance Batch structure to use, non-null.
    127  * @return USB_DIRECTION_IN, or USB_DIRECTION_OUT.
    128  */
    129 static inline usb_direction_t usb_transfer_batch_direction(
    130     const usb_transfer_batch_t *instance)
    131 {
    132         assert(instance);
    133         if (instance->callback_in) {
    134                 assert(instance->callback_out == NULL);
    135                 assert(instance->ep == NULL
    136                     || instance->ep->transfer_type == USB_TRANSFER_CONTROL
    137                     || instance->ep->direction == USB_DIRECTION_IN);
    138                 return USB_DIRECTION_IN;
    139         }
    140         if (instance->callback_out) {
    141                 assert(instance->callback_in == NULL);
    142                 assert(instance->ep == NULL
    143                     || instance->ep->transfer_type == USB_TRANSFER_CONTROL
    144                     || instance->ep->direction == USB_DIRECTION_OUT);
    145                 return USB_DIRECTION_OUT;
    146         }
    147         assert(false);
    148 }
     128void usb_transfer_batch_destroy(usb_transfer_batch_t *);
    149129
    150130#endif
Note: See TracChangeset for help on using the changeset viewer.