Changeset 5fd9c30 in mainline for uspace/lib/usbhost/src/usb_transfer_batch.c
- Timestamp:
- 2017-10-21T20:52:56Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 766043c
- Parents:
- 74b852b
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbhost/src/usb_transfer_batch.c
r74b852b r5fd9c30 34 34 35 35 #include <usb/host/usb_transfer_batch.h> 36 #include <usb/host/endpoint.h> 37 #include <usb/host/bus.h> 36 38 #include <usb/debug.h> 37 39 38 40 #include <assert.h> 39 41 #include <errno.h> 40 #include <macros.h>41 #include <mem.h>42 #include <stdlib.h>43 #include <usbhc_iface.h>44 42 45 /** Allocate and initialize usb_transfer_batch structure. 46 * @param ep endpoint used by the transfer batch. 47 * @param buffer data to send/recieve. 48 * @param buffer_size Size of data buffer. 49 * @param setup_buffer Data to send in SETUP stage of control transfer. 50 * @param func_in callback on IN transfer completion. 51 * @param func_out callback on OUT transfer completion. 52 * @param fun DDF function (passed to callback function). 53 * @param arg Argument to pass to the callback function. 54 * @param private_data driver specific per batch data. 55 * @param private_data_dtor Function to properly destroy private_data. 56 * @return Pointer to valid usb_transfer_batch_t structure, NULL on failure. 43 44 /** Create a batch on given endpoint. 57 45 */ 58 usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *ep, char *buffer, 59 size_t buffer_size, 60 uint64_t setup_buffer, 61 usbhc_iface_transfer_in_callback_t func_in, 62 usbhc_iface_transfer_out_callback_t func_out, 63 void *arg) 46 usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *ep) 64 47 { 65 if (func_in == NULL && func_out == NULL) 66 return NULL; 67 if (func_in != NULL && func_out != NULL) 68 return NULL; 48 assert(ep); 49 assert(ep->bus); 69 50 70 usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t)); 71 if (instance) { 72 instance->ep = ep; 73 instance->callback_in = func_in; 74 instance->callback_out = func_out; 75 instance->arg = arg; 76 instance->buffer = buffer; 77 instance->buffer_size = buffer_size; 78 instance->setup_size = 0; 79 instance->transfered_size = 0; 80 instance->error = EOK; 81 if (ep && ep->transfer_type == USB_TRANSFER_CONTROL) { 82 memcpy(instance->setup_buffer, &setup_buffer, 83 USB_SETUP_PACKET_SIZE); 84 instance->setup_size = USB_SETUP_PACKET_SIZE; 85 } 86 if (instance->ep) 87 endpoint_use(instance->ep); 88 } 89 return instance; 51 usb_transfer_batch_t *batch; 52 if (ep->bus->ops.create_batch) 53 batch = ep->bus->ops.create_batch(ep->bus, ep); 54 else 55 batch = malloc(sizeof(usb_transfer_batch_t)); 56 57 return batch; 90 58 } 91 59 92 /** Correctly dispose all used data structures. 93 * 94 * @param[in] instance Batch structure to use. 60 /** Initialize given batch structure. 95 61 */ 96 void usb_transfer_batch_ destroy(const usb_transfer_batch_t *instance)62 void usb_transfer_batch_init(usb_transfer_batch_t *batch, endpoint_t *ep) 97 63 { 98 if (!instance) 99 return; 100 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n", 101 instance, USB_TRANSFER_BATCH_ARGS(*instance)); 102 if (instance->ep) { 103 endpoint_release(instance->ep); 104 } 105 free(instance); 64 memset(batch, 0, sizeof(*batch)); 65 66 batch->ep = ep; 67 68 endpoint_use(ep); 106 69 } 107 70 108 /** Prepare data and call the right callback.71 /** Call the handler of the batch. 109 72 * 110 * @param[in] instance Batch structure to use. 111 * @param[in] data Data to copy to the output buffer. 112 * @param[in] size Size of @p data. 113 * @param[in] error Error value to use. 73 * @param[in] batch Batch structure to use. 114 74 */ 115 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance, 116 const void *data, size_t size, int error) 75 static int batch_complete(usb_transfer_batch_t *batch) 117 76 { 118 assert(instance); 119 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " finishing.\n", 120 instance, USB_TRANSFER_BATCH_ARGS(*instance)); 77 assert(batch); 121 78 122 /* NOTE: Only one of these pointers should be set. */ 123 if (instance->callback_out) { 124 instance->callback_out(error, instance->arg); 79 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed.\n", 80 batch, USB_TRANSFER_BATCH_ARGS(*batch)); 81 82 if (batch->error == EOK && batch->toggle_reset_mode != RESET_NONE) { 83 usb_log_debug2("Reseting %s due to transaction of %d:%d.\n", 84 batch->toggle_reset_mode == RESET_ALL ? "all EPs toggle" : "EP toggle", 85 batch->ep->target.address, batch->ep->target.endpoint); 86 bus_reset_toggle(batch->ep->bus, 87 batch->ep->target, batch->toggle_reset_mode == RESET_ALL); 125 88 } 126 89 127 if (instance->callback_in) { 128 /* We care about the data and there are some to copy */ 129 const size_t safe_size = min(size, instance->buffer_size); 130 if (data) { 131 memcpy(instance->buffer, data, safe_size); 132 } 133 instance->callback_in(error, safe_size, instance->arg); 134 } 90 return batch->on_complete 91 ? batch->on_complete(batch) 92 : EOK; 93 } 94 95 /** Destroy the batch. 96 * 97 * @param[in] batch Batch structure to use. 98 */ 99 void usb_transfer_batch_destroy(usb_transfer_batch_t *batch) 100 { 101 assert(batch); 102 assert(batch->ep); 103 assert(batch->ep->bus); 104 105 usb_log_debug2("batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n", 106 batch, USB_TRANSFER_BATCH_ARGS(*batch)); 107 108 bus_t *bus = batch->ep->bus; 109 if (bus->ops.destroy_batch) 110 bus->ops.destroy_batch(batch); 111 else 112 free(batch); 113 114 endpoint_release(batch->ep); 115 } 116 117 /** Finish a transfer batch: call handler, destroy batch, release endpoint. 118 * 119 * Call only after the batch have been scheduled && completed! 120 * 121 * @param[in] batch Batch structure to use. 122 */ 123 void usb_transfer_batch_finish(usb_transfer_batch_t *batch) 124 { 125 if (!batch_complete(batch)) 126 usb_log_warning("failed to complete batch %p!", batch); 127 128 usb_transfer_batch_destroy(batch); 129 } 130 131 132 struct old_handler_wrapper_data { 133 usbhc_iface_transfer_in_callback_t in_callback; 134 usbhc_iface_transfer_out_callback_t out_callback; 135 void *arg; 136 }; 137 138 static int old_handler_wrapper(usb_transfer_batch_t *batch) 139 { 140 struct old_handler_wrapper_data *data = batch->on_complete_data; 141 142 assert(data); 143 144 if (data->out_callback) 145 data->out_callback(batch->error, data->arg); 146 147 if (data->in_callback) 148 data->in_callback(batch->error, batch->transfered_size, data->arg); 149 150 free(data); 151 return EOK; 152 } 153 154 void usb_transfer_batch_set_old_handlers(usb_transfer_batch_t *batch, 155 usbhc_iface_transfer_in_callback_t in_callback, 156 usbhc_iface_transfer_out_callback_t out_callback, 157 void *arg) 158 { 159 struct old_handler_wrapper_data *data = malloc(sizeof(*data)); 160 161 data->in_callback = in_callback; 162 data->out_callback = out_callback; 163 data->arg = arg; 164 165 batch->on_complete = old_handler_wrapper; 166 batch->on_complete_data = data; 135 167 } 136 168 /**
Note:
See TracChangeset
for help on using the changeset viewer.