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 completition 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 completition 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
->urb_list
[i
]->transfer_flags
= URB_NO_TRANSFER_DMA_MAP
;
159 stream
->urb_list
[i
]->transfer_dma
= stream
->dma_addr
[i
];
160 stream
->urbs_initialized
++;
165 static int usb_urb_alloc_isoc_urbs(struct usb_data_stream
*stream
)
169 /* allocate the URBs */
170 for (i
= 0; i
< stream
->props
.count
; i
++) {
172 int frame_offset
= 0;
173 dev_dbg(&stream
->udev
->dev
, "%s: alloc urb=%d\n", __func__
, i
);
174 stream
->urb_list
[i
] = usb_alloc_urb(
175 stream
->props
.u
.isoc
.framesperurb
, GFP_ATOMIC
);
176 if (!stream
->urb_list
[i
]) {
177 dev_dbg(&stream
->udev
->dev
, "%s: failed\n", __func__
);
178 for (j
= 0; j
< i
; j
++)
179 usb_free_urb(stream
->urb_list
[j
]);
183 urb
= stream
->urb_list
[i
];
185 urb
->dev
= stream
->udev
;
186 urb
->context
= stream
;
187 urb
->complete
= usb_urb_complete
;
188 urb
->pipe
= usb_rcvisocpipe(stream
->udev
,
189 stream
->props
.endpoint
);
190 urb
->transfer_flags
= URB_ISO_ASAP
| URB_NO_TRANSFER_DMA_MAP
;
191 urb
->interval
= stream
->props
.u
.isoc
.interval
;
192 urb
->number_of_packets
= stream
->props
.u
.isoc
.framesperurb
;
193 urb
->transfer_buffer_length
= stream
->props
.u
.isoc
.framesize
*
194 stream
->props
.u
.isoc
.framesperurb
;
195 urb
->transfer_buffer
= stream
->buf_list
[i
];
196 urb
->transfer_dma
= stream
->dma_addr
[i
];
198 for (j
= 0; j
< stream
->props
.u
.isoc
.framesperurb
; j
++) {
199 urb
->iso_frame_desc
[j
].offset
= frame_offset
;
200 urb
->iso_frame_desc
[j
].length
=
201 stream
->props
.u
.isoc
.framesize
;
202 frame_offset
+= stream
->props
.u
.isoc
.framesize
;
205 stream
->urbs_initialized
++;
210 static int usb_free_stream_buffers(struct usb_data_stream
*stream
)
212 if (stream
->state
& USB_STATE_URB_BUF
) {
213 while (stream
->buf_num
) {
215 dev_dbg(&stream
->udev
->dev
, "%s: free buf=%d\n",
216 __func__
, stream
->buf_num
);
217 usb_free_coherent(stream
->udev
, stream
->buf_size
,
218 stream
->buf_list
[stream
->buf_num
],
219 stream
->dma_addr
[stream
->buf_num
]);
223 stream
->state
&= ~USB_STATE_URB_BUF
;
228 static int usb_alloc_stream_buffers(struct usb_data_stream
*stream
, int num
,
232 stream
->buf_size
= size
;
234 dev_dbg(&stream
->udev
->dev
,
235 "%s: all in all I will use %lu bytes for streaming\n",
236 __func__
, num
* size
);
238 for (stream
->buf_num
= 0; stream
->buf_num
< num
; stream
->buf_num
++) {
239 stream
->buf_list
[stream
->buf_num
] = usb_alloc_coherent(
240 stream
->udev
, size
, GFP_ATOMIC
,
241 &stream
->dma_addr
[stream
->buf_num
]);
242 if (!stream
->buf_list
[stream
->buf_num
]) {
243 dev_dbg(&stream
->udev
->dev
, "%s: alloc buf=%d failed\n",
244 __func__
, stream
->buf_num
);
245 usb_free_stream_buffers(stream
);
249 dev_dbg(&stream
->udev
->dev
, "%s: alloc buf=%d %p (dma %llu)\n",
250 __func__
, stream
->buf_num
,
251 stream
->buf_list
[stream
->buf_num
],
252 (long long)stream
->dma_addr
[stream
->buf_num
]);
253 memset(stream
->buf_list
[stream
->buf_num
], 0, size
);
254 stream
->state
|= USB_STATE_URB_BUF
;
260 int usb_urb_reconfig(struct usb_data_stream
*stream
,
261 struct usb_data_stream_properties
*props
)
268 /* check allocated buffers are large enough for the request */
269 if (props
->type
== USB_BULK
) {
270 buf_size
= stream
->props
.u
.bulk
.buffersize
;
271 } else if (props
->type
== USB_ISOC
) {
272 buf_size
= props
->u
.isoc
.framesize
* props
->u
.isoc
.framesperurb
;
274 dev_err(&stream
->udev
->dev
, "%s: invalid endpoint type=%d\n",
275 KBUILD_MODNAME
, props
->type
);
279 if (stream
->buf_num
< props
->count
|| stream
->buf_size
< buf_size
) {
280 dev_err(&stream
->udev
->dev
,
281 "%s: cannot reconfigure as allocated buffers are too small\n",
286 /* check if all fields are same */
287 if (stream
->props
.type
== props
->type
&&
288 stream
->props
.count
== props
->count
&&
289 stream
->props
.endpoint
== props
->endpoint
) {
290 if (props
->type
== USB_BULK
&&
291 props
->u
.bulk
.buffersize
==
292 stream
->props
.u
.bulk
.buffersize
)
294 else if (props
->type
== USB_ISOC
&&
295 props
->u
.isoc
.framesperurb
==
296 stream
->props
.u
.isoc
.framesperurb
&&
297 props
->u
.isoc
.framesize
==
298 stream
->props
.u
.isoc
.framesize
&&
299 props
->u
.isoc
.interval
==
300 stream
->props
.u
.isoc
.interval
)
304 dev_dbg(&stream
->udev
->dev
, "%s: re-alloc urbs\n", __func__
);
306 usb_urb_free_urbs(stream
);
307 memcpy(&stream
->props
, props
, sizeof(*props
));
308 if (props
->type
== USB_BULK
)
309 return usb_urb_alloc_bulk_urbs(stream
);
310 else if (props
->type
== USB_ISOC
)
311 return usb_urb_alloc_isoc_urbs(stream
);
316 int usb_urb_initv2(struct usb_data_stream
*stream
,
317 const struct usb_data_stream_properties
*props
)
321 if (!stream
|| !props
)
324 memcpy(&stream
->props
, props
, sizeof(*props
));
326 if (!stream
->complete
) {
327 dev_err(&stream
->udev
->dev
,
328 "%s: there is no data callback - this doesn't make sense\n",
333 switch (stream
->props
.type
) {
335 ret
= usb_alloc_stream_buffers(stream
, stream
->props
.count
,
336 stream
->props
.u
.bulk
.buffersize
);
340 return usb_urb_alloc_bulk_urbs(stream
);
342 ret
= usb_alloc_stream_buffers(stream
, stream
->props
.count
,
343 stream
->props
.u
.isoc
.framesize
*
344 stream
->props
.u
.isoc
.framesperurb
);
348 return usb_urb_alloc_isoc_urbs(stream
);
350 dev_err(&stream
->udev
->dev
,
351 "%s: unknown urb-type for data transfer\n",
357 int usb_urb_exitv2(struct usb_data_stream
*stream
)
359 usb_urb_free_urbs(stream
);
360 usb_free_stream_buffers(stream
);