Changeset b4b534ac in mainline for uspace/lib/usbhost
- Timestamp:
- 2016-07-22T08:24:47Z (9 years ago)
- 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. - Location:
- uspace/lib/usbhost
- Files:
-
- 2 added
- 3 deleted
- 6 edited
- 4 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbhost/Makefile
r5b18137 rb4b534ac 32 32 -I$(LIBUSB_PREFIX)/include \ 33 33 -I$(LIBDRV_PREFIX)/include \ 34 -Iinclude/usb/host \ 34 35 -Iinclude 35 36 36 37 SOURCES = \ 38 src/ddf_helpers.c \ 37 39 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 \ 41 42 src/usb_transfer_batch.c 42 43 -
uspace/lib/usbhost/include/usb/host/ddf_helpers.h
r5b18137 rb4b534ac 1 1 /* 2 * Copyright (c) 201 1 Vojtech Horky2 * Copyright (c) 2012 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbohci 28 29 /** @addtogroup libusbhost 29 30 * @{ 30 31 */ 31 32 /** @file 32 * PCI related functions needed by OHCI driver.33 * 33 34 */ 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> 36 42 37 43 #include <ddf/driver.h> 44 #include <ddf/interrupt.h> 38 45 #include <device/hw_res_parsed.h> 39 46 40 int get_my_registers(ddf_dev_t *, addr_range_t *, int *); 41 int enable_interrupts(ddf_dev_t *); 47 typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, bool); 48 typedef void (*driver_fini_t)(hcd_t *); 49 typedef int (*claim_t)(ddf_dev_t *); 50 typedef int (*irq_code_gen_t)(irq_code_t *, const hw_res_list_parsed_t *); 51 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; 62 63 int hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver); 64 65 int 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 int hcd_ddf_setup_root_hub(ddf_dev_t *device); 69 70 hcd_t *dev_to_hcd(ddf_dev_t *dev); 71 72 int hcd_ddf_enable_interrupts(ddf_dev_t *device); 73 int hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res); 74 int 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 *)); 78 void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev); 42 79 43 80 #endif 81 44 82 /** 45 83 * @} 46 84 */ 47 -
uspace/lib/usbhost/include/usb/host/endpoint.h
r5b18137 rb4b534ac 57 57 /** Maximum size of data packets. */ 58 58 size_t max_packet_size; 59 /** Additional opportunities per uframe */ 60 unsigned packets; 59 61 /** Necessary bandwidth. */ 60 62 size_t bandwidth; … … 67 69 /** Signals change of active status. */ 68 70 fibril_condvar_t avail; 71 /** High speed TT data */ 72 struct { 73 usb_address_t address; 74 unsigned port; 75 } tt; 69 76 /** Optional device specific data. */ 70 77 struct { … … 80 87 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint, 81 88 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); 83 91 void endpoint_destroy(endpoint_t *instance); 84 92 -
uspace/lib/usbhost/include/usb/host/hcd.h
r5b18137 rb4b534ac 37 37 #define LIBUSBHOST_HOST_HCD_H 38 38 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 39 44 #include <assert.h> 40 45 #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> 45 47 46 48 typedef struct hcd hcd_t; 47 49 50 typedef int (*schedule_hook_t)(hcd_t *, usb_transfer_batch_t *); 51 typedef int (*ep_add_hook_t)(hcd_t *, endpoint_t *); 52 typedef void (*ep_remove_hook_t)(hcd_t *, endpoint_t *); 53 typedef void (*interrupt_hook_t)(hcd_t *, uint32_t); 54 typedef int (*status_hook_t)(hcd_t *, uint32_t *); 55 56 typedef 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 48 69 /** Generic host controller driver structure. */ 49 70 struct hcd { 50 /** Device manager storing handles and addresses. */51 usb_device_manager_t dev_manager;52 71 /** Endpoint manager. */ 53 usb_ endpoint_manager_t ep_manager;72 usb_bus_t bus; 54 73 74 /** Interrupt replacement fibril */ 75 fid_t polling_fibril; 76 77 /** Driver implementation */ 78 hcd_ops_t ops; 55 79 /** 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; 63 81 }; 64 82 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)) 83 void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth, 84 bw_count_func_t bw_count); 85 86 static inline void hcd_set_implementation(hcd_t *hcd, void *data, 87 const hcd_ops_t *ops) 73 88 { 74 89 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 } 81 96 } 82 97 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]) 98 static inline void * hcd_get_driver_data(hcd_t *hcd) 90 99 { 91 100 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; 94 102 } 95 103 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) 104 usb_address_t hcd_request_address(hcd_t *hcd, usb_speed_t speed); 105 106 int hcd_release_address(hcd_t *hcd, usb_address_t address); 107 108 int hcd_reserve_default_address(hcd_t *hcd, usb_speed_t speed); 109 110 static inline int hcd_release_default_address(hcd_t *hcd) 101 111 { 102 return ddf_fun_data_get(fun);112 return hcd_release_address(hcd, USB_ADDRESS_DEFAULT); 103 113 } 104 114 105 extern usbhc_iface_t hcd_iface; 115 int 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 119 int hcd_remove_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir); 120 121 int 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 126 ssize_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); 106 129 107 130 #endif 108 109 131 /** 110 132 * @} -
uspace/lib/usbhost/include/usb/host/usb_bus.h
r5b18137 rb4b534ac 40 40 #define LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H 41 41 42 #include <usb/host/endpoint.h> 43 #include <usb/usb.h> 44 42 45 #include <adt/list.h> 43 46 #include <fibril_synch.h> 44 #include < usb/usb.h>47 #include <stdbool.h> 45 48 46 #include <usb/host/endpoint.h>47 49 48 50 /** Bytes per second in FULL SPEED */ … … 50 52 /** 90% of total bandwidth is available for periodic transfers */ 51 53 #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 58 typedef size_t (*bw_count_func_t)(usb_speed_t, usb_transfer_type_t, size_t, size_t); 59 typedef void (*ep_remove_callback_t)(endpoint_t *, void *); 60 typedef int (*ep_add_callback_t)(endpoint_t *, void *); 54 61 55 62 /** Endpoint management structure */ 56 typedef struct usb_endpoint_manager { 57 /** Store endpoint_t instances */ 58 list_t endpoint_lists[ENDPOINT_LIST_COUNT]; 63 typedef 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]; 59 69 /** Prevents races accessing lists */ 60 70 fibril_mutex_t guard; … … 62 72 size_t free_bw; 63 73 /** 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 66 81 67 82 size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type, 68 83 size_t size, size_t max_packet_size); 84 size_t bandwidth_count_usb20(usb_speed_t speed, usb_transfer_type_t type, 85 size_t size, size_t max_packet_size); 69 86 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)); 87 int usb_bus_init(usb_bus_t *instance, 88 size_t available_bandwidth, bw_count_func_t bw_count, usb_speed_t max_speed); 73 89 74 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance, 75 usb_target_t target, const uint8_t data[8]); 90 int usb_bus_register_ep(usb_bus_t *instance, endpoint_t *ep, size_t data_size); 76 91 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, 92 int usb_bus_unregister_ep(usb_bus_t *instance, endpoint_t *ep); 93 94 endpoint_t * usb_bus_find_ep(usb_bus_t *instance, 82 95 usb_address_t address, usb_endpoint_t ep, usb_direction_t direction); 83 96 84 int usb_ endpoint_manager_add_ep(usb_endpoint_manager_t *instance,97 int usb_bus_add_ep(usb_bus_t *instance, 85 98 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); 88 102 89 int usb_ endpoint_manager_remove_ep(usb_endpoint_manager_t *instance,103 int usb_bus_remove_ep(usb_bus_t *instance, 90 104 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); 92 106 93 void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance, 94 usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg); 107 int usb_bus_reset_toggle(usb_bus_t *instance, usb_target_t target, bool all); 108 109 int usb_bus_remove_address(usb_bus_t *instance, 110 usb_address_t address, ep_remove_callback_t callback, void *arg); 111 112 int usb_bus_request_address(usb_bus_t *instance, 113 usb_address_t *address, bool strict, usb_speed_t speed); 114 115 int usb_bus_get_speed(usb_bus_t *instance, 116 usb_address_t address, usb_speed_t *speed); 95 117 #endif 96 118 /** -
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
r5b18137 rb4b534ac 37 37 #define LIBUSBHOST_HOST_USB_TRANSFER_BATCH_H 38 38 39 #include <adt/list.h> 39 #include <usb/host/endpoint.h> 40 #include <usb/usb.h> 40 41 42 #include <assert.h> 43 #include <stdbool.h> 44 #include <sys/types.h> 41 45 #include <usbhc_iface.h> 42 #include <usb/usb.h>43 #include <usb/host/endpoint.h>44 46 45 47 #define USB_SETUP_PACKET_SIZE 8 … … 67 69 */ 68 70 size_t setup_size; 69 /** Host controller function, passed to callback function */70 ddf_fun_t *fun;71 71 72 72 /** Actually used portion of the buffer … … 80 80 */ 81 81 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);87 82 } usb_transfer_batch_t; 88 83 … … 108 103 usbhc_iface_transfer_in_callback_t func_in, 109 104 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 114 106 ); 115 107 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance); -
uspace/lib/usbhost/include/usb/host/utils/malloc32.h
r5b18137 rb4b534ac 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2013 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusb ohci28 /** @addtogroup drvusbehci 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief OHCI driver32 * @brief EHCI driver 33 33 */ 34 #ifndef DRV_ OHCI_UTILS_MALLOC32_H35 #define DRV_ OHCI_UTILS_MALLOC32_H34 #ifndef DRV_EHCI_UTILS_MALLOC32_H 35 #define DRV_EHCI_UTILS_MALLOC32_H 36 36 37 #include <a ssert.h>38 #include < malloc.h>39 #include < unistd.h>37 #include <align.h> 38 #include <as.h> 39 #include <ddi.h> 40 40 #include <errno.h> 41 #include < mem.h>42 #include < as.h>41 #include <stdlib.h> 42 #include <sys/types.h> 43 43 44 44 /* Generic TDs and EDs require 16byte alignment, … … 46 46 * buffers do not have to be aligned. 47 47 */ 48 #define OHCI_ALIGN 32 48 #define EHCI_ALIGN 32 49 50 #define EHCI_REQUIRED_PAGE_SIZE 4096 49 51 50 52 /** Get physical address translation … … 70 72 */ 71 73 static 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 } 73 91 74 92 /** Physical mallocator simulator … … 77 95 */ 78 96 static 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 */ 105 static inline void *get_page() 106 { 107 return malloc32(PAGE_SIZE); 108 } 109 110 static inline void return_page(void *page) 111 { 112 free32(page); 113 } 114 115 80 116 #endif 81 117 /** -
uspace/lib/usbhost/src/endpoint.c
r5b18137 rb4b534ac 33 33 */ 34 34 35 #include <usb/host/endpoint.h> 36 35 37 #include <assert.h> 36 38 #include <stdlib.h> 37 #include <errno.h>38 #include <usb/host/endpoint.h>39 39 40 40 /** Allocate ad initialize endpoint_t structure. … … 50 50 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint, 51 51 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) 53 54 { 54 55 endpoint_t *instance = malloc(sizeof(endpoint_t)); … … 60 61 instance->speed = speed; 61 62 instance->max_packet_size = max_packet_size; 63 instance->packets = packets; 62 64 instance->bandwidth = bw; 63 65 instance->toggle = 0; 64 66 instance->active = false; 67 instance->tt.address = tt_address; 68 instance->tt.port = tt_p; 65 69 instance->hc_data.data = NULL; 66 70 instance->hc_data.toggle_get = NULL; … … 109 113 { 110 114 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); 116 116 } 117 117 -
uspace/lib/usbhost/src/usb_bus.c
r5b18137 rb4b534ac 33 33 */ 34 34 35 #include <stdbool.h> 35 #include <usb/host/usb_bus.h> 36 #include <usb/debug.h> 37 36 38 #include <assert.h> 37 39 #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 41 43 42 44 /** Endpoint compare helper function. … … 63 65 64 66 /** Get list that holds endpoints for given address. 65 * @param instance usb_ endpoint_managerstructure, non-null.67 * @param instance usb_bus structure, non-null. 66 68 * @param addr USB address, must be >= 0. 67 69 * @return Pointer to the appropriate list. 68 70 */ 69 static list_t * get_list(usb_ endpoint_manager_t *instance, usb_address_t addr)71 static list_t * get_list(usb_bus_t *instance, usb_address_t addr) 70 72 { 71 73 assert(instance); 72 74 assert(addr >= 0); 73 return &instance-> endpoint_lists[addr % ENDPOINT_LIST_COUNT];75 return &instance->devices[addr % ARRAY_SIZE(instance->devices)].endpoint_list; 74 76 } 75 77 76 78 /** Internal search function, works on locked structure. 77 * @param instance usb_ endpoint_managerstructure, non-null.79 * @param instance usb_bus structure, non-null. 78 80 * @param address USB address, must be valid. 79 81 * @param endpoint USB endpoint number. … … 83 85 * @note Assumes that the internal mutex is locked. 84 86 */ 85 static endpoint_t * find_locked(usb_ endpoint_manager_t *instance,87 static endpoint_t * find_locked(usb_bus_t *instance, 86 88 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 87 89 { … … 95 97 } 96 98 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 */ 106 static 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; 97 122 } 98 123 … … 145 170 } 146 171 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 */ 179 size_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 147 191 /** Initialize to default state. 148 192 * You need to provide valid bw_count function if you plan to use 149 193 * add_endpoint/remove_endpoint pair. 150 194 * 151 * @param instance usb_ endpoint_managerstructure, non-null.195 * @param instance usb_bus structure, non-null. 152 196 * @param available_bandwidth Size of the bandwidth pool. 153 197 * @param bw_count function to use to calculate endpoint bw requirements. 154 198 * @return Error code. 155 199 */ 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)) 200 int usb_bus_init(usb_bus_t *instance, 201 size_t available_bandwidth, bw_count_func_t bw_count, usb_speed_t max_speed) 159 202 { 160 203 assert(instance); … … 162 205 instance->free_bw = available_bandwidth; 163 206 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; 166 213 } 167 214 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.h178 */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.h194 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 registered212 * as different interfaces use different endpoints,213 * unless you're changing configuration or alternative214 * 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 }227 215 } 228 216 229 217 /** Register endpoint structure. 230 218 * Checks for duplicates. 231 * @param instance usb_ endpoint_manager, non-null.219 * @param instance usb_bus, non-null. 232 220 * @param ep endpoint_t to register. 233 221 * @param data_size Size of data to transfer. 234 222 * @return Error code. 235 223 */ 236 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance, 237 endpoint_t *ep, size_t data_size) 224 int usb_bus_register_ep(usb_bus_t *instance, endpoint_t *ep, size_t data_size) 238 225 { 239 226 assert(instance); … … 258 245 259 246 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)); 260 250 fibril_mutex_unlock(&instance->guard); 261 251 return EOK; … … 264 254 /** Unregister endpoint structure. 265 255 * Checks for duplicates. 266 * @param instance usb_ endpoint_manager, non-null.256 * @param instance usb_bus, non-null. 267 257 * @param ep endpoint_t to unregister. 268 258 * @return Error code. 269 259 */ 270 int usb_endpoint_manager_unregister_ep( 271 usb_endpoint_manager_t *instance, endpoint_t *ep) 260 int usb_bus_unregister_ep(usb_bus_t *instance, endpoint_t *ep) 272 261 { 273 262 assert(instance); … … 282 271 list_remove(&ep->link); 283 272 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)); 284 276 fibril_mutex_unlock(&instance->guard); 285 277 return EOK; … … 287 279 288 280 /** Find endpoint_t representing the given communication route. 289 * @param instance usb_ endpoint_manager, non-null.281 * @param instance usb_bus, non-null. 290 282 * @param address 291 283 */ 292 endpoint_t * usb_ endpoint_manager_find_ep(usb_endpoint_manager_t *instance,284 endpoint_t * usb_bus_find_ep(usb_bus_t *instance, 293 285 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 294 286 { … … 302 294 303 295 /** Create and register new endpoint_t structure. 304 * @param instance usb_ endpoint_managerstructure, non-null.296 * @param instance usb_bus structure, non-null. 305 297 * @param address USB address. 306 298 * @param endpoint USB endpoint number. … … 314 306 * @return Error code. 315 307 */ 316 int usb_ endpoint_manager_add_ep(usb_endpoint_manager_t *instance,308 int usb_bus_add_ep(usb_bus_t *instance, 317 309 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) 320 313 { 321 314 assert(instance); 322 315 if (instance->bw_count == NULL) 323 316 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; 335 326 } 336 327 … … 342 333 } 343 334 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); 346 347 if (!ep) { 347 348 fibril_mutex_unlock(&instance->guard); … … 365 366 366 367 /** Unregister and destroy endpoint_t structure representing given route. 367 * @param instance usb_ endpoint_managerstructure, non-null.368 * @param instance usb_bus structure, non-null. 368 369 * @param address USB address. 369 370 * @param endpoint USB endpoint number. … … 373 374 * @return Error code. 374 375 */ 375 int usb_ endpoint_manager_remove_ep(usb_endpoint_manager_t *instance,376 int usb_bus_remove_ep(usb_bus_t *instance, 376 377 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) 378 379 { 379 380 assert(instance); … … 395 396 } 396 397 398 int 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 397 418 /** Unregister and destroy all endpoints using given address. 398 * @param instance usb_ endpoint_managerstructure, non-null.419 * @param instance usb_bus structure, non-null. 399 420 * @param address USB address. 400 421 * @param endpoint USB endpoint number. … … 404 425 * @return Error code. 405 426 */ 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 li nk = list_first(list);419 while (link != NULL) {427 int 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; ) { 420 441 endpoint_t *ep = list_get_instance(link, endpoint_t, link); 421 next = list_next(link, list); 422 442 link = list_next(link, list); 423 443 if (ep->address == address) { 424 444 list_remove(&ep->link); … … 427 447 endpoint_destroy(ep); 428 448 } 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 */ 461 int 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 */ 508 int 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; 432 525 } 433 526 /** -
uspace/lib/usbhost/src/usb_transfer_batch.c
r5b18137 rb4b534ac 32 32 * USB transfer transaction structures (implementation). 33 33 */ 34 35 #include <usb/host/usb_transfer_batch.h> 36 #include <usb/debug.h> 37 38 #include <assert.h> 34 39 #include <errno.h> 35 40 #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> 42 44 43 45 /** Allocate and initialize usb_transfer_batch structure. … … 61 63 usbhc_iface_transfer_in_callback_t func_in, 62 64 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 67 66 ) 68 67 { … … 81 80 instance->buffer_size = buffer_size; 82 81 instance->setup_size = 0; 83 instance->fun = fun;84 instance->private_data = private_data;85 instance->private_data_dtor = private_data_dtor;86 82 instance->transfered_size = 0; 87 83 instance->error = EOK; … … 110 106 endpoint_release(instance->ep); 111 107 } 112 if (instance->private_data) {113 assert(instance->private_data_dtor);114 instance->private_data_dtor(instance->private_data);115 }116 108 free(instance); 117 109 } … … 133 125 /* NOTE: Only one of these pointers should be set. */ 134 126 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); 144 128 } 145 129 … … 150 134 memcpy(instance->buffer, data, safe_size); 151 135 } 152 instance->callback_in(instance->fun, error, 153 safe_size, instance->arg); 136 instance->callback_in(error, safe_size, instance->arg); 154 137 } 155 138 }
Note:
See TracChangeset
for help on using the changeset viewer.