Changeset b4b534ac in mainline for uspace/lib/usbhost


Ignore:
Timestamp:
2016-07-22T08:24:47Z (9 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f76d2c2
Parents:
5b18137 (diff), 8351f9a4 (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.
Message:

Merge from lp:~jan.vesely/helenos/usb

Location:
uspace/lib/usbhost
Files:
2 added
3 deleted
6 edited
4 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbhost/Makefile

    r5b18137 rb4b534ac  
    3232        -I$(LIBUSB_PREFIX)/include \
    3333        -I$(LIBDRV_PREFIX)/include \
     34        -Iinclude/usb/host \
    3435        -Iinclude
    3536
    3637SOURCES = \
     38        src/ddf_helpers.c \
    3739        src/endpoint.c \
    38         src/iface.c \
    39         src/usb_device_manager.c \
    40         src/usb_endpoint_manager.c \
     40        src/hcd.c \
     41        src/usb_bus.c \
    4142        src/usb_transfer_batch.c
    4243
  • uspace/lib/usbhost/include/usb/host/ddf_helpers.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2011 Vojtech Horky
     2 * Copyright (c) 2012 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbohci
     28
     29/** @addtogroup libusbhost
    2930 * @{
    3031 */
    3132/** @file
    32  * PCI related functions needed by OHCI driver.
     33 *
    3334 */
    34 #ifndef DRV_OHCI_RES_H
    35 #define DRV_OHCI_RES_H
     35
     36#ifndef LIBUSBHOST_HOST_DDF_HELPERS_H
     37#define LIBUSBHOST_HOST_DDF_HELPERS_H
     38
     39#include <usb/host/hcd.h>
     40#include <usb/host/usb_bus.h>
     41#include <usb/usb.h>
    3642
    3743#include <ddf/driver.h>
     44#include <ddf/interrupt.h>
    3845#include <device/hw_res_parsed.h>
    3946
    40 int get_my_registers(ddf_dev_t *, addr_range_t *, int *);
    41 int enable_interrupts(ddf_dev_t *);
     47typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, bool);
     48typedef void (*driver_fini_t)(hcd_t *);
     49typedef int (*claim_t)(ddf_dev_t *);
     50typedef int (*irq_code_gen_t)(irq_code_t *, const hw_res_list_parsed_t *);
     51
     52typedef 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;
     62
     63int hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver);
     64
     65int hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed,
     66    size_t bw, bw_count_func_t bw_count);
     67void hcd_ddf_clean_hc(ddf_dev_t *device);
     68int hcd_ddf_setup_root_hub(ddf_dev_t *device);
     69
     70hcd_t *dev_to_hcd(ddf_dev_t *dev);
     71
     72int hcd_ddf_enable_interrupts(ddf_dev_t *device);
     73int hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res);
     74int hcd_ddf_setup_interrupts(ddf_dev_t *device,
     75    const hw_res_list_parsed_t *hw_res,
     76    interrupt_handler_t handler,
     77    int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *));
     78void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev);
    4279
    4380#endif
     81
    4482/**
    4583 * @}
    4684 */
    47 
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    r5b18137 rb4b534ac  
    5757        /** Maximum size of data packets. */
    5858        size_t max_packet_size;
     59        /** Additional opportunities per uframe */
     60        unsigned packets;
    5961        /** Necessary bandwidth. */
    6062        size_t bandwidth;
     
    6769        /** Signals change of active status. */
    6870        fibril_condvar_t avail;
     71        /** High speed TT data */
     72        struct {
     73                usb_address_t address;
     74                unsigned port;
     75        } tt;
    6976        /** Optional device specific data. */
    7077        struct {
     
    8087endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint,
    8188    usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
    82     size_t max_packet_size, size_t bw);
     89    size_t max_packet_size, unsigned packets, size_t bw,
     90    usb_address_t tt_address, unsigned tt_port);
    8391void endpoint_destroy(endpoint_t *instance);
    8492
  • uspace/lib/usbhost/include/usb/host/hcd.h

    r5b18137 rb4b534ac  
    3737#define LIBUSBHOST_HOST_HCD_H
    3838
     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>
     43
    3944#include <assert.h>
    4045#include <usbhc_iface.h>
    41 
    42 #include <usb/host/usb_device_manager.h>
    43 #include <usb/host/usb_endpoint_manager.h>
    44 #include <usb/host/usb_transfer_batch.h>
     46#include <sys/types.h>
    4547
    4648typedef struct hcd hcd_t;
    4749
     50typedef int (*schedule_hook_t)(hcd_t *, usb_transfer_batch_t *);
     51typedef int (*ep_add_hook_t)(hcd_t *, endpoint_t *);
     52typedef void (*ep_remove_hook_t)(hcd_t *, endpoint_t *);
     53typedef void (*interrupt_hook_t)(hcd_t *, uint32_t);
     54typedef int (*status_hook_t)(hcd_t *, uint32_t *);
     55
     56typedef struct {
     57        /** Transfer scheduling, implement in device driver. */
     58        schedule_hook_t schedule;
     59        /** Hook called upon registering new endpoint. */
     60        ep_add_hook_t ep_add_hook;
     61        /** Hook called upon removing of an endpoint. */
     62        ep_remove_hook_t ep_remove_hook;
     63        /** Hook to be called on device interrupt, passes ARG1 */
     64        interrupt_hook_t irq_hook;
     65        /** Periodic polling hook */
     66        status_hook_t status_hook;
     67} hcd_ops_t;
     68
    4869/** Generic host controller driver structure. */
    4970struct hcd {
    50         /** Device manager storing handles and addresses. */
    51         usb_device_manager_t dev_manager;
    5271        /** Endpoint manager. */
    53         usb_endpoint_manager_t ep_manager;
     72        usb_bus_t bus;
    5473
     74        /** Interrupt replacement fibril */
     75        fid_t polling_fibril;
     76
     77        /** Driver implementation */
     78        hcd_ops_t ops;
    5579        /** Device specific driver data. */
    56         void *private_data;
    57         /** Transfer scheduling, implement in device driver. */
    58         int (*schedule)(hcd_t *, usb_transfer_batch_t *);
    59         /** Hook called upon registering new endpoint. */
    60         int (*ep_add_hook)(hcd_t *, endpoint_t *);
    61         /** Hook called upon removing of an endpoint. */
    62         void (*ep_remove_hook)(hcd_t *, endpoint_t *);
     80        void * driver_data;
    6381};
    6482
    65 /** Initialize hcd_t structure.
    66  * Initializes device and endpoint managers. Sets data and hook pointer to NULL.
    67  * @param hcd hcd_t structure to initialize, non-null.
    68  * @param bandwidth Available bandwidth, passed to endpoint manager.
    69  * @param bw_count Bandwidth compute function, passed to endpoint manager.
    70  */
    71 static inline void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth,
    72     size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t))
     83void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth,
     84    bw_count_func_t bw_count);
     85
     86static inline void hcd_set_implementation(hcd_t *hcd, void *data,
     87    const hcd_ops_t *ops)
    7388{
    7489        assert(hcd);
    75         usb_device_manager_init(&hcd->dev_manager, max_speed);
    76         usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count);
    77         hcd->private_data = NULL;
    78         hcd->schedule = NULL;
    79         hcd->ep_add_hook = NULL;
    80         hcd->ep_remove_hook = NULL;
     90        if (ops) {
     91                hcd->driver_data = data;
     92                hcd->ops = *ops;
     93        } else {
     94                memset(&hcd->ops, 0, sizeof(hcd->ops));
     95        }
    8196}
    8297
    83 /** Check registered endpoints and reset toggle bit if necessary.
    84  * @param hcd hcd_t structure, non-null.
    85  * @param target Control communication target.
    86  * @param setup_data Setup packet of the control communication.
    87  */
    88 static inline void reset_ep_if_need(hcd_t *hcd, usb_target_t target,
    89     const char setup_data[8])
     98static inline void * hcd_get_driver_data(hcd_t *hcd)
    9099{
    91100        assert(hcd);
    92         usb_endpoint_manager_reset_eps_if_need(
    93             &hcd->ep_manager, target, (const uint8_t *)setup_data);
     101        return hcd->driver_data;
    94102}
    95103
    96 /** Data retrieve wrapper.
    97  * @param fun ddf function, non-null.
    98  * @return pointer cast to hcd_t*.
    99  */
    100 static inline hcd_t *fun_to_hcd(ddf_fun_t *fun)
     104usb_address_t hcd_request_address(hcd_t *hcd, usb_speed_t speed);
     105
     106int hcd_release_address(hcd_t *hcd, usb_address_t address);
     107
     108int hcd_reserve_default_address(hcd_t *hcd, usb_speed_t speed);
     109
     110static inline int hcd_release_default_address(hcd_t *hcd)
    101111{
    102         return ddf_fun_data_get(fun);
     112        return hcd_release_address(hcd, USB_ADDRESS_DEFAULT);
    103113}
    104114
    105 extern usbhc_iface_t hcd_iface;
     115int hcd_add_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir,
     116    usb_transfer_type_t type, size_t max_packet_size, unsigned packets,
     117    size_t size, usb_address_t tt_address, unsigned tt_port);
     118
     119int hcd_remove_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir);
     120
     121int hcd_send_batch(hcd_t *hcd, usb_target_t target, usb_direction_t direction,
     122    void *data, size_t size, uint64_t setup_data,
     123    usbhc_iface_transfer_in_callback_t in,
     124    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name);
     125
     126ssize_t hcd_send_batch_sync(hcd_t *hcd, usb_target_t target,
     127    usb_direction_t dir, void *data, size_t size, uint64_t setup_data,
     128    const char* name);
    106129
    107130#endif
    108 
    109131/**
    110132 * @}
  • uspace/lib/usbhost/include/usb/host/usb_bus.h

    r5b18137 rb4b534ac  
    4040#define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H
    4141
     42#include <usb/host/endpoint.h>
     43#include <usb/usb.h>
     44
    4245#include <adt/list.h>
    4346#include <fibril_synch.h>
    44 #include <usb/usb.h>
     47#include <stdbool.h>
    4548
    46 #include <usb/host/endpoint.h>
    4749
    4850/** Bytes per second in FULL SPEED */
     
    5052/** 90% of total bandwidth is available for periodic transfers */
    5153#define BANDWIDTH_AVAILABLE_USB11 ((BANDWIDTH_TOTAL_USB11 / 10) * 9)
    52 /** 16 addresses per list */
    53 #define ENDPOINT_LIST_COUNT 8
     54
     55//TODO: Implement
     56#define BANDWIDTH_AVAILABLE_USB20  1
     57
     58typedef size_t (*bw_count_func_t)(usb_speed_t, usb_transfer_type_t, size_t, size_t);
     59typedef void (*ep_remove_callback_t)(endpoint_t *, void *);
     60typedef int (*ep_add_callback_t)(endpoint_t *, void *);
    5461
    5562/** Endpoint management structure */
    56 typedef struct usb_endpoint_manager {
    57         /** Store endpoint_t instances */
    58         list_t endpoint_lists[ENDPOINT_LIST_COUNT];
     63typedef struct usb_bus {
     64        struct {
     65                usb_speed_t speed;      /**< Device speed */
     66                bool occupied;          /**< The address is in use. */
     67                list_t endpoint_list;   /**< Store endpoint_t instances */
     68        } devices[USB_ADDRESS_COUNT];
    5969        /** Prevents races accessing lists */
    6070        fibril_mutex_t guard;
     
    6272        size_t free_bw;
    6373        /** Use this function to count bw required by EP */
    64         size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t);
    65 } usb_endpoint_manager_t;
     74        bw_count_func_t bw_count;
     75        /** Maximum speed allowed. */
     76        usb_speed_t max_speed;
     77        /** The last reserved address */
     78        usb_address_t last_address;
     79} usb_bus_t;
     80
    6681
    6782size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type,
    6883    size_t size, size_t max_packet_size);
     84size_t bandwidth_count_usb20(usb_speed_t speed, usb_transfer_type_t type,
     85    size_t size, size_t max_packet_size);
    6986
    70 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
    71     size_t available_bandwidth,
    72     size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t));
     87int usb_bus_init(usb_bus_t *instance,
     88    size_t available_bandwidth, bw_count_func_t bw_count, usb_speed_t max_speed);
    7389
    74 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance,
    75     usb_target_t target, const uint8_t data[8]);
     90int usb_bus_register_ep(usb_bus_t *instance, endpoint_t *ep, size_t data_size);
    7691
    77 int usb_endpoint_manager_register_ep(
    78     usb_endpoint_manager_t *instance, endpoint_t *ep, size_t data_size);
    79 int usb_endpoint_manager_unregister_ep(
    80     usb_endpoint_manager_t *instance, endpoint_t *ep);
    81 endpoint_t * usb_endpoint_manager_find_ep(usb_endpoint_manager_t *instance,
     92int usb_bus_unregister_ep(usb_bus_t *instance, endpoint_t *ep);
     93
     94endpoint_t * usb_bus_find_ep(usb_bus_t *instance,
    8295    usb_address_t address, usb_endpoint_t ep, usb_direction_t direction);
    8396
    84 int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
     97int usb_bus_add_ep(usb_bus_t *instance,
    8598    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
    86     usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size,
    87     size_t data_size, int (*callback)(endpoint_t *, void *), void *arg);
     99    usb_transfer_type_t type, size_t max_packet_size, unsigned packets,
     100    size_t data_size, ep_add_callback_t callback, void *arg,
     101    usb_address_t tt_address, unsigned tt_port);
    88102
    89 int usb_endpoint_manager_remove_ep(usb_endpoint_manager_t *instance,
     103int usb_bus_remove_ep(usb_bus_t *instance,
    90104    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
    91     void (*callback)(endpoint_t *, void *), void *arg);
     105    ep_remove_callback_t callback, void *arg);
    92106
    93 void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance,
    94     usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg);
     107int usb_bus_reset_toggle(usb_bus_t *instance, usb_target_t target, bool all);
     108
     109int usb_bus_remove_address(usb_bus_t *instance,
     110    usb_address_t address, ep_remove_callback_t callback, void *arg);
     111
     112int usb_bus_request_address(usb_bus_t *instance,
     113    usb_address_t *address, bool strict, usb_speed_t speed);
     114
     115int usb_bus_get_speed(usb_bus_t *instance,
     116    usb_address_t address, usb_speed_t *speed);
    95117#endif
    96118/**
  • uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h

    r5b18137 rb4b534ac  
    3737#define LIBUSBHOST_HOST_USB_TRANSFER_BATCH_H
    3838
    39 #include <adt/list.h>
     39#include <usb/host/endpoint.h>
     40#include <usb/usb.h>
    4041
     42#include <assert.h>
     43#include <stdbool.h>
     44#include <sys/types.h>
    4145#include <usbhc_iface.h>
    42 #include <usb/usb.h>
    43 #include <usb/host/endpoint.h>
    4446
    4547#define USB_SETUP_PACKET_SIZE 8
     
    6769         */
    6870        size_t setup_size;
    69         /** Host controller function, passed to callback function */
    70         ddf_fun_t *fun;
    7171
    7272        /** Actually used portion of the buffer
     
    8080         */
    8181        int error;
    82 
    83         /** Driver specific data */
    84         void *private_data;
    85         /** Callback to properly remove driver data during destruction */
    86         void (*private_data_dtor)(void *p_data);
    8782} usb_transfer_batch_t;
    8883
     
    108103    usbhc_iface_transfer_in_callback_t func_in,
    109104    usbhc_iface_transfer_out_callback_t func_out,
    110     void *arg,
    111     ddf_fun_t *fun,
    112     void *private_data,
    113     void (*private_data_dtor)(void *p_data)
     105    void *arg
    114106);
    115107void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance);
  • uspace/lib/usbhost/include/usb/host/utils/malloc32.h

    r5b18137 rb4b534ac  
    11/*
    2  * Copyright (c) 2010 Jan Vesely
     2 * Copyright (c) 2013 Jan Vesely
    33 * All rights reserved.
    44 *
     
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbohci
     28/** @addtogroup drvusbehci
    2929 * @{
    3030 */
    3131/** @file
    32  * @brief OHCI driver
     32 * @brief EHCI driver
    3333 */
    34 #ifndef DRV_OHCI_UTILS_MALLOC32_H
    35 #define DRV_OHCI_UTILS_MALLOC32_H
     34#ifndef DRV_EHCI_UTILS_MALLOC32_H
     35#define DRV_EHCI_UTILS_MALLOC32_H
    3636
    37 #include <assert.h>
    38 #include <malloc.h>
    39 #include <unistd.h>
     37#include <align.h>
     38#include <as.h>
     39#include <ddi.h>
    4040#include <errno.h>
    41 #include <mem.h>
    42 #include <as.h>
     41#include <stdlib.h>
     42#include <sys/types.h>
    4343
    4444/* Generic TDs and EDs require 16byte alignment,
     
    4646 * buffers do not have to be aligned.
    4747 */
    48 #define OHCI_ALIGN 32
     48#define EHCI_ALIGN   32
     49
     50#define EHCI_REQUIRED_PAGE_SIZE   4096
    4951
    5052/** Get physical address translation
     
    7072 */
    7173static inline void * malloc32(size_t size)
    72         { return memalign(OHCI_ALIGN, size); }
     74{
     75        uintptr_t phys;
     76        void *address = AS_AREA_ANY;
     77        size_t real_size = ALIGN_UP(size, PAGE_SIZE);
     78
     79        const int ret = dmamem_map_anonymous(real_size,
     80            DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0, &phys,
     81            &address);
     82
     83        if (ret == EOK) {
     84                /* Poison, accessing it should be enough to make sure
     85                 * the location is mapped, but poison works better */
     86                memset(address, 0x5, real_size);
     87                return address;
     88        }
     89        return NULL;
     90}
    7391
    7492/** Physical mallocator simulator
     
    7795 */
    7896static inline void free32(void *addr)
    79         { free(addr); }
     97{
     98        dmamem_unmap_anonymous(addr);
     99}
     100
     101/** Create 4KB page mapping
     102 *
     103 * @return Address of the mapped page, NULL on failure.
     104 */
     105static inline void *get_page()
     106{
     107        return malloc32(PAGE_SIZE);
     108}
     109
     110static inline void return_page(void *page)
     111{
     112        free32(page);
     113}
     114
     115
    80116#endif
    81117/**
  • uspace/lib/usbhost/src/endpoint.c

    r5b18137 rb4b534ac  
    3333 */
    3434
     35#include <usb/host/endpoint.h>
     36
    3537#include <assert.h>
    3638#include <stdlib.h>
    37 #include <errno.h>
    38 #include <usb/host/endpoint.h>
    3939
    4040/** Allocate ad initialize endpoint_t structure.
     
    5050endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint,
    5151    usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
    52     size_t max_packet_size, size_t bw)
     52    size_t max_packet_size, unsigned packets, size_t bw,
     53    usb_address_t tt_address, unsigned tt_p)
    5354{
    5455        endpoint_t *instance = malloc(sizeof(endpoint_t));
     
    6061                instance->speed = speed;
    6162                instance->max_packet_size = max_packet_size;
     63                instance->packets = packets;
    6264                instance->bandwidth = bw;
    6365                instance->toggle = 0;
    6466                instance->active = false;
     67                instance->tt.address = tt_address;
     68                instance->tt.port = tt_p;
    6569                instance->hc_data.data = NULL;
    6670                instance->hc_data.toggle_get = NULL;
     
    109113{
    110114        assert(instance);
    111         fibril_mutex_lock(&instance->guard);
    112         instance->hc_data.data = NULL;
    113         instance->hc_data.toggle_get = NULL;
    114         instance->hc_data.toggle_set = NULL;
    115         fibril_mutex_unlock(&instance->guard);
     115        endpoint_set_hc_data(instance, NULL, NULL, NULL);
    116116}
    117117
  • uspace/lib/usbhost/src/usb_bus.c

    r5b18137 rb4b534ac  
    3333 */
    3434
    35 #include <stdbool.h>
     35#include <usb/host/usb_bus.h>
     36#include <usb/debug.h>
     37
    3638#include <assert.h>
    3739#include <errno.h>
    38 
    39 #include <usb/debug.h>
    40 #include <usb/host/usb_endpoint_manager.h>
     40#include <macros.h>
     41#include <stdbool.h>
     42
    4143
    4244/** Endpoint compare helper function.
     
    6365
    6466/** Get list that holds endpoints for given address.
    65  * @param instance usb_endpoint_manager structure, non-null.
     67 * @param instance usb_bus structure, non-null.
    6668 * @param addr USB address, must be >= 0.
    6769 * @return Pointer to the appropriate list.
    6870 */
    69 static list_t * get_list(usb_endpoint_manager_t *instance, usb_address_t addr)
     71static list_t * get_list(usb_bus_t *instance, usb_address_t addr)
    7072{
    7173        assert(instance);
    7274        assert(addr >= 0);
    73         return &instance->endpoint_lists[addr % ENDPOINT_LIST_COUNT];
     75        return &instance->devices[addr % ARRAY_SIZE(instance->devices)].endpoint_list;
    7476}
    7577
    7678/** Internal search function, works on locked structure.
    77  * @param instance usb_endpoint_manager structure, non-null.
     79 * @param instance usb_bus structure, non-null.
    7880 * @param address USB address, must be valid.
    7981 * @param endpoint USB endpoint number.
     
    8385 * @note Assumes that the internal mutex is locked.
    8486 */
    85 static endpoint_t * find_locked(usb_endpoint_manager_t *instance,
     87static endpoint_t * find_locked(usb_bus_t *instance,
    8688    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
    8789{
     
    9597        }
    9698        return NULL;
     99}
     100
     101/** Get a free USB address
     102 *
     103 * @param[in] instance Device manager structure to use.
     104 * @return Free address, or error code.
     105 */
     106static usb_address_t usb_bus_get_free_address(usb_bus_t *instance)
     107{
     108
     109        usb_address_t new_address = instance->last_address;
     110        do {
     111                new_address = (new_address + 1) % USB_ADDRESS_COUNT;
     112                if (new_address == USB_ADDRESS_DEFAULT)
     113                        new_address = 1;
     114                if (new_address == instance->last_address)
     115                        return ENOSPC;
     116        } while (instance->devices[new_address].occupied);
     117
     118        assert(new_address != USB_ADDRESS_DEFAULT);
     119        instance->last_address = new_address;
     120
     121        return new_address;
    97122}
    98123
     
    145170}
    146171
     172/** Calculate bandwidth that needs to be reserved for communication with EP.
     173 * Calculation follows USB 2.0 specification.
     174 * @param speed Device's speed.
     175 * @param type Type of the transfer.
     176 * @param size Number of byte to transfer.
     177 * @param max_packet_size Maximum bytes in one packet.
     178 */
     179size_t bandwidth_count_usb20(usb_speed_t speed, usb_transfer_type_t type,
     180    size_t size, size_t max_packet_size)
     181{
     182        /* We care about bandwidth only for interrupt and isochronous. */
     183        if ((type != USB_TRANSFER_INTERRUPT)
     184            && (type != USB_TRANSFER_ISOCHRONOUS)) {
     185                return 0;
     186        }
     187        //TODO Implement
     188        return 0;
     189}
     190
    147191/** Initialize to default state.
    148192 * You need to provide valid bw_count function if you plan to use
    149193 * add_endpoint/remove_endpoint pair.
    150194 *
    151  * @param instance usb_endpoint_manager structure, non-null.
     195 * @param instance usb_bus structure, non-null.
    152196 * @param available_bandwidth Size of the bandwidth pool.
    153197 * @param bw_count function to use to calculate endpoint bw requirements.
    154198 * @return Error code.
    155199 */
    156 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
    157     size_t available_bandwidth,
    158     size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t))
     200int usb_bus_init(usb_bus_t *instance,
     201    size_t available_bandwidth, bw_count_func_t bw_count, usb_speed_t max_speed)
    159202{
    160203        assert(instance);
     
    162205        instance->free_bw = available_bandwidth;
    163206        instance->bw_count = bw_count;
    164         for (unsigned i = 0; i < ENDPOINT_LIST_COUNT; ++i) {
    165                 list_initialize(&instance->endpoint_lists[i]);
     207        instance->last_address = 0;
     208        instance->max_speed = max_speed;
     209        for (unsigned i = 0; i < ARRAY_SIZE(instance->devices); ++i) {
     210                list_initialize(&instance->devices[i].endpoint_list);
     211                instance->devices[i].speed = USB_SPEED_MAX;
     212                instance->devices[i].occupied = false;
    166213        }
    167214        return EOK;
    168 }
    169 
    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),
    198                             link, endpoint_t, ep) {
    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),
    218                             link, endpoint_t, ep) {
    219                                 if (ep->address == target.address) {
    220                                         endpoint_toggle_set(ep,0);
    221                                 }
    222                         }
    223                         fibril_mutex_unlock(&instance->guard);
    224                 }
    225         break;
    226         }
    227215}
    228216
    229217/** Register endpoint structure.
    230218 * Checks for duplicates.
    231  * @param instance usb_endpoint_manager, non-null.
     219 * @param instance usb_bus, non-null.
    232220 * @param ep endpoint_t to register.
    233221 * @param data_size Size of data to transfer.
    234222 * @return Error code.
    235223 */
    236 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance,
    237     endpoint_t *ep, size_t data_size)
     224int usb_bus_register_ep(usb_bus_t *instance, endpoint_t *ep, size_t data_size)
    238225{
    239226        assert(instance);
     
    258245
    259246        instance->free_bw -= ep->bandwidth;
     247        usb_log_debug("Registered EP(%d:%d:%s:%s)\n", ep->address, ep->endpoint,
     248            usb_str_transfer_type_short(ep->transfer_type),
     249            usb_str_direction(ep->direction));
    260250        fibril_mutex_unlock(&instance->guard);
    261251        return EOK;
     
    264254/** Unregister endpoint structure.
    265255 * Checks for duplicates.
    266  * @param instance usb_endpoint_manager, non-null.
     256 * @param instance usb_bus, non-null.
    267257 * @param ep endpoint_t to unregister.
    268258 * @return Error code.
    269259 */
    270 int usb_endpoint_manager_unregister_ep(
    271     usb_endpoint_manager_t *instance, endpoint_t *ep)
     260int usb_bus_unregister_ep(usb_bus_t *instance, endpoint_t *ep)
    272261{
    273262        assert(instance);
     
    282271        list_remove(&ep->link);
    283272        instance->free_bw += ep->bandwidth;
     273        usb_log_debug("Unregistered EP(%d:%d:%s:%s)\n", ep->address,
     274            ep->endpoint, usb_str_transfer_type_short(ep->transfer_type),
     275            usb_str_direction(ep->direction));
    284276        fibril_mutex_unlock(&instance->guard);
    285277        return EOK;
     
    287279
    288280/** Find endpoint_t representing the given communication route.
    289  * @param instance usb_endpoint_manager, non-null.
     281 * @param instance usb_bus, non-null.
    290282 * @param address
    291283 */
    292 endpoint_t * usb_endpoint_manager_find_ep(usb_endpoint_manager_t *instance,
     284endpoint_t * usb_bus_find_ep(usb_bus_t *instance,
    293285    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
    294286{
     
    302294
    303295/** Create and register new endpoint_t structure.
    304  * @param instance usb_endpoint_manager structure, non-null.
     296 * @param instance usb_bus structure, non-null.
    305297 * @param address USB address.
    306298 * @param endpoint USB endpoint number.
     
    314306 * @return Error code.
    315307 */
    316 int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
     308int usb_bus_add_ep(usb_bus_t *instance,
    317309    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
    318     usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size,
    319     size_t data_size, int (*callback)(endpoint_t *, void *), void *arg)
     310    usb_transfer_type_t type, size_t max_packet_size, unsigned packets,
     311    size_t data_size, ep_add_callback_t callback, void *arg,
     312    usb_address_t tt_address, unsigned tt_port)
    320313{
    321314        assert(instance);
    322315        if (instance->bw_count == NULL)
    323316                return ENOTSUP;
    324         if (address < 0)
    325                 return EINVAL;
    326 
    327         const size_t bw =
    328             instance->bw_count(speed, type, data_size, max_packet_size);
    329 
    330         fibril_mutex_lock(&instance->guard);
    331         /* Check for available bandwidth */
    332         if (bw > instance->free_bw) {
    333                 fibril_mutex_unlock(&instance->guard);
    334                 return ENOSPC;
     317        if (!usb_address_is_valid(address))
     318                return EINVAL;
     319
     320
     321        fibril_mutex_lock(&instance->guard);
     322        /* Check for speed and address */
     323        if (!instance->devices[address].occupied) {
     324                fibril_mutex_unlock(&instance->guard);
     325                return ENOENT;
    335326        }
    336327
     
    342333        }
    343334
    344         ep = endpoint_create(
    345             address, endpoint, direction, type, speed, max_packet_size, bw);
     335        const usb_speed_t speed = instance->devices[address].speed;
     336        const size_t bw =
     337            instance->bw_count(speed, type, data_size, max_packet_size);
     338
     339        /* Check for available bandwidth */
     340        if (bw > instance->free_bw) {
     341                fibril_mutex_unlock(&instance->guard);
     342                return ENOSPC;
     343        }
     344
     345        ep = endpoint_create(address, endpoint, direction, type, speed,
     346            max_packet_size, packets, bw, tt_address, tt_port);
    346347        if (!ep) {
    347348                fibril_mutex_unlock(&instance->guard);
     
    365366
    366367/** Unregister and destroy endpoint_t structure representing given route.
    367  * @param instance usb_endpoint_manager structure, non-null.
     368 * @param instance usb_bus structure, non-null.
    368369 * @param address USB address.
    369370 * @param endpoint USB endpoint number.
     
    373374 * @return Error code.
    374375 */
    375 int usb_endpoint_manager_remove_ep(usb_endpoint_manager_t *instance,
     376int usb_bus_remove_ep(usb_bus_t *instance,
    376377    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
    377     void (*callback)(endpoint_t *, void *), void *arg)
     378    ep_remove_callback_t callback, void *arg)
    378379{
    379380        assert(instance);
     
    395396}
    396397
     398int usb_bus_reset_toggle(usb_bus_t *instance, usb_target_t target, bool all)
     399{
     400        assert(instance);
     401        if (!usb_target_is_valid(target))
     402                return EINVAL;
     403
     404        int ret = ENOENT;
     405
     406        fibril_mutex_lock(&instance->guard);
     407        list_foreach(*get_list(instance, target.address), link, endpoint_t, ep) {
     408                if ((ep->address == target.address)
     409                    && (all || ep->endpoint == target.endpoint)) {
     410                        endpoint_toggle_set(ep, 0);
     411                        ret = EOK;
     412                }
     413        }
     414        fibril_mutex_unlock(&instance->guard);
     415        return ret;
     416}
     417
    397418/** Unregister and destroy all endpoints using given address.
    398  * @param instance usb_endpoint_manager structure, non-null.
     419 * @param instance usb_bus structure, non-null.
    399420 * @param address USB address.
    400421 * @param endpoint USB endpoint number.
     
    404425 * @return Error code.
    405426 */
    406 void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance,
    407     usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg)
    408 {
    409         list_t *list;
    410         link_t *link;
    411         link_t *next;
    412 
    413         assert(address >= 0);
    414         assert(instance);
    415         fibril_mutex_lock(&instance->guard);
    416 
    417         list = get_list(instance, address);
    418         link = list_first(list);
    419         while (link != NULL) {
     427int usb_bus_remove_address(usb_bus_t *instance,
     428    usb_address_t address, ep_remove_callback_t callback, void *arg)
     429{
     430        assert(instance);
     431        if (!usb_address_is_valid(address))
     432                return EINVAL;
     433
     434        fibril_mutex_lock(&instance->guard);
     435
     436        const int ret = instance->devices[address].occupied ? EOK : ENOENT;
     437        instance->devices[address].occupied = false;
     438
     439        list_t *list = get_list(instance, address);
     440        for (link_t *link = list_first(list); link != NULL; ) {
    420441                endpoint_t *ep = list_get_instance(link, endpoint_t, link);
    421                 next = list_next(link, list);
    422 
     442                link = list_next(link, list);
    423443                if (ep->address == address) {
    424444                        list_remove(&ep->link);
     
    427447                        endpoint_destroy(ep);
    428448                }
    429                 link = next;
    430         }
    431         fibril_mutex_unlock(&instance->guard);
     449        }
     450        fibril_mutex_unlock(&instance->guard);
     451        return ret;
     452}
     453
     454/** Request USB address.
     455 * @param instance usb_device_manager
     456 * @param address Pointer to requested address value, place to store new address
     457 * @parma strict Fail if the requested address is not available.
     458 * @return Error code.
     459 * @note Default address is only available in strict mode.
     460 */
     461int usb_bus_request_address(usb_bus_t *instance,
     462    usb_address_t *address, bool strict, usb_speed_t speed)
     463{
     464        assert(instance);
     465        assert(address);
     466        if (speed > instance->max_speed)
     467                return ENOTSUP;
     468
     469        if (!usb_address_is_valid(*address))
     470                return EINVAL;
     471
     472        usb_address_t addr = *address;
     473
     474        fibril_mutex_lock(&instance->guard);
     475        /* Only grant default address to strict requests */
     476        if ((addr == USB_ADDRESS_DEFAULT) && !strict) {
     477                addr = usb_bus_get_free_address(instance);
     478        }
     479
     480        if (instance->devices[addr].occupied) {
     481                if (strict) {
     482                        fibril_mutex_unlock(&instance->guard);
     483                        return ENOENT;
     484                }
     485                addr = usb_bus_get_free_address(instance);
     486        }
     487        if (usb_address_is_valid(addr)) {
     488                assert(instance->devices[addr].occupied == false);
     489                assert(addr != USB_ADDRESS_DEFAULT || strict);
     490
     491                instance->devices[addr].occupied = true;
     492                instance->devices[addr].speed = speed;
     493                *address = addr;
     494                addr = 0;
     495        }
     496
     497        fibril_mutex_unlock(&instance->guard);
     498        return addr;
     499}
     500
     501/** Get speed assigned to USB address.
     502 *
     503 * @param[in] instance Device manager structure to use.
     504 * @param[in] address Address the caller wants to find.
     505 * @param[out] speed Assigned speed.
     506 * @return Error code.
     507 */
     508int usb_bus_get_speed(usb_bus_t *instance, usb_address_t address,
     509    usb_speed_t *speed)
     510{
     511        assert(instance);
     512        if (!usb_address_is_valid(address)) {
     513                return EINVAL;
     514        }
     515
     516        fibril_mutex_lock(&instance->guard);
     517
     518        const int ret = instance->devices[address].occupied ? EOK : ENOENT;
     519        if (speed && instance->devices[address].occupied) {
     520                *speed = instance->devices[address].speed;
     521        }
     522
     523        fibril_mutex_unlock(&instance->guard);
     524        return ret;
    432525}
    433526/**
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    r5b18137 rb4b534ac  
    3232 * USB transfer transaction structures (implementation).
    3333 */
     34
     35#include <usb/host/usb_transfer_batch.h>
     36#include <usb/debug.h>
     37
     38#include <assert.h>
    3439#include <errno.h>
    3540#include <macros.h>
    36 
    37 #include <usb/usb.h>
    38 #include <usb/debug.h>
    39 
    40 #include <usb/host/usb_transfer_batch.h>
    41 #include <usb/host/hcd.h>
     41#include <mem.h>
     42#include <stdlib.h>
     43#include <usbhc_iface.h>
    4244
    4345/** Allocate and initialize usb_transfer_batch structure.
     
    6163    usbhc_iface_transfer_in_callback_t func_in,
    6264    usbhc_iface_transfer_out_callback_t func_out,
    63     void *arg,
    64     ddf_fun_t *fun,
    65     void *private_data,
    66     void (*private_data_dtor)(void *)
     65    void *arg
    6766    )
    6867{
     
    8180                instance->buffer_size = buffer_size;
    8281                instance->setup_size = 0;
    83                 instance->fun = fun;
    84                 instance->private_data = private_data;
    85                 instance->private_data_dtor = private_data_dtor;
    8682                instance->transfered_size = 0;
    8783                instance->error = EOK;
     
    110106                endpoint_release(instance->ep);
    111107        }
    112         if (instance->private_data) {
    113                 assert(instance->private_data_dtor);
    114                 instance->private_data_dtor(instance->private_data);
    115         }
    116108        free(instance);
    117109}
     
    133125        /* NOTE: Only one of these pointers should be set. */
    134126        if (instance->callback_out) {
    135                 /* Check for commands that reset toggle bit */
    136                 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL
    137                     && error == EOK) {
    138                         const usb_target_t target =
    139                             {{ instance->ep->address, instance->ep->endpoint }};
    140                         reset_ep_if_need(fun_to_hcd(instance->fun), target,
    141                             instance->setup_buffer);
    142                 }
    143                 instance->callback_out(instance->fun, error, instance->arg);
     127                instance->callback_out(error, instance->arg);
    144128        }
    145129
     
    150134                        memcpy(instance->buffer, data, safe_size);
    151135                }
    152                 instance->callback_in(instance->fun, error,
    153                     safe_size, instance->arg);
     136                instance->callback_in(error, safe_size, instance->arg);
    154137        }
    155138}
Note: See TracChangeset for help on using the changeset viewer.