[media] dvb_usb_v2: use Kernel logging (pr_debug/pr_err/pr_info)
[deliverable/linux.git] / drivers / media / dvb / dvb-usb / usb_urb.c
CommitLineData
c79b339f
AP
1/* usb-urb.c is part of the DVB USB library.
2 *
3 * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
4 * see dvb-usb-init.c for copyright information.
5 *
6 * This file keeps functions for initializing and handling the
7 * BULK and ISOC USB data transfers in a generic way.
8 * Can be used for DVB-only and also, that's the plan, for
9 * Hybrid USB devices (analog and DVB).
10 */
11#include "dvb_usb_common.h"
12
13/* URB stuff for streaming */
bce1c029
AP
14
15int usb_urb_reconfig(struct usb_data_stream *stream,
16 struct usb_data_stream_properties *props);
17
c79b339f
AP
18static void usb_urb_complete(struct urb *urb)
19{
20 struct usb_data_stream *stream = urb->context;
21 int ptype = usb_pipetype(urb->pipe);
22 int i;
23 u8 *b;
24
23d8e63a
AP
25 pr_debug("%s: %s urb completed status=%d length=%d/%d" \
26 " pack_num=%d errors=%d\n", __func__,
27 ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk",
28 urb->status, urb->actual_length,
29 urb->transfer_buffer_length,
30 urb->number_of_packets, urb->error_count);
c79b339f
AP
31
32 switch (urb->status) {
4e60d951
AP
33 case 0: /* success */
34 case -ETIMEDOUT: /* NAK */
35 break;
36 case -ECONNRESET: /* kill */
37 case -ENOENT:
38 case -ESHUTDOWN:
39 return;
40 default: /* error */
15072bba
AP
41 pr_debug("%s: URB completition failed=%d\n", __func__,
42 urb->status);
4e60d951 43 break;
c79b339f
AP
44 }
45
46 b = (u8 *) urb->transfer_buffer;
47 switch (ptype) {
4e60d951
AP
48 case PIPE_ISOCHRONOUS:
49 for (i = 0; i < urb->number_of_packets; i++) {
50 if (urb->iso_frame_desc[i].status != 0)
23d8e63a
AP
51 pr_debug("%s: iso frame descriptor has an " \
52 "error=%d\n", __func__,
15072bba 53 urb->iso_frame_desc[i].status);
4e60d951
AP
54 else if (urb->iso_frame_desc[i].actual_length > 0)
55 stream->complete(stream,
56 b + urb->iso_frame_desc[i].offset,
57 urb->iso_frame_desc[i].actual_length);
58
59 urb->iso_frame_desc[i].status = 0;
60 urb->iso_frame_desc[i].actual_length = 0;
61 }
4e60d951
AP
62 break;
63 case PIPE_BULK:
64 if (urb->actual_length > 0)
65 stream->complete(stream, b, urb->actual_length);
66 break;
67 default:
23d8e63a
AP
68 pr_err("%s: unknown endpoint type in completition handler",
69 KBUILD_MODNAME);
4e60d951 70 return;
c79b339f 71 }
4e60d951 72 usb_submit_urb(urb, GFP_ATOMIC);
c79b339f
AP
73}
74
75int usb_urb_kill(struct usb_data_stream *stream)
76{
77 int i;
78 for (i = 0; i < stream->urbs_submitted; i++) {
15072bba 79 pr_debug("%s: kill URB=%d\n", __func__, i);
c79b339f
AP
80 /* stop the URB */
81 usb_kill_urb(stream->urb_list[i]);
82 }
83 stream->urbs_submitted = 0;
84 return 0;
85}
86
bce1c029
AP
87int usb_urb_submit(struct usb_data_stream *stream,
88 struct usb_data_stream_properties *props)
c79b339f 89{
4e60d951 90 int i, ret;
bce1c029
AP
91
92 if (props) {
93 ret = usb_urb_reconfig(stream, props);
94 if (ret < 0)
95 return ret;
96 }
97
c79b339f 98 for (i = 0; i < stream->urbs_initialized; i++) {
15072bba 99 pr_debug("%s: submit URB=%d\n", __func__, i);
4e60d951
AP
100 ret = usb_submit_urb(stream->urb_list[i], GFP_ATOMIC);
101 if (ret) {
23d8e63a
AP
102 pr_err("%s: could not submit URB no. %d - get them " \
103 "all back", KBUILD_MODNAME, i);
c79b339f
AP
104 usb_urb_kill(stream);
105 return ret;
106 }
107 stream->urbs_submitted++;
108 }
109 return 0;
110}
111
bce1c029 112int usb_urb_free_urbs(struct usb_data_stream *stream)
c79b339f 113{
bce1c029 114 int i;
c79b339f 115
bce1c029 116 usb_urb_kill(stream);
c79b339f 117
bce1c029
AP
118 for (i = 0; i < stream->urbs_initialized; i++) {
119 if (stream->urb_list[i] != NULL) {
bce1c029
AP
120 pr_debug("%s: free URB=%d\n", __func__, i);
121 /* free the URBs */
122 usb_free_urb(stream->urb_list[i]);
c79b339f 123 }
c79b339f 124 }
bce1c029 125 stream->urbs_initialized = 0;
c79b339f
AP
126
127 return 0;
128}
129
bce1c029 130static int usb_urb_alloc_bulk_urbs(struct usb_data_stream *stream)
c79b339f
AP
131{
132 int i, j;
133
c79b339f
AP
134 /* allocate the URBs */
135 for (i = 0; i < stream->props.count; i++) {
bce1c029 136 pr_debug("%s: alloc URB=%d\n", __func__, i);
c79b339f
AP
137 stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
138 if (!stream->urb_list[i]) {
15072bba 139 pr_debug("%s: failed\n", __func__);
c79b339f
AP
140 for (j = 0; j < i; j++)
141 usb_free_urb(stream->urb_list[j]);
142 return -ENOMEM;
143 }
bce1c029
AP
144 usb_fill_bulk_urb(stream->urb_list[i],
145 stream->udev,
4e60d951 146 usb_rcvbulkpipe(stream->udev,
bce1c029 147 stream->props.endpoint),
c79b339f
AP
148 stream->buf_list[i],
149 stream->props.u.bulk.buffersize,
150 usb_urb_complete, stream);
151
152 stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
153 stream->urb_list[i]->transfer_dma = stream->dma_addr[i];
154 stream->urbs_initialized++;
155 }
156 return 0;
157}
158
bce1c029 159static int usb_urb_alloc_isoc_urbs(struct usb_data_stream *stream)
c79b339f 160{
4e60d951 161 int i, j;
c79b339f 162
c79b339f
AP
163 /* allocate the URBs */
164 for (i = 0; i < stream->props.count; i++) {
165 struct urb *urb;
166 int frame_offset = 0;
bce1c029 167 pr_debug("%s: alloc URB=%d\n", __func__, i);
4e60d951
AP
168 stream->urb_list[i] = usb_alloc_urb(
169 stream->props.u.isoc.framesperurb, GFP_ATOMIC);
c79b339f 170 if (!stream->urb_list[i]) {
15072bba 171 pr_debug("%s: failed\n", __func__);
c79b339f
AP
172 for (j = 0; j < i; j++)
173 usb_free_urb(stream->urb_list[j]);
174 return -ENOMEM;
175 }
176
177 urb = stream->urb_list[i];
178
179 urb->dev = stream->udev;
180 urb->context = stream;
181 urb->complete = usb_urb_complete;
4e60d951
AP
182 urb->pipe = usb_rcvisocpipe(stream->udev,
183 stream->props.endpoint);
c79b339f
AP
184 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
185 urb->interval = stream->props.u.isoc.interval;
186 urb->number_of_packets = stream->props.u.isoc.framesperurb;
bce1c029
AP
187 urb->transfer_buffer_length = stream->props.u.isoc.framesize *
188 stream->props.u.isoc.framesperurb;
c79b339f
AP
189 urb->transfer_buffer = stream->buf_list[i];
190 urb->transfer_dma = stream->dma_addr[i];
191
192 for (j = 0; j < stream->props.u.isoc.framesperurb; j++) {
193 urb->iso_frame_desc[j].offset = frame_offset;
4e60d951
AP
194 urb->iso_frame_desc[j].length =
195 stream->props.u.isoc.framesize;
c79b339f
AP
196 frame_offset += stream->props.u.isoc.framesize;
197 }
198
199 stream->urbs_initialized++;
200 }
201 return 0;
202}
203
bce1c029
AP
204int usb_free_stream_buffers(struct usb_data_stream *stream)
205{
206 if (stream->state & USB_STATE_URB_BUF) {
207 while (stream->buf_num) {
208 stream->buf_num--;
15072bba
AP
209 pr_debug("%s: free buf=%d\n", __func__,
210 stream->buf_num);
bce1c029
AP
211 usb_free_coherent(stream->udev, stream->buf_size,
212 stream->buf_list[stream->buf_num],
213 stream->dma_addr[stream->buf_num]);
214 }
215 }
216
217 stream->state &= ~USB_STATE_URB_BUF;
218
219 return 0;
220}
221
222int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num,
223 unsigned long size)
224{
225 stream->buf_num = 0;
226 stream->buf_size = size;
227
15072bba
AP
228 pr_debug("%s: all in all I will use %lu bytes for streaming\n",
229 __func__, num * size);
bce1c029
AP
230
231 for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
15072bba 232 pr_debug("%s: alloc buf=%d\n", __func__, stream->buf_num);
bce1c029
AP
233 stream->buf_list[stream->buf_num] = usb_alloc_coherent(
234 stream->udev, size, GFP_ATOMIC,
235 &stream->dma_addr[stream->buf_num]);
236 if (stream->buf_list[stream->buf_num] == NULL) {
15072bba 237 pr_debug("%s: failed\n", __func__);
bce1c029
AP
238 usb_free_stream_buffers(stream);
239 return -ENOMEM;
240 }
15072bba
AP
241
242 pr_debug("%s: buf %d: %p (dma %llu)\n", __func__,
bce1c029
AP
243 stream->buf_num,
244 stream->buf_list[stream->buf_num],
245 (long long)stream->dma_addr[stream->buf_num]);
246 memset(stream->buf_list[stream->buf_num], 0, size);
247 stream->state |= USB_STATE_URB_BUF;
248 }
bce1c029
AP
249
250 return 0;
251}
252
253int usb_urb_reconfig(struct usb_data_stream *stream,
254 struct usb_data_stream_properties *props)
255{
256 int buf_size;
257
258 if (props == NULL)
259 return 0;
260
261 /* check allocated buffers are large enough for the request */
15072bba 262 if (props->type == USB_BULK) {
bce1c029 263 buf_size = stream->props.u.bulk.buffersize;
15072bba 264 } else if (props->type == USB_ISOC) {
bce1c029 265 buf_size = props->u.isoc.framesize * props->u.isoc.framesperurb;
15072bba 266 } else {
23d8e63a
AP
267 pr_err("%s: invalid endpoint type=%d", KBUILD_MODNAME,
268 props->type);
bce1c029 269 return -EINVAL;
15072bba 270 }
bce1c029
AP
271
272 if (stream->buf_num < props->count || stream->buf_size < buf_size) {
23d8e63a
AP
273 pr_err("%s: cannot reconfigure as allocated buffers are too " \
274 "small", KBUILD_MODNAME);
bce1c029
AP
275 return -EINVAL;
276 }
277
278 /* check if all fields are same */
279 if (stream->props.type == props->type &&
280 stream->props.count == props->count &&
281 stream->props.endpoint == props->endpoint) {
282 if (props->type == USB_BULK &&
283 props->u.bulk.buffersize ==
284 stream->props.u.bulk.buffersize)
285 return 0;
286 else if (props->type == USB_ISOC &&
287 props->u.isoc.framesperurb ==
288 stream->props.u.isoc.framesperurb &&
289 props->u.isoc.framesize ==
290 stream->props.u.isoc.framesize &&
291 props->u.isoc.interval ==
292 stream->props.u.isoc.interval)
293 return 0;
294 }
295
296 pr_debug("%s: re-alloc URBs\n", __func__);
297
298 usb_urb_free_urbs(stream);
299 memcpy(&stream->props, props, sizeof(*props));
300 if (props->type == USB_BULK)
301 return usb_urb_alloc_bulk_urbs(stream);
302 else if (props->type == USB_ISOC)
303 return usb_urb_alloc_isoc_urbs(stream);
304
305 return 0;
306}
307
4e60d951
AP
308int usb_urb_init(struct usb_data_stream *stream,
309 struct usb_data_stream_properties *props)
c79b339f 310{
bce1c029
AP
311 int ret;
312
c79b339f
AP
313 if (stream == NULL || props == NULL)
314 return -EINVAL;
315
316 memcpy(&stream->props, props, sizeof(*props));
317
4e60d951
AP
318 usb_clear_halt(stream->udev, usb_rcvbulkpipe(stream->udev,
319 stream->props.endpoint));
c79b339f
AP
320
321 if (stream->complete == NULL) {
23d8e63a
AP
322 pr_err("%s: there is no data callback - this doesn't make " \
323 "sense", KBUILD_MODNAME);
c79b339f
AP
324 return -EINVAL;
325 }
326
327 switch (stream->props.type) {
4e60d951 328 case USB_BULK:
bce1c029
AP
329 ret = usb_alloc_stream_buffers(stream, stream->props.count,
330 stream->props.u.bulk.buffersize);
331 if (ret < 0)
332 return ret;
333
334 return usb_urb_alloc_bulk_urbs(stream);
4e60d951 335 case USB_ISOC:
bce1c029
AP
336 ret = usb_alloc_stream_buffers(stream, stream->props.count,
337 stream->props.u.isoc.framesize *
338 stream->props.u.isoc.framesperurb);
339 if (ret < 0)
340 return ret;
341
342 return usb_urb_alloc_isoc_urbs(stream);
4e60d951 343 default:
23d8e63a
AP
344 pr_err("%s: unknown URB-type for data transfer",
345 KBUILD_MODNAME);
4e60d951 346 return -EINVAL;
c79b339f
AP
347 }
348}
349
350int usb_urb_exit(struct usb_data_stream *stream)
351{
bce1c029 352 usb_urb_free_urbs(stream);
c79b339f 353 usb_free_stream_buffers(stream);
bce1c029 354
c79b339f
AP
355 return 0;
356}
This page took 0.041938 seconds and 5 git commands to generate.