source: mainline/uspace/lib/usbhost/src/usb_transfer_batch.c@ e0a4686

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e0a4686 was e0a5d4c, checked in by Ondřej Hlavatý <aearsis@…>, 7 years ago

usb: update copyrights

The data was generated by a script, guided manually. If you feel your
name is missing somewhere, please add it!

The semi-automated process was roughly:

1) Changes per file and author (limited to our team) were counted
2) Trivial numbers were thrown away
3) Authors were sorted by lines added to file
4) All previous copyrights were replaced by the newly generated one
5) Hunks changing only year were discarded

It seems that a lot of my copyrights were added. It is due to me being
both sticking my nose everywhere and lazy to update the copyright right
away :)

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Copyright (c) 2011 Jan Vesely
3 * Copyright (c) 2018 Ondrej Hlavaty
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29/** @addtogroup libusbhost
30 * @{
31 */
32/** @file
33 * USB transfer transaction structures (implementation).
34 */
35
36#include <assert.h>
37#include <errno.h>
38#include <stdlib.h>
39#include <str_error.h>
40#include <usb/debug.h>
41
42#include "endpoint.h"
43#include "bus.h"
44
45#include "usb_transfer_batch.h"
46
47/**
48 * Create a batch on a given endpoint.
49 *
50 * If the bus callback is not defined, it just creates a default batch.
51 */
52usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *ep)
53{
54 assert(ep);
55
56 bus_t *bus = endpoint_get_bus(ep);
57
58 if (!bus->ops->batch_create) {
59 usb_transfer_batch_t *batch = calloc(1, sizeof(usb_transfer_batch_t));
60 if (!batch)
61 return NULL;
62 usb_transfer_batch_init(batch, ep);
63 return batch;
64 }
65
66 return bus->ops->batch_create(ep);
67}
68
69/**
70 * Initialize given batch structure.
71 */
72void usb_transfer_batch_init(usb_transfer_batch_t *batch, endpoint_t *ep)
73{
74 assert(ep);
75 /* Batch reference */
76 endpoint_add_ref(ep);
77 batch->ep = ep;
78}
79
80/**
81 * Destroy the batch. If there's no bus callback, just free it.
82 */
83void usb_transfer_batch_destroy(usb_transfer_batch_t *batch)
84{
85 assert(batch);
86 assert(batch->ep);
87
88 bus_t *bus = endpoint_get_bus(batch->ep);
89 endpoint_t *ep = batch->ep;
90
91 if (bus->ops) {
92 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " destroying.",
93 batch, USB_TRANSFER_BATCH_ARGS(*batch));
94 bus->ops->batch_destroy(batch);
95 }
96 else {
97 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.",
98 batch, USB_TRANSFER_BATCH_ARGS(*batch));
99 free(batch);
100 }
101
102 /* Batch reference */
103 endpoint_del_ref(ep);
104}
105
106bool usb_transfer_batch_bounce_required(usb_transfer_batch_t *batch)
107{
108 if (!batch->size)
109 return false;
110
111 unsigned flags = batch->dma_buffer.policy & DMA_POLICY_FLAGS_MASK;
112 unsigned required_flags =
113 batch->ep->required_transfer_buffer_policy & DMA_POLICY_FLAGS_MASK;
114
115 if (required_flags & ~flags)
116 return true;
117
118 size_t chunk_mask = dma_policy_chunk_mask(batch->dma_buffer.policy);
119 size_t required_chunk_mask =
120 dma_policy_chunk_mask(batch->ep->required_transfer_buffer_policy);
121
122 /* If the chunks are at least as large as required, we're good */
123 if ((required_chunk_mask & ~chunk_mask) == 0)
124 return false;
125
126 size_t start_chunk = batch->offset & ~chunk_mask;
127 size_t end_chunk = (batch->offset + batch->size - 1) & ~chunk_mask;
128
129 /* The requested area crosses a chunk boundary */
130 if (start_chunk != end_chunk)
131 return true;
132
133 return false;
134}
135
136errno_t usb_transfer_batch_bounce(usb_transfer_batch_t *batch)
137{
138 assert(batch);
139 assert(!batch->is_bounced);
140
141 dma_buffer_release(&batch->dma_buffer);
142
143 batch->original_buffer = batch->dma_buffer.virt + batch->offset;
144
145 usb_log_debug("Batch(%p): Buffer cannot be used directly, "
146 "falling back to bounce buffer!", batch);
147
148 const errno_t err = dma_buffer_alloc_policy(&batch->dma_buffer,
149 batch->size, batch->ep->transfer_buffer_policy);
150 if (err)
151 return err;
152
153 /* Copy the data out */
154 if (batch->dir == USB_DIRECTION_OUT)
155 memcpy(batch->dma_buffer.virt,
156 batch->original_buffer,
157 batch->size);
158
159 batch->is_bounced = true;
160 batch->offset = 0;
161
162 return err;
163}
164
165/**
166 * Finish a transfer batch: call handler, destroy batch, release endpoint.
167 *
168 * Call only after the batch have been scheduled && completed!
169 */
170void usb_transfer_batch_finish(usb_transfer_batch_t *batch)
171{
172 assert(batch);
173 assert(batch->ep);
174
175 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " finishing.",
176 batch, USB_TRANSFER_BATCH_ARGS(*batch));
177
178 if (batch->error == EOK && batch->size > 0) {
179 if (batch->is_bounced) {
180 /* We we're forced to use bounce buffer, copy it back */
181 if (batch->dir == USB_DIRECTION_IN)
182 memcpy(batch->original_buffer,
183 batch->dma_buffer.virt,
184 batch->transferred_size);
185
186 dma_buffer_free(&batch->dma_buffer);
187 }
188 else {
189 dma_buffer_release(&batch->dma_buffer);
190 }
191 }
192
193 if (batch->on_complete) {
194 const int err = batch->on_complete(batch->on_complete_data, batch->error, batch->transferred_size);
195 if (err)
196 usb_log_warning("Batch %p failed to complete: %s",
197 batch, str_error(err));
198 }
199
200 usb_transfer_batch_destroy(batch);
201}
202
203/**
204 * @}
205 */
Note: See TracBrowser for help on using the repository browser.