Changeset e50cd7f in mainline for uspace/lib/usb/src/devpoll.c
- Timestamp:
- 2011-04-17T19:17:55Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 63517c2, cfbbe1d3
- Parents:
- ef354b6 (diff), 8595577b (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/devpoll.c
ref354b6 re50cd7f 33 33 * USB device driver framework - automatic interrupt polling. 34 34 */ 35 #include <usb/dev drv.h>35 #include <usb/devpoll.h> 36 36 #include <usb/request.h> 37 37 #include <usb/debug.h> 38 #include <usb/classes/classes.h> 38 39 #include <errno.h> 39 40 #include <str_error.h> … … 45 46 /** Data needed for polling. */ 46 47 typedef struct { 48 int debug; 49 size_t max_failures; 50 useconds_t delay; 51 bool auto_clear_halt; 52 bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *); 53 void (*on_polling_end)(usb_device_t *, bool, void *); 54 bool (*on_error)(usb_device_t *, int, void *); 55 47 56 usb_device_t *dev; 48 57 size_t pipe_index; 49 usb_polling_callback_t callback;50 usb_polling_terminted_callback_t terminated_callback;51 58 size_t request_size; 52 59 uint8_t *buffer; … … 54 61 } polling_data_t; 55 62 63 56 64 /** Polling fibril. 57 65 * … … 66 74 usb_pipe_t *pipe 67 75 = polling_data->dev->pipes[polling_data->pipe_index].pipe; 76 77 if (polling_data->debug > 0) { 78 usb_endpoint_mapping_t *mapping 79 = &polling_data->dev->pipes[polling_data->pipe_index]; 80 usb_log_debug("Poll0x%x: started polling of `%s' - " \ 81 "interface %d (%s,%d,%d), %zuB/%zu.\n", 82 polling_data, 83 polling_data->dev->ddf_dev->name, 84 (int) mapping->interface->interface_number, 85 usb_str_class(mapping->interface->interface_class), 86 (int) mapping->interface->interface_subclass, 87 (int) mapping->interface->interface_protocol, 88 polling_data->request_size, pipe->max_packet_size); 89 } 68 90 69 91 size_t failed_attempts = 0; 70 while (failed_attempts < MAX_FAILED_ATTEMPTS) {92 while (failed_attempts <= polling_data->max_failures) { 71 93 int rc; 72 73 rc = usb_pipe_start_session(pipe);74 if (rc != EOK) {75 failed_attempts++;76 continue;77 }78 94 79 95 size_t actual_size; … … 81 97 polling_data->request_size, &actual_size); 82 98 83 /* Quit the session regardless of errors. */ 84 usb_pipe_end_session(pipe); 99 if (polling_data->debug > 1) { 100 if (rc == EOK) { 101 usb_log_debug( 102 "Poll0x%x: received: '%s' (%zuB).\n", 103 polling_data, 104 usb_debug_str_buffer(polling_data->buffer, 105 actual_size, 16), 106 actual_size); 107 } else { 108 usb_log_debug( 109 "Poll0x%x: polling failed: %s.\n", 110 polling_data, str_error(rc)); 111 } 112 } 113 114 /* If the pipe stalled, we can try to reset the stall. */ 115 if ((rc == ESTALL) && (polling_data->auto_clear_halt)) { 116 /* 117 * We ignore error here as this is usually a futile 118 * attempt anyway. 119 */ 120 usb_request_clear_endpoint_halt( 121 &polling_data->dev->ctrl_pipe, 122 pipe->endpoint_no); 123 } 85 124 86 125 if (rc != EOK) { 126 if (polling_data->on_error != NULL) { 127 bool cont = polling_data->on_error( 128 polling_data->dev, rc, 129 polling_data->custom_arg); 130 if (!cont) { 131 failed_attempts 132 = polling_data->max_failures; 133 } 134 } 87 135 failed_attempts++; 88 136 continue; … … 90 138 91 139 /* We have the data, execute the callback now. */ 92 bool carry_on = polling_data-> callback(polling_data->dev,140 bool carry_on = polling_data->on_data(polling_data->dev, 93 141 polling_data->buffer, actual_size, 94 142 polling_data->custom_arg); … … 101 149 /* Reset as something might be only a temporary problem. */ 102 150 failed_attempts = 0; 103 } 104 105 if (failed_attempts > 0) { 106 usb_log_error( 107 "Polling of device `%s' terminated: recurring failures.\n", 108 polling_data->dev->ddf_dev->name); 109 } 110 111 if (polling_data->terminated_callback != NULL) { 112 polling_data->terminated_callback(polling_data->dev, 151 152 /* Take a rest before next request. */ 153 async_usleep(polling_data->delay); 154 } 155 156 if (polling_data->on_polling_end != NULL) { 157 polling_data->on_polling_end(polling_data->dev, 113 158 failed_attempts > 0, polling_data->custom_arg); 159 } 160 161 if (polling_data->debug > 0) { 162 if (failed_attempts > 0) { 163 usb_log_error( 164 "Polling of device `%s' terminated: %s.\n", 165 polling_data->dev->ddf_dev->name, 166 "recurring failures"); 167 } else { 168 usb_log_debug( 169 "Polling of device `%s' terminated by user.\n", 170 polling_data->dev->ddf_dev->name 171 ); 172 } 114 173 } 115 174 … … 154 213 } 155 214 215 usb_device_auto_polling_t *auto_polling 216 = malloc(sizeof(usb_device_auto_polling_t)); 217 if (auto_polling == NULL) { 218 return ENOMEM; 219 } 220 221 auto_polling->debug = 1; 222 auto_polling->auto_clear_halt = true; 223 auto_polling->delay = 0; 224 auto_polling->max_failures = MAX_FAILED_ATTEMPTS; 225 auto_polling->on_data = callback; 226 auto_polling->on_polling_end = terminated_callback; 227 auto_polling->on_error = NULL; 228 229 int rc = usb_device_auto_polling(dev, pipe_index, auto_polling, 230 request_size, arg); 231 232 free(auto_polling); 233 234 return rc; 235 } 236 237 /** Start automatic device polling over interrupt in pipe. 238 * 239 * The polling settings is copied thus it is okay to destroy the structure 240 * after this function returns. 241 * 242 * @warning There is no guarantee when the request to the device 243 * will be sent for the first time (it is possible that this 244 * first request would be executed prior to return from this function). 245 * 246 * @param dev Device to be periodically polled. 247 * @param pipe_index Index of the endpoint pipe used for polling. 248 * @param polling Polling settings. 249 * @param request_size How many bytes to ask for in each request. 250 * @param arg Custom argument (passed as is to the callbacks). 251 * @return Error code. 252 * @retval EOK New fibril polling the device was already started. 253 */ 254 int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index, 255 usb_device_auto_polling_t *polling, 256 size_t request_size, void *arg) 257 { 258 if (dev == NULL) { 259 return EBADMEM; 260 } 261 if (pipe_index >= dev->pipes_count) { 262 return EINVAL; 263 } 264 if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT) 265 || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) { 266 return EINVAL; 267 } 268 if ((polling == NULL) || (polling->on_data == NULL)) { 269 return EBADMEM; 270 } 271 156 272 polling_data_t *polling_data = malloc(sizeof(polling_data_t)); 157 273 if (polling_data == NULL) { … … 159 275 } 160 276 161 /* Allocate now to prevent immediate failure in the polling fibril. */162 polling_data->buffer = malloc( request_size);277 /* Fill-in the data. */ 278 polling_data->buffer = malloc(sizeof(request_size)); 163 279 if (polling_data->buffer == NULL) { 164 280 free(polling_data); 165 281 return ENOMEM; 166 282 } 283 polling_data->request_size = request_size; 167 284 polling_data->dev = dev; 168 285 polling_data->pipe_index = pipe_index; 169 polling_data->callback = callback;170 polling_data->terminated_callback = terminated_callback;171 polling_data->request_size = request_size;172 286 polling_data->custom_arg = arg; 287 288 polling_data->debug = polling->debug; 289 polling_data->max_failures = polling->max_failures; 290 if (polling->delay >= 0) { 291 polling_data->delay = (useconds_t) polling->delay; 292 } else { 293 polling_data->delay = (useconds_t) dev->pipes[pipe_index] 294 .descriptor->poll_interval; 295 } 296 polling_data->auto_clear_halt = polling->auto_clear_halt; 297 298 polling_data->on_data = polling->on_data; 299 polling_data->on_polling_end = polling->on_polling_end; 300 polling_data->on_error = polling->on_error; 173 301 174 302 fid_t fibril = fibril_create(polling_fibril, polling_data); … … 176 304 free(polling_data->buffer); 177 305 free(polling_data); 178 /* FIXME: better error code. */179 306 return ENOMEM; 180 307 } 181 308 fibril_add_ready(fibril); 182 309 183 /* The allocated buffer etc. will be freed by the fibril. */310 /* Fibril launched. That fibril will free the allocated data. */ 184 311 185 312 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.