1 // SPDX-License-Identifier: GPL-2.0
2 /* usb-urb.c is part of the DVB USB library.
4 * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de)
5 * see dvb-usb-init.c for copyright information.
7 * This file keeps functions for initializing and handling the
8 * BULK and ISOC USB data transfers in a generic way.
9 * Can be used for DVB-only and also, that's the plan, for
10 * Hybrid USB devices (analog and DVB).
12 #include "dvb_usb_common.h"
14 /* URB stuff for streaming */
16 int usb_urb_reconfig(struct usb_data_stream
*stream
,
17 struct usb_data_stream_properties
*props
);
19 static void usb_urb_complete(struct urb
*urb
)
21 struct usb_data_stream
*stream
= urb
->context
;
22 int ptype
= usb_pipetype(urb
->pipe
);
26 dev_dbg_ratelimited(&stream
->udev
->dev
,
27 "%s: %s urb completed status=%d length=%d/%d pack_num=%d errors=%d\n",
28 __func__
, ptype
== PIPE_ISOCHRONOUS
? "isoc" : "bulk",
29 urb
->status
, urb
->actual_length
,
30 urb
->transfer_buffer_length
,
31 urb
->number_of_packets
, urb
->error_count
);
33 switch (urb
->status
) {
35 case -ETIMEDOUT
: /* NAK */
37 case -ECONNRESET
: /* kill */
42 dev_dbg_ratelimited(&stream
->udev
->dev
,
43 "%s: urb completion failed=%d\n",
44 __func__
, urb
->status
);
48 b
= (u8
*) urb
->transfer_buffer
;
50 case PIPE_ISOCHRONOUS
:
51 for (i
= 0; i
< urb
->number_of_packets
; i
++) {
52 if (urb
->iso_frame_desc
[i
].status
!= 0)
53 dev_dbg(&stream
->udev
->dev
,
54 "%s: iso frame descriptor has an error=%d\n",
56 urb
->iso_frame_desc
[i
].status
);
57 else if (urb
->iso_frame_desc
[i
].actual_length
> 0)
58 stream
->complete(stream
,
59 b
+ urb
->iso_frame_desc
[i
].offset
,
60 urb
->iso_frame_desc
[i
].actual_length
);
62 urb
->iso_frame_desc
[i
].status
= 0;
63 urb
->iso_frame_desc
[i
].actual_length
= 0;
67 if (urb
->actual_length
> 0)
68 stream
->complete(stream
, b
, urb
->actual_length
);
71 dev_err(&stream
->udev
->dev
,
72 "%s: unknown endpoint type in completion handler\n",
76 usb_submit_urb(urb
, GFP_ATOMIC
);
79 int usb_urb_killv2(struct usb_data_stream
*stream
)
82 for (i
= 0; i
< stream
->urbs_submitted
; i
++) {
83 dev_dbg(&stream
->udev
->dev
, "%s: kill urb=%d\n", __func__
, i
);
85 usb_kill_urb(stream
->urb_list
[i
]);
87 stream
->urbs_submitted
= 0;
91 int usb_urb_submitv2(struct usb_data_stream
*stream
,
92 struct usb_data_stream_properties
*props
)
97 ret
= usb_urb_reconfig(stream
, props
);
102 for (i
= 0; i
< stream
->urbs_initialized
; i
++) {
103 dev_dbg(&stream
->udev
->dev
, "%s: submit urb=%d\n", __func__
, i
);
104 ret
= usb_submit_urb(stream
->urb_list
[i
], GFP_ATOMIC
);
106 dev_err(&stream
->udev
->dev
,
107 "%s: could not submit urb no. %d - get them all back\n",
109 usb_urb_killv2(stream
);
112 stream
->urbs_submitted
++;
117 static int usb_urb_free_urbs(struct usb_data_stream
*stream
)
121 usb_urb_killv2(stream
);
123 for (i
= stream
->urbs_initialized
- 1; i
>= 0; i
--) {
124 if (stream
->urb_list
[i
]) {
125 dev_dbg(&stream
->udev
->dev
, "%s: free urb=%d\n",
128 usb_free_urb(stream
->urb_list
[i
]);
131 stream
->urbs_initialized
= 0;
136 static int usb_urb_alloc_bulk_urbs(struct usb_data_stream
*stream
)
140 /* allocate the URBs */
141 for (i
= 0; i
< stream
->props
.count
; i
++) {
142 dev_dbg(&stream
->udev
->dev
, "%s: alloc urb=%d\n", __func__
, i
);
143 stream
->urb_list
[i
] = usb_alloc_urb(0, GFP_ATOMIC
);
144 if (!stream
->urb_list
[i
]) {
145 dev_dbg(&stream
->udev
->dev
, "%s: failed\n", __func__
);
146 for (j
= 0; j
< i
; j
++)
147 usb_free_urb(stream
->urb_list
[j
]);
150 usb_fill_bulk_urb(stream
->urb_list
[i
],
152 usb_rcvbulkpipe(stream
->udev
,
153 stream
->props
.endpoint
),
155 stream
->props
.u
.bulk
.buffersize
,
156 usb_urb_complete
, stream
);
158 stream
->urbs_initialized
++;
163 static int usb_urb_alloc_isoc_urbs(struct usb_data_stream
*stream
)
167 /* allocate the URBs */
168 for (i
= 0; i
< stream
->props
.count
; i
++) {
170 int frame_offset
= 0;
171 dev_dbg(&stream
->udev
->dev
, "%s: alloc urb=%d\n", __func__
, i
);
172 stream
->urb_list
[i
] = usb_alloc_urb(
173 stream
->props
.u
.isoc
.framesperurb
, GFP_ATOMIC
);
174 if (!stream
->urb_list
[i
]) {
175 dev_dbg(&stream
->udev
->dev
, "%s: failed\n", __func__
);
176 for (j
= 0; j
< i
; j
++)
177 usb_free_urb(stream
->urb_list
[j
]);
181 urb
= stream
->urb_list
[i
];
183 urb
->dev
= stream
->udev
;
184 urb
->context
= stream
;
185 urb
->complete
= usb_urb_complete
;
186 urb
->pipe
= usb_rcvisocpipe(stream
->udev
,
187 stream
->props
.endpoint
);
188 urb
->transfer_flags
= URB_ISO_ASAP
;
189 urb
->interval
= stream
->props
.u
.isoc
.interval
;
190 urb
->number_of_packets
= stream
->props
.u
.isoc
.framesperurb
;
191 urb
->transfer_buffer_length
= stream
->props
.u
.isoc
.framesize
*
192 stream
->props
.u
.isoc
.framesperurb
;
193 urb
->transfer_buffer
= stream
->buf_list
[i
];
195 for (j
= 0; j
< stream
->props
.u
.isoc
.framesperurb
; j
++) {
196 urb
->iso_frame_desc
[j
].offset
= frame_offset
;
197 urb
->iso_frame_desc
[j
].length
=
198 stream
->props
.u
.isoc
.framesize
;
199 frame_offset
+= stream
->props
.u
.isoc
.framesize
;
202 stream
->urbs_initialized
++;
207 static int usb_free_stream_buffers(struct usb_data_stream
*stream
)
209 if (stream
->state
& USB_STATE_URB_BUF
) {
210 while (stream
->buf_num
) {
212 kfree(stream
->buf_list
[stream
->buf_num
]);
216 stream
->state
&= ~USB_STATE_URB_BUF
;
221 static int usb_alloc_stream_buffers(struct usb_data_stream
*stream
, int num
,
225 stream
->buf_size
= size
;
227 dev_dbg(&stream
->udev
->dev
,
228 "%s: all in all I will use %lu bytes for streaming\n",
229 __func__
, num
* size
);
231 for (stream
->buf_num
= 0; stream
->buf_num
< num
; stream
->buf_num
++) {
232 stream
->buf_list
[stream
->buf_num
] = kzalloc(size
, GFP_ATOMIC
);
233 if (!stream
->buf_list
[stream
->buf_num
]) {
234 dev_dbg(&stream
->udev
->dev
, "%s: alloc buf=%d failed\n",
235 __func__
, stream
->buf_num
);
236 usb_free_stream_buffers(stream
);
240 dev_dbg(&stream
->udev
->dev
, "%s: alloc buf=%d %p (dma %llu)\n",
241 __func__
, stream
->buf_num
,
242 stream
->buf_list
[stream
->buf_num
],
243 (long long)stream
->dma_addr
[stream
->buf_num
]);
244 stream
->state
|= USB_STATE_URB_BUF
;
250 int usb_urb_reconfig(struct usb_data_stream
*stream
,
251 struct usb_data_stream_properties
*props
)
258 /* check allocated buffers are large enough for the request */
259 if (props
->type
== USB_BULK
) {
260 buf_size
= stream
->props
.u
.bulk
.buffersize
;
261 } else if (props
->type
== USB_ISOC
) {
262 buf_size
= props
->u
.isoc
.framesize
* props
->u
.isoc
.framesperurb
;
264 dev_err(&stream
->udev
->dev
, "%s: invalid endpoint type=%d\n",
265 KBUILD_MODNAME
, props
->type
);
269 if (stream
->buf_num
< props
->count
|| stream
->buf_size
< buf_size
) {
270 dev_err(&stream
->udev
->dev
,
271 "%s: cannot reconfigure as allocated buffers are too small\n",
276 /* check if all fields are same */
277 if (stream
->props
.type
== props
->type
&&
278 stream
->props
.count
== props
->count
&&
279 stream
->props
.endpoint
== props
->endpoint
) {
280 if (props
->type
== USB_BULK
&&
281 props
->u
.bulk
.buffersize
==
282 stream
->props
.u
.bulk
.buffersize
)
284 else if (props
->type
== USB_ISOC
&&
285 props
->u
.isoc
.framesperurb
==
286 stream
->props
.u
.isoc
.framesperurb
&&
287 props
->u
.isoc
.framesize
==
288 stream
->props
.u
.isoc
.framesize
&&
289 props
->u
.isoc
.interval
==
290 stream
->props
.u
.isoc
.interval
)
294 dev_dbg(&stream
->udev
->dev
, "%s: re-alloc urbs\n", __func__
);
296 usb_urb_free_urbs(stream
);
297 memcpy(&stream
->props
, props
, sizeof(*props
));
298 if (props
->type
== USB_BULK
)
299 return usb_urb_alloc_bulk_urbs(stream
);
300 else if (props
->type
== USB_ISOC
)
301 return usb_urb_alloc_isoc_urbs(stream
);
306 int usb_urb_initv2(struct usb_data_stream
*stream
,
307 const struct usb_data_stream_properties
*props
)
311 if (!stream
|| !props
)
314 memcpy(&stream
->props
, props
, sizeof(*props
));
316 if (!stream
->complete
) {
317 dev_err(&stream
->udev
->dev
,
318 "%s: there is no data callback - this doesn't make sense\n",
323 switch (stream
->props
.type
) {
325 ret
= usb_alloc_stream_buffers(stream
, stream
->props
.count
,
326 stream
->props
.u
.bulk
.buffersize
);
330 return usb_urb_alloc_bulk_urbs(stream
);
332 ret
= usb_alloc_stream_buffers(stream
, stream
->props
.count
,
333 stream
->props
.u
.isoc
.framesize
*
334 stream
->props
.u
.isoc
.framesperurb
);
338 return usb_urb_alloc_isoc_urbs(stream
);
340 dev_err(&stream
->udev
->dev
,
341 "%s: unknown urb-type for data transfer\n",
347 int usb_urb_exitv2(struct usb_data_stream
*stream
)
349 usb_urb_free_urbs(stream
);
350 usb_free_stream_buffers(stream
);