Changes in uspace/lib/usbdev/src/devpoll.c [b77931d:a0487a2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbdev/src/devpoll.c
rb77931d ra0487a2 46 46 /** Data needed for polling. */ 47 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 48 /** Parameters for automated polling. */ 49 usb_device_auto_polling_t auto_polling; 50 51 /** USB device to poll. */ 56 52 usb_device_t *dev; 53 /** Device pipe to use for polling. */ 57 54 size_t pipe_index; 55 /** Size of the recieved data. */ 58 56 size_t request_size; 57 /** Data buffer. */ 59 58 uint8_t *buffer; 60 void *custom_arg;61 59 } polling_data_t; 62 60 … … 69 67 static int polling_fibril(void *arg) 70 68 { 71 polling_data_t *polling_data = (polling_data_t *) arg; 72 assert(polling_data); 69 assert(arg); 70 const polling_data_t *data = arg; 71 /* Helper to reduce typing. */ 72 const usb_device_auto_polling_t *params = &data->auto_polling; 73 73 74 74 usb_pipe_t *pipe 75 = & polling_data->dev->pipes[polling_data->pipe_index].pipe;76 77 if (p olling_data->debug > 0) {78 usb_endpoint_mapping_t *mapping79 = & polling_data->dev->pipes[polling_data->pipe_index];75 = &data->dev->pipes[data->pipe_index].pipe; 76 77 if (params->debug > 0) { 78 const usb_endpoint_mapping_t *mapping 79 = &data->dev->pipes[data->pipe_index]; 80 80 usb_log_debug("Poll%p: started polling of `%s' - " \ 81 81 "interface %d (%s,%d,%d), %zuB/%zu.\n", 82 polling_data, 83 polling_data->dev->ddf_dev->name, 82 data, data->dev->ddf_dev->name, 84 83 (int) mapping->interface->interface_number, 85 84 usb_str_class(mapping->interface->interface_class), 86 85 (int) mapping->interface->interface_subclass, 87 86 (int) mapping->interface->interface_protocol, 88 polling_data->request_size, pipe->max_packet_size); 89 } 90 87 data->request_size, pipe->max_packet_size); 88 } 89 90 usb_pipe_start_long_transfer(pipe); 91 91 size_t failed_attempts = 0; 92 while (failed_attempts <= polling_data->max_failures) { 93 int rc; 94 92 while (failed_attempts <= params->max_failures) { 95 93 size_t actual_size; 96 rc = usb_pipe_read(pipe, polling_data->buffer,97 polling_data->request_size, &actual_size);98 99 if (p olling_data->debug > 1) {94 const int rc = usb_pipe_read(pipe, data->buffer, 95 data->request_size, &actual_size); 96 97 if (params->debug > 1) { 100 98 if (rc == EOK) { 101 99 usb_log_debug( 102 100 "Poll%p: received: '%s' (%zuB).\n", 103 polling_data,104 usb_debug_str_buffer( polling_data->buffer,101 data, 102 usb_debug_str_buffer(data->buffer, 105 103 actual_size, 16), 106 104 actual_size); … … 108 106 usb_log_debug( 109 107 "Poll%p: polling failed: %s.\n", 110 polling_data, str_error(rc));108 data, str_error(rc)); 111 109 } 112 110 } 113 111 114 112 /* If the pipe stalled, we can try to reset the stall. */ 115 if ((rc == ESTALL) && (p olling_data->auto_clear_halt)) {113 if ((rc == ESTALL) && (params->auto_clear_halt)) { 116 114 /* 117 115 * We ignore error here as this is usually a futile … … 119 117 */ 120 118 usb_request_clear_endpoint_halt( 121 &polling_data->dev->ctrl_pipe, 122 pipe->endpoint_no); 119 &data->dev->ctrl_pipe, pipe->endpoint_no); 123 120 } 124 121 125 122 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 } 123 ++failed_attempts; 124 const bool cont = (params->on_error == NULL) ? true : 125 params->on_error(data->dev, rc, params->arg); 126 if (!cont) { 127 failed_attempts = params->max_failures; 134 128 } 135 failed_attempts++;136 129 continue; 137 130 } 138 131 139 132 /* We have the data, execute the callback now. */ 140 bool carry_on = polling_data->on_data(polling_data->dev,141 polling_data->buffer, actual_size,142 polling_data->custom_arg);133 assert(params->on_data); 134 const bool carry_on = params->on_data( 135 data->dev, data->buffer, actual_size, params->arg); 143 136 144 137 if (!carry_on) { 138 /* This is user requested abort, erases failures. */ 145 139 failed_attempts = 0; 146 140 break; … … 151 145 152 146 /* 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, 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"); 147 async_usleep(params->delay); 148 } 149 150 usb_pipe_end_long_transfer(pipe); 151 152 const bool failed = failed_attempts > 0; 153 154 if (params->on_polling_end != NULL) { 155 params->on_polling_end(data->dev, failed, params->arg); 156 } 157 158 if (params->debug > 0) { 159 if (failed) { 160 usb_log_error("Polling of device `%s' terminated: " 161 "recurring failures.\n", data->dev->ddf_dev->name); 167 162 } else { 168 usb_log_debug( 169 "Polling of device `%s' terminated by user.\n", 170 polling_data->dev->ddf_dev->name 171 ); 163 usb_log_debug("Polling of device `%s' terminated: " 164 "driver request.\n", data->dev->ddf_dev->name); 172 165 } 173 166 } 174 167 175 168 /* Free the allocated memory. */ 176 free( polling_data->buffer);177 free( polling_data);169 free(data->buffer); 170 free(data); 178 171 179 172 return EOK; … … 202 195 usb_polling_terminted_callback_t terminated_callback, void *arg) 203 196 { 204 if ((dev == NULL) || (callback == NULL)) {205 return EBADMEM;206 }207 if (request_size == 0) {208 return EINVAL;209 }210 if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)211 || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {212 return EINVAL;213 }214 215 197 const usb_device_auto_polling_t auto_polling = { 216 198 .debug = 1, … … 221 203 .on_polling_end = terminated_callback, 222 204 .on_error = NULL, 205 .arg = arg, 223 206 }; 224 207 225 208 return usb_device_auto_polling(dev, pipe_index, &auto_polling, 226 request_size , arg);209 request_size); 227 210 } 228 211 … … 246 229 int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index, 247 230 const usb_device_auto_polling_t *polling, 248 size_t request_size , void *arg)231 size_t request_size) 249 232 { 250 if ( dev == NULL) {233 if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) { 251 234 return EBADMEM; 252 235 } 253 if (pipe_index >= dev->pipes_count) { 236 237 if (pipe_index >= dev->pipes_count || request_size == 0) { 254 238 return EINVAL; 255 239 } … … 257 241 || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) { 258 242 return EINVAL; 259 }260 if ((polling == NULL) || (polling->on_data == NULL)) {261 return EBADMEM;262 243 } 263 244 … … 276 257 polling_data->dev = dev; 277 258 polling_data->pipe_index = pipe_index; 278 polling_data->custom_arg = arg; 279 280 polling_data->debug = polling->debug; 281 polling_data->max_failures = polling->max_failures; 282 if (polling->delay >= 0) { 283 polling_data->delay = (useconds_t) polling->delay; 284 } else { 285 polling_data->delay = (useconds_t) dev->pipes[pipe_index] 286 .descriptor->poll_interval; 287 } 288 polling_data->auto_clear_halt = polling->auto_clear_halt; 289 290 polling_data->on_data = polling->on_data; 291 polling_data->on_polling_end = polling->on_polling_end; 292 polling_data->on_error = polling->on_error; 259 260 /* Copy provided settings. */ 261 polling_data->auto_polling = *polling; 262 263 /* Negative value means use descriptor provided value. */ 264 if (polling->delay < 0) { 265 polling_data->auto_polling.delay = 266 (int) dev->pipes[pipe_index].descriptor->poll_interval; 267 } 293 268 294 269 fid_t fibril = fibril_create(polling_fibril, polling_data);
Note:
See TracChangeset
for help on using the changeset viewer.