Changes in uspace/lib/usbhost/src/endpoint.c [f527f58:17873ac7] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbhost/src/endpoint.c
rf527f58 r17873ac7 1 1 /* 2 2 * Copyright (c) 2011 Jan Vesely 3 * Copyright (c) 2017 Ondrej Hlavaty <aearsis@eideo.cz> 3 4 * All rights reserved. 4 5 * … … 35 36 36 37 #include <usb/host/endpoint.h> 38 #include <usb/host/usb_transfer_batch.h> 39 #include <usb/host/bus.h> 37 40 38 41 #include <assert.h> 42 #include <atomic.h> 43 #include <mem.h> 39 44 #include <stdlib.h> 40 #include <atomic.h>41 45 42 /** Allocate ad initialize endpoint_t structure. 43 * @param address USB address. 44 * @param endpoint USB endpoint number. 45 * @param direction Communication direction. 46 * @param type USB transfer type. 47 * @param speed Communication speed. 48 * @param max_packet_size Maximum size of data packets. 49 * @param bw Required bandwidth. 50 * @return Pointer to initialized endpoint_t structure, NULL on failure. 46 /** Initialize provided endpoint structure. 51 47 */ 52 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint, 53 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 54 size_t max_packet_size, unsigned packets, size_t bw, 55 usb_address_t tt_address, unsigned tt_p) 48 void endpoint_init(endpoint_t *ep, bus_t *bus) 56 49 { 57 endpoint_t *instance = malloc(sizeof(endpoint_t)); 58 if (instance) { 59 atomic_set(&instance->refcnt, 0); 60 instance->address = address; 61 instance->endpoint = endpoint; 62 instance->direction = direction; 63 instance->transfer_type = type; 64 instance->speed = speed; 65 instance->max_packet_size = max_packet_size; 66 instance->packets = packets; 67 instance->bandwidth = bw; 68 instance->toggle = 0; 69 instance->active = false; 70 instance->tt.address = tt_address; 71 instance->tt.port = tt_p; 72 instance->hc_data.data = NULL; 73 instance->hc_data.toggle_get = NULL; 74 instance->hc_data.toggle_set = NULL; 75 link_initialize(&instance->link); 76 fibril_mutex_initialize(&instance->guard); 77 fibril_condvar_initialize(&instance->avail); 78 } 79 return instance; 50 memset(ep, 0, sizeof(endpoint_t)); 51 52 ep->bus = bus; 53 atomic_set(&ep->refcnt, 0); 54 link_initialize(&ep->link); 55 fibril_mutex_initialize(&ep->guard); 56 fibril_condvar_initialize(&ep->avail); 80 57 } 81 58 82 /** Properly dispose of endpoint_t structure. 83 * @param instance endpoint_t structure. 84 */ 85 void endpoint_destroy(endpoint_t *instance) 59 void endpoint_add_ref(endpoint_t *ep) 86 60 { 87 assert(instance); 88 assert(!instance->active); 89 assert(instance->hc_data.data == NULL); 90 free(instance); 61 atomic_inc(&ep->refcnt); 91 62 } 92 63 93 void endpoint_ add_ref(endpoint_t *instance)64 void endpoint_del_ref(endpoint_t *ep) 94 65 { 95 atomic_inc(&instance->refcnt); 96 } 66 if (atomic_predec(&ep->refcnt) == 0) { 67 if (ep->bus->ops.destroy_endpoint) { 68 ep->bus->ops.destroy_endpoint(ep); 69 } 70 else { 71 assert(ep->active_batch == NULL); 97 72 98 void endpoint_del_ref(endpoint_t *instance) 99 { 100 if (atomic_predec(&instance->refcnt) == 0) 101 endpoint_destroy(instance); 102 } 103 104 /** Set device specific data and hooks. 105 * @param instance endpoint_t structure. 106 * @param data device specific data. 107 * @param toggle_get Hook to call when retrieving value of toggle bit. 108 * @param toggle_set Hook to call when setting the value of toggle bit. 109 */ 110 void endpoint_set_hc_data(endpoint_t *instance, 111 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 112 { 113 assert(instance); 114 fibril_mutex_lock(&instance->guard); 115 instance->hc_data.data = data; 116 instance->hc_data.toggle_get = toggle_get; 117 instance->hc_data.toggle_set = toggle_set; 118 fibril_mutex_unlock(&instance->guard); 119 } 120 121 /** Clear device specific data and hooks. 122 * @param instance endpoint_t structure. 123 * @note This function does not free memory pointed to by data pointer. 124 */ 125 void endpoint_clear_hc_data(endpoint_t *instance) 126 { 127 assert(instance); 128 endpoint_set_hc_data(instance, NULL, NULL, NULL); 73 /* Assume mostly the eps will be allocated by malloc. */ 74 free(ep); 75 } 76 } 129 77 } 130 78 131 79 /** Mark the endpoint as active and block access for further fibrils. 132 * @param instanceendpoint_t structure.80 * @param ep endpoint_t structure. 133 81 */ 134 void endpoint_ use(endpoint_t *instance)82 void endpoint_activate_locked(endpoint_t *ep, usb_transfer_batch_t *batch) 135 83 { 136 assert( instance);137 /* Add reference for active endpoint. */138 endpoint_add_ref(instance);139 fibril_mutex_lock(&instance->guard);140 while (instance->active) 141 fibril_condvar_wait(&instance->avail, &instance->guard);142 instance->active = true;143 fibril_mutex_unlock(&instance->guard);84 assert(ep); 85 assert(batch); 86 assert(batch->ep == ep); 87 assert(fibril_mutex_is_locked(&ep->guard)); 88 89 while (ep->active_batch != NULL) 90 fibril_condvar_wait(&ep->avail, &ep->guard); 91 ep->active_batch = batch; 144 92 } 145 93 146 94 /** Mark the endpoint as inactive and allow access for further fibrils. 147 * @param instanceendpoint_t structure.95 * @param ep endpoint_t structure. 148 96 */ 149 void endpoint_ release(endpoint_t *instance)97 void endpoint_deactivate_locked(endpoint_t *ep) 150 98 { 151 assert(instance); 152 fibril_mutex_lock(&instance->guard); 153 instance->active = false; 154 fibril_mutex_unlock(&instance->guard); 155 fibril_condvar_signal(&instance->avail); 156 /* Drop reference for active endpoint. */ 157 endpoint_del_ref(instance); 99 assert(ep); 100 assert(fibril_mutex_is_locked(&ep->guard)); 101 102 if (ep->active_batch && ep->active_batch->error == EOK) 103 usb_transfer_batch_reset_toggle(ep->active_batch); 104 105 ep->active_batch = NULL; 106 fibril_condvar_signal(&ep->avail); 158 107 } 159 108 160 /** Get the value of toggle bit.161 * @param instance endpoint_t structure.162 * @ note Will use provided hook.109 /** Abort an active batch on endpoint, if any. 110 * 111 * @param[in] ep endpoint_t structure. 163 112 */ 164 int endpoint_toggle_get(endpoint_t *instance)113 void endpoint_abort(endpoint_t *ep) 165 114 { 166 assert(instance); 167 fibril_mutex_lock(&instance->guard); 168 if (instance->hc_data.toggle_get) 169 instance->toggle = 170 instance->hc_data.toggle_get(instance->hc_data.data); 171 const int ret = instance->toggle; 172 fibril_mutex_unlock(&instance->guard); 173 return ret; 115 assert(ep); 116 117 fibril_mutex_lock(&ep->guard); 118 usb_transfer_batch_t *batch = ep->active_batch; 119 endpoint_deactivate_locked(ep); 120 fibril_mutex_unlock(&ep->guard); 121 122 if (batch) 123 usb_transfer_batch_abort(batch); 174 124 } 175 125 176 /** Set the value of toggle bit.177 * @param instance endpoint_t structure.178 * @ note Will use provided hook.126 /** Get the value of toggle bit. Either uses the toggle_get op, or just returns 127 * the value of the toggle. 128 * @param ep endpoint_t structure. 179 129 */ 180 void endpoint_toggle_set(endpoint_t *instance, int toggle)130 int endpoint_toggle_get(endpoint_t *ep) 181 131 { 182 assert(instance); 183 assert(toggle == 0 || toggle == 1); 184 fibril_mutex_lock(&instance->guard); 185 instance->toggle = toggle; 186 if (instance->hc_data.toggle_set) 187 instance->hc_data.toggle_set(instance->hc_data.data, toggle); 188 fibril_mutex_unlock(&instance->guard); 132 assert(ep); 133 134 return ep->bus->ops.endpoint_get_toggle 135 ? ep->bus->ops.endpoint_get_toggle(ep) 136 : ep->toggle; 189 137 } 138 139 /** Set the value of toggle bit. Either uses the toggle_set op, or just sets 140 * the toggle inside. 141 * @param ep endpoint_t structure. 142 */ 143 void endpoint_toggle_set(endpoint_t *ep, bool toggle) 144 { 145 assert(ep); 146 147 if (ep->bus->ops.endpoint_set_toggle) { 148 ep->bus->ops.endpoint_set_toggle(ep, toggle); 149 } 150 else { 151 ep->toggle = toggle; 152 } 153 } 154 190 155 191 156 /**
Note:
See TracChangeset
for help on using the changeset viewer.