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 */
15 static void usb_urb_complete(struct urb
*urb
)
17 struct usb_data_stream
*stream
= urb
->context
;
18 int ptype
= usb_pipetype(urb
->pipe
);
22 deb_uxfer("'%s' urb completed. status: %d, length: %d/%d, pack_num: %d, errors: %d\n",
23 ptype
== PIPE_ISOCHRONOUS
? "isoc" : "bulk",
24 urb
->status
,urb
->actual_length
,urb
->transfer_buffer_length
,
25 urb
->number_of_packets
,urb
->error_count
);
27 switch (urb
->status
) {
29 case -ETIMEDOUT
: /* NAK */
31 case -ECONNRESET
: /* kill */
36 deb_ts("urb completion error %d.\n", urb
->status
);
40 b
= (u8
*) urb
->transfer_buffer
;
42 case PIPE_ISOCHRONOUS
:
43 for (i
= 0; i
< urb
->number_of_packets
; i
++) {
45 if (urb
->iso_frame_desc
[i
].status
!= 0)
46 deb_ts("iso frame descriptor has an error: %d\n",urb
->iso_frame_desc
[i
].status
);
47 else if (urb
->iso_frame_desc
[i
].actual_length
> 0)
48 stream
->complete(stream
, b
+ urb
->iso_frame_desc
[i
].offset
, urb
->iso_frame_desc
[i
].actual_length
);
50 urb
->iso_frame_desc
[i
].status
= 0;
51 urb
->iso_frame_desc
[i
].actual_length
= 0;
53 debug_dump(b
,20,deb_uxfer
);
56 if (urb
->actual_length
> 0)
57 stream
->complete(stream
, b
, urb
->actual_length
);
60 err("unknown endpoint type in completion handler.");
63 usb_submit_urb(urb
,GFP_ATOMIC
);
66 int usb_urb_kill(struct usb_data_stream
*stream
)
69 for (i
= 0; i
< stream
->urbs_submitted
; i
++) {
70 deb_ts("killing URB no. %d.\n",i
);
73 usb_kill_urb(stream
->urb_list
[i
]);
75 stream
->urbs_submitted
= 0;
79 int usb_urb_submit(struct usb_data_stream
*stream
)
82 for (i
= 0; i
< stream
->urbs_initialized
; i
++) {
83 deb_ts("submitting URB no. %d\n",i
);
84 if ((ret
= usb_submit_urb(stream
->urb_list
[i
],GFP_ATOMIC
))) {
85 err("could not submit URB no. %d - get them all back",i
);
89 stream
->urbs_submitted
++;
94 static int usb_free_stream_buffers(struct usb_data_stream
*stream
)
96 if (stream
->state
& USB_STATE_URB_BUF
) {
97 while (stream
->buf_num
) {
99 deb_mem("freeing buffer %d\n",stream
->buf_num
);
100 usb_free_coherent(stream
->udev
, stream
->buf_size
,
101 stream
->buf_list
[stream
->buf_num
],
102 stream
->dma_addr
[stream
->buf_num
]);
106 stream
->state
&= ~USB_STATE_URB_BUF
;
111 static int usb_allocate_stream_buffers(struct usb_data_stream
*stream
, int num
, unsigned long size
)
114 stream
->buf_size
= size
;
116 deb_mem("all in all I will use %lu bytes for streaming\n",num
*size
);
118 for (stream
->buf_num
= 0; stream
->buf_num
< num
; stream
->buf_num
++) {
119 deb_mem("allocating buffer %d\n",stream
->buf_num
);
120 if (( stream
->buf_list
[stream
->buf_num
] =
121 usb_alloc_coherent(stream
->udev
, size
, GFP_KERNEL
,
122 &stream
->dma_addr
[stream
->buf_num
]) ) == NULL
) {
123 deb_mem("not enough memory for urb-buffer allocation.\n");
124 usb_free_stream_buffers(stream
);
127 deb_mem("buffer %d: %p (dma: %Lu)\n",
129 stream
->buf_list
[stream
->buf_num
], (long long)stream
->dma_addr
[stream
->buf_num
]);
130 memset(stream
->buf_list
[stream
->buf_num
],0,size
);
131 stream
->state
|= USB_STATE_URB_BUF
;
133 deb_mem("allocation successful\n");
138 static int usb_bulk_urb_init(struct usb_data_stream
*stream
)
142 if ((i
= usb_allocate_stream_buffers(stream
,stream
->props
.count
,
143 stream
->props
.u
.bulk
.buffersize
)) < 0)
146 /* allocate the URBs */
147 for (i
= 0; i
< stream
->props
.count
; i
++) {
148 stream
->urb_list
[i
] = usb_alloc_urb(0, GFP_KERNEL
);
149 if (!stream
->urb_list
[i
]) {
150 deb_mem("not enough memory for urb_alloc_urb!.\n");
151 for (j
= 0; j
< i
; j
++)
152 usb_free_urb(stream
->urb_list
[j
]);
155 usb_fill_bulk_urb( stream
->urb_list
[i
], stream
->udev
,
156 usb_rcvbulkpipe(stream
->udev
,stream
->props
.endpoint
),
158 stream
->props
.u
.bulk
.buffersize
,
159 usb_urb_complete
, stream
);
161 stream
->urb_list
[i
]->transfer_flags
= URB_NO_TRANSFER_DMA_MAP
;
162 stream
->urb_list
[i
]->transfer_dma
= stream
->dma_addr
[i
];
163 stream
->urbs_initialized
++;
168 static int usb_isoc_urb_init(struct usb_data_stream
*stream
)
172 if ((i
= usb_allocate_stream_buffers(stream
,stream
->props
.count
,
173 stream
->props
.u
.isoc
.framesize
*stream
->props
.u
.isoc
.framesperurb
)) < 0)
176 /* allocate the URBs */
177 for (i
= 0; i
< stream
->props
.count
; i
++) {
179 int frame_offset
= 0;
181 stream
->urb_list
[i
] = usb_alloc_urb(stream
->props
.u
.isoc
.framesperurb
, GFP_KERNEL
);
182 if (!stream
->urb_list
[i
]) {
183 deb_mem("not enough memory for urb_alloc_urb!\n");
184 for (j
= 0; j
< i
; j
++)
185 usb_free_urb(stream
->urb_list
[j
]);
189 urb
= stream
->urb_list
[i
];
191 urb
->dev
= stream
->udev
;
192 urb
->context
= stream
;
193 urb
->complete
= usb_urb_complete
;
194 urb
->pipe
= usb_rcvisocpipe(stream
->udev
,stream
->props
.endpoint
);
195 urb
->transfer_flags
= URB_ISO_ASAP
| URB_NO_TRANSFER_DMA_MAP
;
196 urb
->interval
= stream
->props
.u
.isoc
.interval
;
197 urb
->number_of_packets
= stream
->props
.u
.isoc
.framesperurb
;
198 urb
->transfer_buffer_length
= stream
->buf_size
;
199 urb
->transfer_buffer
= stream
->buf_list
[i
];
200 urb
->transfer_dma
= stream
->dma_addr
[i
];
202 for (j
= 0; j
< stream
->props
.u
.isoc
.framesperurb
; j
++) {
203 urb
->iso_frame_desc
[j
].offset
= frame_offset
;
204 urb
->iso_frame_desc
[j
].length
= stream
->props
.u
.isoc
.framesize
;
205 frame_offset
+= stream
->props
.u
.isoc
.framesize
;
208 stream
->urbs_initialized
++;
213 int usb_urb_init(struct usb_data_stream
*stream
, struct usb_data_stream_properties
*props
)
215 if (stream
== NULL
|| props
== NULL
)
218 memcpy(&stream
->props
, props
, sizeof(*props
));
220 usb_clear_halt(stream
->udev
,usb_rcvbulkpipe(stream
->udev
,stream
->props
.endpoint
));
222 if (stream
->complete
== NULL
) {
223 err("there is no data callback - this doesn't make sense.");
227 switch (stream
->props
.type
) {
229 return usb_bulk_urb_init(stream
);
231 return usb_isoc_urb_init(stream
);
233 err("unknown URB-type for data transfer.");
238 int usb_urb_exit(struct usb_data_stream
*stream
)
242 usb_urb_kill(stream
);
244 for (i
= 0; i
< stream
->urbs_initialized
; i
++) {
245 if (stream
->urb_list
[i
] != NULL
) {
246 deb_mem("freeing URB no. %d.\n",i
);
248 usb_free_urb(stream
->urb_list
[i
]);
251 stream
->urbs_initialized
= 0;
253 usb_free_stream_buffers(stream
);