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