1 /* usb-urb.c is part of the DVB USB library.
3 * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
4 * see dvb-usb-init.c for copyright information.
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).
11 #include "dvb-usb-common.h"
13 /* URB stuff for streaming */
14 static void usb_urb_complete(struct urb
*urb
)
16 struct usb_data_stream
*stream
= urb
->context
;
17 int ptype
= usb_pipetype(urb
->pipe
);
21 deb_uxfer("'%s' urb completed. status: %d, length: %d/%d, pack_num: %d, errors: %d\n",
22 ptype
== PIPE_ISOCHRONOUS
? "isoc" : "bulk",
23 urb
->status
,urb
->actual_length
,urb
->transfer_buffer_length
,
24 urb
->number_of_packets
,urb
->error_count
);
26 switch (urb
->status
) {
28 case -ETIMEDOUT
: /* NAK */
30 case -ECONNRESET
: /* kill */
35 deb_ts("urb completition error %d.\n", urb
->status
);
39 b
= (u8
*) urb
->transfer_buffer
;
41 case PIPE_ISOCHRONOUS
:
42 for (i
= 0; i
< urb
->number_of_packets
; i
++) {
44 if (urb
->iso_frame_desc
[i
].status
!= 0)
45 deb_ts("iso frame descriptor has an error: %d\n",urb
->iso_frame_desc
[i
].status
);
46 else if (urb
->iso_frame_desc
[i
].actual_length
> 0)
47 stream
->complete(stream
, b
+ urb
->iso_frame_desc
[i
].offset
, urb
->iso_frame_desc
[i
].actual_length
);
49 urb
->iso_frame_desc
[i
].status
= 0;
50 urb
->iso_frame_desc
[i
].actual_length
= 0;
52 debug_dump(b
,20,deb_uxfer
);
55 if (urb
->actual_length
> 0)
56 stream
->complete(stream
, b
, urb
->actual_length
);
59 err("unknown endpoint type in completition handler.");
62 usb_submit_urb(urb
,GFP_ATOMIC
);
65 int usb_urb_kill(struct usb_data_stream
*stream
)
68 for (i
= 0; i
< stream
->urbs_submitted
; i
++) {
69 deb_ts("killing URB no. %d.\n",i
);
72 usb_kill_urb(stream
->urb_list
[i
]);
74 stream
->urbs_submitted
= 0;
78 int usb_urb_submit(struct usb_data_stream
*stream
)
81 for (i
= 0; i
< stream
->urbs_initialized
; i
++) {
82 deb_ts("submitting URB no. %d\n",i
);
83 if ((ret
= usb_submit_urb(stream
->urb_list
[i
],GFP_ATOMIC
))) {
84 err("could not submit URB no. %d - get them all back",i
);
88 stream
->urbs_submitted
++;
93 static int usb_free_stream_buffers(struct usb_data_stream
*stream
)
95 if (stream
->state
& USB_STATE_URB_BUF
) {
96 while (stream
->buf_num
) {
98 deb_mem("freeing buffer %d\n",stream
->buf_num
);
99 usb_free_coherent(stream
->udev
, stream
->buf_size
,
100 stream
->buf_list
[stream
->buf_num
],
101 stream
->dma_addr
[stream
->buf_num
]);
105 stream
->state
&= ~USB_STATE_URB_BUF
;
110 static int usb_allocate_stream_buffers(struct usb_data_stream
*stream
, int num
, unsigned long size
)
113 stream
->buf_size
= size
;
115 deb_mem("all in all I will use %lu bytes for streaming\n",num
*size
);
117 for (stream
->buf_num
= 0; stream
->buf_num
< num
; stream
->buf_num
++) {
118 deb_mem("allocating buffer %d\n",stream
->buf_num
);
119 if (( stream
->buf_list
[stream
->buf_num
] =
120 usb_alloc_coherent(stream
->udev
, size
, GFP_ATOMIC
,
121 &stream
->dma_addr
[stream
->buf_num
]) ) == NULL
) {
122 deb_mem("not enough memory for urb-buffer allocation.\n");
123 usb_free_stream_buffers(stream
);
126 deb_mem("buffer %d: %p (dma: %Lu)\n",
128 stream
->buf_list
[stream
->buf_num
], (long long)stream
->dma_addr
[stream
->buf_num
]);
129 memset(stream
->buf_list
[stream
->buf_num
],0,size
);
130 stream
->state
|= USB_STATE_URB_BUF
;
132 deb_mem("allocation successful\n");
137 static int usb_bulk_urb_init(struct usb_data_stream
*stream
)
141 if ((i
= usb_allocate_stream_buffers(stream
,stream
->props
.count
,
142 stream
->props
.u
.bulk
.buffersize
)) < 0)
145 /* allocate the URBs */
146 for (i
= 0; i
< stream
->props
.count
; i
++) {
147 stream
->urb_list
[i
] = usb_alloc_urb(0, GFP_ATOMIC
);
148 if (!stream
->urb_list
[i
]) {
149 deb_mem("not enough memory for urb_alloc_urb!.\n");
150 for (j
= 0; j
< i
; j
++)
151 usb_free_urb(stream
->urb_list
[j
]);
154 usb_fill_bulk_urb( stream
->urb_list
[i
], stream
->udev
,
155 usb_rcvbulkpipe(stream
->udev
,stream
->props
.endpoint
),
157 stream
->props
.u
.bulk
.buffersize
,
158 usb_urb_complete
, stream
);
160 stream
->urb_list
[i
]->transfer_flags
= URB_NO_TRANSFER_DMA_MAP
;
161 stream
->urb_list
[i
]->transfer_dma
= stream
->dma_addr
[i
];
162 stream
->urbs_initialized
++;
167 static int usb_isoc_urb_init(struct usb_data_stream
*stream
)
171 if ((i
= usb_allocate_stream_buffers(stream
,stream
->props
.count
,
172 stream
->props
.u
.isoc
.framesize
*stream
->props
.u
.isoc
.framesperurb
)) < 0)
175 /* allocate the URBs */
176 for (i
= 0; i
< stream
->props
.count
; i
++) {
178 int frame_offset
= 0;
180 stream
->urb_list
[i
] = usb_alloc_urb(stream
->props
.u
.isoc
.framesperurb
, GFP_ATOMIC
);
181 if (!stream
->urb_list
[i
]) {
182 deb_mem("not enough memory for urb_alloc_urb!\n");
183 for (j
= 0; j
< i
; j
++)
184 usb_free_urb(stream
->urb_list
[j
]);
188 urb
= stream
->urb_list
[i
];
190 urb
->dev
= stream
->udev
;
191 urb
->context
= stream
;
192 urb
->complete
= usb_urb_complete
;
193 urb
->pipe
= usb_rcvisocpipe(stream
->udev
,stream
->props
.endpoint
);
194 urb
->transfer_flags
= URB_ISO_ASAP
| URB_NO_TRANSFER_DMA_MAP
;
195 urb
->interval
= stream
->props
.u
.isoc
.interval
;
196 urb
->number_of_packets
= stream
->props
.u
.isoc
.framesperurb
;
197 urb
->transfer_buffer_length
= stream
->buf_size
;
198 urb
->transfer_buffer
= stream
->buf_list
[i
];
199 urb
->transfer_dma
= stream
->dma_addr
[i
];
201 for (j
= 0; j
< stream
->props
.u
.isoc
.framesperurb
; j
++) {
202 urb
->iso_frame_desc
[j
].offset
= frame_offset
;
203 urb
->iso_frame_desc
[j
].length
= stream
->props
.u
.isoc
.framesize
;
204 frame_offset
+= stream
->props
.u
.isoc
.framesize
;
207 stream
->urbs_initialized
++;
212 int usb_urb_init(struct usb_data_stream
*stream
, struct usb_data_stream_properties
*props
)
214 if (stream
== NULL
|| props
== NULL
)
217 memcpy(&stream
->props
, props
, sizeof(*props
));
219 usb_clear_halt(stream
->udev
,usb_rcvbulkpipe(stream
->udev
,stream
->props
.endpoint
));
221 if (stream
->complete
== NULL
) {
222 err("there is no data callback - this doesn't make sense.");
226 switch (stream
->props
.type
) {
228 return usb_bulk_urb_init(stream
);
230 return usb_isoc_urb_init(stream
);
232 err("unknown URB-type for data transfer.");
237 int usb_urb_exit(struct usb_data_stream
*stream
)
241 usb_urb_kill(stream
);
243 for (i
= 0; i
< stream
->urbs_initialized
; i
++) {
244 if (stream
->urb_list
[i
] != NULL
) {
245 deb_mem("freeing URB no. %d.\n",i
);
247 usb_free_urb(stream
->urb_list
[i
]);
250 stream
->urbs_initialized
= 0;
252 usb_free_stream_buffers(stream
);