00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <usb/dev/poll.h>
00036 #include <usb/dev/request.h>
00037 #include <usb/debug.h>
00038 #include <usb/classes/classes.h>
00039 #include <errno.h>
00040 #include <str_error.h>
00041 #include <assert.h>
00042
00044 #define MAX_FAILED_ATTEMPTS 3
00045
00047 typedef struct {
00048 int debug;
00049 size_t max_failures;
00050 useconds_t delay;
00051 bool auto_clear_halt;
00052 bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *);
00053 void (*on_polling_end)(usb_device_t *, bool, void *);
00054 bool (*on_error)(usb_device_t *, int, void *);
00055
00056 usb_device_t *dev;
00057 size_t pipe_index;
00058 size_t request_size;
00059 uint8_t *buffer;
00060 void *custom_arg;
00061 } polling_data_t;
00062
00063
00069 static int polling_fibril(void *arg)
00070 {
00071 polling_data_t *polling_data = (polling_data_t *) arg;
00072 assert(polling_data);
00073
00074 usb_pipe_t *pipe
00075 = polling_data->dev->pipes[polling_data->pipe_index].pipe;
00076
00077 if (polling_data->debug > 0) {
00078 usb_endpoint_mapping_t *mapping
00079 = &polling_data->dev->pipes[polling_data->pipe_index];
00080 usb_log_debug("Poll%p: started polling of `%s' - " \
00081 "interface %d (%s,%d,%d), %zuB/%zu.\n",
00082 polling_data,
00083 polling_data->dev->ddf_dev->name,
00084 (int) mapping->interface->interface_number,
00085 usb_str_class(mapping->interface->interface_class),
00086 (int) mapping->interface->interface_subclass,
00087 (int) mapping->interface->interface_protocol,
00088 polling_data->request_size, pipe->max_packet_size);
00089 }
00090
00091 size_t failed_attempts = 0;
00092 while (failed_attempts <= polling_data->max_failures) {
00093 int rc;
00094
00095 size_t actual_size;
00096 rc = usb_pipe_read(pipe, polling_data->buffer,
00097 polling_data->request_size, &actual_size);
00098
00099 if (polling_data->debug > 1) {
00100 if (rc == EOK) {
00101 usb_log_debug(
00102 "Poll%p: received: '%s' (%zuB).\n",
00103 polling_data,
00104 usb_debug_str_buffer(polling_data->buffer,
00105 actual_size, 16),
00106 actual_size);
00107 } else {
00108 usb_log_debug(
00109 "Poll%p: polling failed: %s.\n",
00110 polling_data, str_error(rc));
00111 }
00112 }
00113
00114
00115 if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
00116
00117
00118
00119
00120 usb_request_clear_endpoint_halt(
00121 &polling_data->dev->ctrl_pipe,
00122 pipe->endpoint_no);
00123 }
00124
00125 if (rc != EOK) {
00126 if (polling_data->on_error != NULL) {
00127 bool cont = polling_data->on_error(
00128 polling_data->dev, rc,
00129 polling_data->custom_arg);
00130 if (!cont) {
00131 failed_attempts
00132 = polling_data->max_failures;
00133 }
00134 }
00135 failed_attempts++;
00136 continue;
00137 }
00138
00139
00140 bool carry_on = polling_data->on_data(polling_data->dev,
00141 polling_data->buffer, actual_size,
00142 polling_data->custom_arg);
00143
00144 if (!carry_on) {
00145 failed_attempts = 0;
00146 break;
00147 }
00148
00149
00150 failed_attempts = 0;
00151
00152
00153 async_usleep(polling_data->delay);
00154 }
00155
00156 if (polling_data->on_polling_end != NULL) {
00157 polling_data->on_polling_end(polling_data->dev,
00158 failed_attempts > 0, polling_data->custom_arg);
00159 }
00160
00161 if (polling_data->debug > 0) {
00162 if (failed_attempts > 0) {
00163 usb_log_error(
00164 "Polling of device `%s' terminated: %s.\n",
00165 polling_data->dev->ddf_dev->name,
00166 "recurring failures");
00167 } else {
00168 usb_log_debug(
00169 "Polling of device `%s' terminated by user.\n",
00170 polling_data->dev->ddf_dev->name
00171 );
00172 }
00173 }
00174
00175
00176 free(polling_data->buffer);
00177 free(polling_data);
00178
00179 return EOK;
00180 }
00181
00200 int usb_device_auto_poll(usb_device_t *dev, size_t pipe_index,
00201 usb_polling_callback_t callback, size_t request_size,
00202 usb_polling_terminted_callback_t terminated_callback, void *arg)
00203 {
00204 if ((dev == NULL) || (callback == NULL)) {
00205 return EBADMEM;
00206 }
00207 if (request_size == 0) {
00208 return EINVAL;
00209 }
00210 if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
00211 || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
00212 return EINVAL;
00213 }
00214
00215 usb_device_auto_polling_t *auto_polling
00216 = malloc(sizeof(usb_device_auto_polling_t));
00217 if (auto_polling == NULL) {
00218 return ENOMEM;
00219 }
00220
00221 auto_polling->debug = 1;
00222 auto_polling->auto_clear_halt = true;
00223 auto_polling->delay = 0;
00224 auto_polling->max_failures = MAX_FAILED_ATTEMPTS;
00225 auto_polling->on_data = callback;
00226 auto_polling->on_polling_end = terminated_callback;
00227 auto_polling->on_error = NULL;
00228
00229 int rc = usb_device_auto_polling(dev, pipe_index, auto_polling,
00230 request_size, arg);
00231
00232 free(auto_polling);
00233
00234 return rc;
00235 }
00236
00254 int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
00255 usb_device_auto_polling_t *polling,
00256 size_t request_size, void *arg)
00257 {
00258 if (dev == NULL) {
00259 return EBADMEM;
00260 }
00261 if (pipe_index >= dev->pipes_count) {
00262 return EINVAL;
00263 }
00264 if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
00265 || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
00266 return EINVAL;
00267 }
00268 if ((polling == NULL) || (polling->on_data == NULL)) {
00269 return EBADMEM;
00270 }
00271
00272 polling_data_t *polling_data = malloc(sizeof(polling_data_t));
00273 if (polling_data == NULL) {
00274 return ENOMEM;
00275 }
00276
00277
00278 polling_data->buffer = malloc(sizeof(request_size));
00279 if (polling_data->buffer == NULL) {
00280 free(polling_data);
00281 return ENOMEM;
00282 }
00283 polling_data->request_size = request_size;
00284 polling_data->dev = dev;
00285 polling_data->pipe_index = pipe_index;
00286 polling_data->custom_arg = arg;
00287
00288 polling_data->debug = polling->debug;
00289 polling_data->max_failures = polling->max_failures;
00290 if (polling->delay >= 0) {
00291 polling_data->delay = (useconds_t) polling->delay;
00292 } else {
00293 polling_data->delay = (useconds_t) dev->pipes[pipe_index]
00294 .descriptor->poll_interval;
00295 }
00296 polling_data->auto_clear_halt = polling->auto_clear_halt;
00297
00298 polling_data->on_data = polling->on_data;
00299 polling_data->on_polling_end = polling->on_polling_end;
00300 polling_data->on_error = polling->on_error;
00301
00302 fid_t fibril = fibril_create(polling_fibril, polling_data);
00303 if (fibril == 0) {
00304 free(polling_data->buffer);
00305 free(polling_data);
00306 return ENOMEM;
00307 }
00308 fibril_add_ready(fibril);
00309
00310
00311
00312 return EOK;
00313 }
00314