Changeset dcaf819 in mainline for uspace/lib/usb/src
- Timestamp:
- 2011-04-06T22:33:08Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9a7e5b4
- Parents:
- 6bf9bc4 (diff), 87305bb (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/usb/src/host
- Files:
-
- 1 added
- 2 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/host/batch.c
r6bf9bc4 rdcaf819 54 54 void *arg, 55 55 ddf_fun_t *fun, 56 endpoint_t *ep, 56 57 void *private_data 57 58 ) … … 77 78 instance->next_step = NULL; 78 79 instance->error = EOK; 79 80 instance->ep = ep; 80 81 } 81 82 /*----------------------------------------------------------------------------*/ -
uspace/lib/usb/src/host/device_keeper.c
r6bf9bc4 rdcaf819 56 56 instance->devices[i].control_used = 0; 57 57 instance->devices[i].handle = 0; 58 instance->devices[i].toggle_status[0] = 0; 59 instance->devices[i].toggle_status[1] = 0; 60 } 58 list_initialize(&instance->devices[i].endpoints); 59 } 60 } 61 /*----------------------------------------------------------------------------*/ 62 void usb_device_keeper_add_ep( 63 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep) 64 { 65 assert(instance); 66 fibril_mutex_lock(&instance->guard); 67 assert(instance->devices[address].occupied); 68 list_append(&ep->same_device_eps, &instance->devices[address].endpoints); 69 fibril_mutex_unlock(&instance->guard); 61 70 } 62 71 /*----------------------------------------------------------------------------*/ … … 66 75 * @param[in] speed Speed of the device requesting default address. 67 76 */ 68 void usb_device_keeper_reserve_default_address( usb_device_keeper_t *instance,69 usb_ speed_t speed)77 void usb_device_keeper_reserve_default_address( 78 usb_device_keeper_t *instance, usb_speed_t speed) 70 79 { 71 80 assert(instance); … … 101 110 * Really ugly one. 102 111 */ 103 void usb_device_keeper_reset_if_need( usb_device_keeper_t *instance,104 usb_ target_t target, const uint8_t *data)112 void usb_device_keeper_reset_if_need( 113 usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data) 105 114 { 106 115 assert(instance); … … 120 129 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 121 130 /* endpoint number is < 16, thus first byte is enough */ 122 instance->devices[target.address].toggle_status[0] &= 123 ~(1 << data[4]); 124 instance->devices[target.address].toggle_status[1] &= 125 ~(1 << data[4]); 131 assert(!"NOT IMPLEMENTED!"); 126 132 } 127 133 break; … … 131 137 /* target must be device */ 132 138 if ((data[0] & 0xf) == 0) { 133 instance->devices[target.address].toggle_status[0] = 0; 134 instance->devices[target.address].toggle_status[1] = 0; 139 link_t *current = 140 instance->devices[target.address].endpoints.next; 141 while (current != 142 &instance->devices[target.address].endpoints) 143 { 144 endpoint_toggle_reset(current); 145 current = current->next; 146 } 135 147 } 136 148 break; 137 149 } 138 150 fibril_mutex_unlock(&instance->guard); 139 }140 /*----------------------------------------------------------------------------*/141 /** Get current value of endpoint toggle.142 *143 * @param[in] instance Device keeper structure to use.144 * @param[in] target Device and endpoint used.145 * @return Error code146 */147 int usb_device_keeper_get_toggle(usb_device_keeper_t *instance,148 usb_target_t target, usb_direction_t direction)149 {150 assert(instance);151 /* only control pipes are bi-directional and those do not need toggle */152 if (direction == USB_DIRECTION_BOTH)153 return ENOENT;154 int ret;155 fibril_mutex_lock(&instance->guard);156 if (target.endpoint > 15 || target.endpoint < 0157 || target.address >= USB_ADDRESS_COUNT || target.address < 0158 || !instance->devices[target.address].occupied) {159 usb_log_error("Invalid data when asking for toggle value.\n");160 ret = EINVAL;161 } else {162 ret = (instance->devices[target.address].toggle_status[direction]163 >> target.endpoint) & 1;164 }165 fibril_mutex_unlock(&instance->guard);166 return ret;167 }168 /*----------------------------------------------------------------------------*/169 /** Set current value of endpoint toggle.170 *171 * @param[in] instance Device keeper structure to use.172 * @param[in] target Device and endpoint used.173 * @param[in] toggle Toggle value.174 * @return Error code.175 */176 int usb_device_keeper_set_toggle(usb_device_keeper_t *instance,177 usb_target_t target, usb_direction_t direction, bool toggle)178 {179 assert(instance);180 /* only control pipes are bi-directional and those do not need toggle */181 if (direction == USB_DIRECTION_BOTH)182 return ENOENT;183 int ret;184 fibril_mutex_lock(&instance->guard);185 if (target.endpoint > 15 || target.endpoint < 0186 || target.address >= USB_ADDRESS_COUNT || target.address < 0187 || !instance->devices[target.address].occupied) {188 usb_log_error("Invalid data when setting toggle value.\n");189 ret = EINVAL;190 } else {191 if (toggle) {192 instance->devices[target.address].toggle_status[direction]193 |= (1 << target.endpoint);194 } else {195 instance->devices[target.address].toggle_status[direction]196 &= ~(1 << target.endpoint);197 }198 ret = EOK;199 }200 fibril_mutex_unlock(&instance->guard);201 return ret;202 151 } 203 152 /*----------------------------------------------------------------------------*/ … … 208 157 * @return Free address, or error code. 209 158 */ 210 usb_address_t device_keeper_get_free_address( usb_device_keeper_t *instance,211 usb_ speed_t speed)159 usb_address_t device_keeper_get_free_address( 160 usb_device_keeper_t *instance, usb_speed_t speed) 212 161 { 213 162 assert(instance); … … 229 178 instance->devices[new_address].occupied = true; 230 179 instance->devices[new_address].speed = speed; 231 instance->devices[new_address].toggle_status[0] = 0;232 instance->devices[new_address].toggle_status[1] = 0;233 180 instance->last_address = new_address; 234 181 fibril_mutex_unlock(&instance->guard); … … 259 206 * @param[in] address Device address 260 207 */ 261 void usb_device_keeper_release( usb_device_keeper_t *instance,262 usb_ address_t address)208 void usb_device_keeper_release( 209 usb_device_keeper_t *instance, usb_address_t address) 263 210 { 264 211 assert(instance); … … 278 225 * @return USB Address, or error code. 279 226 */ 280 usb_address_t usb_device_keeper_find( usb_device_keeper_t *instance,281 devman_handle_t handle)227 usb_address_t usb_device_keeper_find( 228 usb_device_keeper_t *instance, devman_handle_t handle) 282 229 { 283 230 assert(instance); … … 301 248 * @return USB speed. 302 249 */ 303 usb_speed_t usb_device_keeper_get_speed( usb_device_keeper_t *instance,304 usb_ address_t address)250 usb_speed_t usb_device_keeper_get_speed( 251 usb_device_keeper_t *instance, usb_address_t address) 305 252 { 306 253 assert(instance); … … 310 257 } 311 258 /*----------------------------------------------------------------------------*/ 312 void usb_device_keeper_use_control( usb_device_keeper_t *instance,313 usb_ target_t target)259 void usb_device_keeper_use_control( 260 usb_device_keeper_t *instance, usb_target_t target) 314 261 { 315 262 assert(instance); … … 323 270 } 324 271 /*----------------------------------------------------------------------------*/ 325 void usb_device_keeper_release_control( usb_device_keeper_t *instance,326 usb_ target_t target)272 void usb_device_keeper_release_control( 273 usb_device_keeper_t *instance, usb_target_t target) 327 274 { 328 275 assert(instance); -
uspace/lib/usb/src/host/usb_endpoint_manager.c
r6bf9bc4 rdcaf819 1 1 /* 2 2 * Copyright (c) 2011 Jan Vesely 3 * All rights reserved.3 * All rights eps. 4 4 * 5 5 * Redistribution and use in source and binary forms, with or without … … 27 27 */ 28 28 29 #include <bool.h> 29 30 #include <assert.h> 30 31 #include <errno.h> 31 #include <usb/host/bandwidth.h> 32 33 typedef struct { 32 33 #include <usb/host/usb_endpoint_manager.h> 34 35 #define BUCKET_COUNT 7 36 37 typedef struct { 34 38 usb_address_t address; 35 39 usb_endpoint_t endpoint; 36 40 usb_direction_t direction; 37 } __attribute__((aligned (sizeof(unsigned long)))) transfer_t;38 /*----------------------------------------------------------------------------*/ 41 } __attribute__((aligned (sizeof(unsigned long)))) id_t; 42 #define MAX_KEYS (sizeof(id_t) / sizeof(unsigned long)) 39 43 typedef struct { 40 transfer_t transfer; 44 union { 45 id_t id; 46 unsigned long key[MAX_KEYS]; 47 }; 41 48 link_t link; 42 bool used; 43 size_t required; 44 } transfer_status_t; 45 /*----------------------------------------------------------------------------*/ 46 #define BUCKET_COUNT 7 47 #define MAX_KEYS (sizeof(transfer_t) / sizeof(unsigned long)) 48 /*----------------------------------------------------------------------------*/ 49 static hash_index_t transfer_hash(unsigned long key[]) 49 size_t bw; 50 endpoint_t *ep; 51 } node_t; 52 /*----------------------------------------------------------------------------*/ 53 static hash_index_t node_hash(unsigned long key[]) 50 54 { 51 55 hash_index_t hash = 0; … … 58 62 } 59 63 /*----------------------------------------------------------------------------*/ 60 static int transfer_compare( 61 unsigned long key[], hash_count_t keys, link_t *item) 64 static int node_compare(unsigned long key[], hash_count_t keys, link_t *item) 62 65 { 63 66 assert(item); 64 transfer_status_t *status = 65 hash_table_get_instance(item, transfer_status_t, link); 66 const size_t bytes = 67 keys < MAX_KEYS ? keys * sizeof(unsigned long) : sizeof(transfer_t); 68 return bcmp(key, &status->transfer, bytes) == 0; 69 } 70 /*----------------------------------------------------------------------------*/ 71 static void transfer_remove(link_t *item) 67 node_t *node = hash_table_get_instance(item, node_t, link); 68 hash_count_t i = 0; 69 for (; i < keys; ++i) { 70 if (key[i] != node->key[i]) 71 return false; 72 } 73 return true; 74 } 75 /*----------------------------------------------------------------------------*/ 76 static void node_remove(link_t *item) 72 77 { 73 78 assert(item); 74 transfer_status_t *status = 75 hash_table_get_instance(item, transfer_status_t, link); 76 assert(status); 77 free(status); 78 } 79 /*----------------------------------------------------------------------------*/ 80 hash_table_operations_t op = { 81 .hash = transfer_hash, 82 .compare = transfer_compare, 83 .remove_callback = transfer_remove, 79 node_t *node = hash_table_get_instance(item, node_t, link); 80 endpoint_destroy(node->ep); 81 free(node); 82 } 83 /*----------------------------------------------------------------------------*/ 84 static hash_table_operations_t op = { 85 .hash = node_hash, 86 .compare = node_compare, 87 .remove_callback = node_remove, 84 88 }; 85 89 /*----------------------------------------------------------------------------*/ … … 120 124 } 121 125 /*----------------------------------------------------------------------------*/ 122 int bandwidth_init(bandwidth_t *instance, size_t bandwidth,123 size_t (*usage_fnc)(usb_speed_t, usb_transfer_type_t, size_t, size_t))126 int usb_endpoint_manager_init(usb_endpoint_manager_t *instance, 127 size_t available_bandwidth) 124 128 { 125 129 assert(instance); 126 130 fibril_mutex_initialize(&instance->guard); 127 instance->free = bandwidth;128 instance-> usage_fnc = usage_fnc;131 fibril_condvar_initialize(&instance->change); 132 instance->free_bw = available_bandwidth; 129 133 bool ht = 130 hash_table_create(&instance-> reserved, BUCKET_COUNT, MAX_KEYS, &op);134 hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op); 131 135 return ht ? EOK : ENOMEM; 132 136 } 133 137 /*----------------------------------------------------------------------------*/ 134 void bandwidth_destroy(bandwidth_t *instance) 135 { 136 hash_table_destroy(&instance->reserved); 137 } 138 /*----------------------------------------------------------------------------*/ 139 int bandwidth_reserve(bandwidth_t *instance, usb_address_t address, 140 usb_endpoint_t endpoint, usb_direction_t direction, usb_speed_t speed, 141 usb_transfer_type_t transfer_type, size_t max_packet_size, size_t size, 142 unsigned interval) 143 { 144 if (transfer_type != USB_TRANSFER_ISOCHRONOUS && 145 transfer_type != USB_TRANSFER_INTERRUPT) { 146 return ENOTSUP; 147 } 148 149 assert(instance); 150 assert(instance->usage_fnc); 151 152 transfer_t trans = { 138 void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance) 139 { 140 hash_table_destroy(&instance->ep_table); 141 } 142 /*----------------------------------------------------------------------------*/ 143 int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance, 144 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 145 endpoint_t *ep, size_t data_size) 146 { 147 assert(ep); 148 size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type, 149 data_size, ep->max_packet_size); 150 assert(instance); 151 152 id_t id = { 153 153 .address = address, 154 154 .endpoint = endpoint, … … 156 156 }; 157 157 fibril_mutex_lock(&instance->guard); 158 const size_t required = 159 instance->usage_fnc(speed, transfer_type, size, max_packet_size); 160 161 if (required > instance->free) { 158 159 link_t *item = 160 hash_table_find(&instance->ep_table, (unsigned long*)&id); 161 if (item != NULL) { 162 fibril_mutex_unlock(&instance->guard); 163 return EEXISTS; 164 } 165 166 if (bw > instance->free_bw) { 162 167 fibril_mutex_unlock(&instance->guard); 163 168 return ENOSPC; 164 169 } 165 170 166 link_t *item = 167 hash_table_find(&instance->reserved, (unsigned long*)&trans); 168 if (item != NULL) { 169 fibril_mutex_unlock(&instance->guard); 170 return EEXISTS; 171 } 172 173 transfer_status_t *status = malloc(sizeof(transfer_status_t)); 174 if (status == NULL) { 171 node_t *node = malloc(sizeof(node_t)); 172 if (node == NULL) { 175 173 fibril_mutex_unlock(&instance->guard); 176 174 return ENOMEM; 177 175 } 178 176 179 status->transfer = trans;180 status->required = required;181 status->used = false;182 link_initialize(& status->link);183 184 hash_table_insert(&instance-> reserved,185 (unsigned long*)& status->transfer, &status->link);186 instance->free -= required;177 node->id = id; 178 node->bw = bw; 179 node->ep = ep; 180 link_initialize(&node->link); 181 182 hash_table_insert(&instance->ep_table, 183 (unsigned long*)&id, &node->link); 184 instance->free_bw -= bw; 187 185 fibril_mutex_unlock(&instance->guard); 186 fibril_condvar_broadcast(&instance->change); 188 187 return EOK; 189 /* TODO: compute bandwidth used */ 190 } 191 /*----------------------------------------------------------------------------*/ 192 int bandwidth_release(bandwidth_t *instance, usb_address_t address, 193 usb_endpoint_t endpoint, usb_direction_t direction) 194 { 195 assert(instance); 196 transfer_t trans = { 188 } 189 /*----------------------------------------------------------------------------*/ 190 int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance, 191 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 192 { 193 assert(instance); 194 id_t id = { 197 195 .address = address, 198 196 .endpoint = endpoint, … … 201 199 fibril_mutex_lock(&instance->guard); 202 200 link_t *item = 203 hash_table_find(&instance-> reserved, (unsigned long*)&trans);201 hash_table_find(&instance->ep_table, (unsigned long*)&id); 204 202 if (item == NULL) { 205 203 fibril_mutex_unlock(&instance->guard); … … 207 205 } 208 206 209 transfer_status_t *status = 210 hash_table_get_instance(item, transfer_status_t, link); 211 212 instance->free += status->required; 213 214 hash_table_remove(&instance->reserved, 215 (unsigned long*)&trans, MAX_KEYS); 207 node_t *node = hash_table_get_instance(item, node_t, link); 208 instance->free_bw += node->bw; 209 hash_table_remove(&instance->ep_table, (unsigned long*)&id, MAX_KEYS); 216 210 217 211 fibril_mutex_unlock(&instance->guard); 212 fibril_condvar_broadcast(&instance->change); 218 213 return EOK; 219 /* TODO: compute bandwidth freed */ 220 } 221 /*----------------------------------------------------------------------------*/ 222 int bandwidth_use(bandwidth_t *instance, usb_address_t address,223 usb_endpoint_t endpoint, usb_direction_t direction, size_tbw)224 { 225 assert(instance); 226 transfer_t trans= {214 } 215 /*----------------------------------------------------------------------------*/ 216 endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance, 217 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction, 218 size_t *bw) 219 { 220 assert(instance); 221 id_t id = { 227 222 .address = address, 228 223 .endpoint = endpoint, … … 231 226 fibril_mutex_lock(&instance->guard); 232 227 link_t *item = 233 hash_table_find(&instance->reserved, (unsigned long*)&trans); 234 int ret = EOK; 235 if (item != NULL) { 236 transfer_status_t *status = 237 hash_table_get_instance(item, transfer_status_t, link); 238 assert(status); 239 if (status->required >= bw) { 240 if (status->used) { 241 ret = EINPROGRESS; 242 } 243 status->used = true; 244 } else { 245 ret = ENOSPC; 246 } 247 } else { 248 ret = EINVAL; 249 } 228 hash_table_find(&instance->ep_table, (unsigned long*)&id); 229 if (item == NULL) { 230 fibril_mutex_unlock(&instance->guard); 231 return NULL; 232 } 233 node_t *node = hash_table_get_instance(item, node_t, link); 234 if (bw) 235 *bw = node->bw; 236 250 237 fibril_mutex_unlock(&instance->guard); 251 return ret; 252 } 253 /*----------------------------------------------------------------------------*/ 254 int bandwidth_free(bandwidth_t *instance, usb_address_t address, 255 usb_endpoint_t endpoint, usb_direction_t direction) 256 { 257 assert(instance); 258 transfer_t trans = { 259 .address = address, 260 .endpoint = endpoint, 261 .direction = direction, 262 }; 263 fibril_mutex_lock(&instance->guard); 264 link_t *item = 265 hash_table_find(&instance->reserved, (unsigned long*)&trans); 266 int ret = EOK; 267 if (item != NULL) { 268 transfer_status_t *status = 269 hash_table_get_instance(item, transfer_status_t, link); 270 assert(status); 271 if (!status->used) { 272 ret = ENOENT; 273 } 274 status->used = false; 275 } else { 276 ret = EINVAL; 277 } 278 fibril_mutex_unlock(&instance->guard); 279 return ret; 280 } 238 return node->ep; 239 }
Note:
See TracChangeset
for help on using the changeset viewer.