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("unkown 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_buffer_free(stream
->udev
, stream
->buf_size
,
100 stream
->buf_list
[stream
->buf_num
], stream
->dma_addr
[stream
->buf_num
]);
104 stream
->state
&= ~USB_STATE_URB_BUF
;
109 static int usb_allocate_stream_buffers(struct usb_data_stream
*stream
, int num
, unsigned long size
)
112 stream
->buf_size
= size
;
114 deb_mem("all in all I will use %lu bytes for streaming\n",num
*size
);
116 for (stream
->buf_num
= 0; stream
->buf_num
< num
; stream
->buf_num
++) {
117 deb_mem("allocating buffer %d\n",stream
->buf_num
);
118 if (( stream
->buf_list
[stream
->buf_num
] =
119 usb_buffer_alloc(stream
->udev
, size
, GFP_ATOMIC
,
120 &stream
->dma_addr
[stream
->buf_num
]) ) == NULL
) {
121 deb_mem("not enough memory for urb-buffer allocation.\n");
122 usb_free_stream_buffers(stream
);
125 deb_mem("buffer %d: %p (dma: %Lu)\n",
127 stream
->buf_list
[stream
->buf_num
], (long long)stream
->dma_addr
[stream
->buf_num
]);
128 memset(stream
->buf_list
[stream
->buf_num
],0,size
);
129 stream
->state
|= USB_STATE_URB_BUF
;
131 deb_mem("allocation successful\n");
136 static int usb_bulk_urb_init(struct usb_data_stream
*stream
)
140 if ((i
= usb_allocate_stream_buffers(stream
,stream
->props
.count
,
141 stream
->props
.u
.bulk
.buffersize
)) < 0)
144 /* allocate the URBs */
145 for (i
= 0; i
< stream
->props
.count
; i
++) {
146 if ((stream
->urb_list
[i
] = usb_alloc_urb(0,GFP_ATOMIC
)) == NULL
)
149 usb_fill_bulk_urb( stream
->urb_list
[i
], stream
->udev
,
150 usb_rcvbulkpipe(stream
->udev
,stream
->props
.endpoint
),
152 stream
->props
.u
.bulk
.buffersize
,
153 usb_urb_complete
, stream
);
155 stream
->urb_list
[i
]->transfer_flags
= 0;
156 stream
->urbs_initialized
++;
161 static int usb_isoc_urb_init(struct usb_data_stream
*stream
)
165 if ((i
= usb_allocate_stream_buffers(stream
,stream
->props
.count
,
166 stream
->props
.u
.isoc
.framesize
*stream
->props
.u
.isoc
.framesperurb
)) < 0)
169 /* allocate the URBs */
170 for (i
= 0; i
< stream
->props
.count
; i
++) {
172 int frame_offset
= 0;
173 if ((stream
->urb_list
[i
] =
174 usb_alloc_urb(stream
->props
.u
.isoc
.framesperurb
,GFP_ATOMIC
)) == NULL
)
177 urb
= stream
->urb_list
[i
];
179 urb
->dev
= stream
->udev
;
180 urb
->context
= stream
;
181 urb
->complete
= usb_urb_complete
;
182 urb
->pipe
= usb_rcvisocpipe(stream
->udev
,stream
->props
.endpoint
);
183 urb
->transfer_flags
= URB_ISO_ASAP
| URB_NO_TRANSFER_DMA_MAP
;
184 urb
->interval
= stream
->props
.u
.isoc
.interval
;
185 urb
->number_of_packets
= stream
->props
.u
.isoc
.framesperurb
;
186 urb
->transfer_buffer_length
= stream
->buf_size
;
187 urb
->transfer_buffer
= stream
->buf_list
[i
];
188 urb
->transfer_dma
= stream
->dma_addr
[i
];
190 for (j
= 0; j
< stream
->props
.u
.isoc
.framesperurb
; j
++) {
191 urb
->iso_frame_desc
[j
].offset
= frame_offset
;
192 urb
->iso_frame_desc
[j
].length
= stream
->props
.u
.isoc
.framesize
;
193 frame_offset
+= stream
->props
.u
.isoc
.framesize
;
196 stream
->urbs_initialized
++;
201 int usb_urb_init(struct usb_data_stream
*stream
, struct usb_data_stream_properties
*props
)
203 if (stream
== NULL
|| props
== NULL
)
206 memcpy(&stream
->props
, props
, sizeof(*props
));
208 usb_clear_halt(stream
->udev
,usb_rcvbulkpipe(stream
->udev
,stream
->props
.endpoint
));
210 if (stream
->complete
== NULL
) {
211 err("there is no data callback - this doesn't make sense.");
215 switch (stream
->props
.type
) {
217 return usb_bulk_urb_init(stream
);
219 return usb_isoc_urb_init(stream
);
221 err("unkown URB-type for data transfer.");
226 int usb_urb_exit(struct usb_data_stream
*stream
)
230 usb_urb_kill(stream
);
232 for (i
= 0; i
< stream
->urbs_initialized
; i
++) {
233 if (stream
->urb_list
[i
] != NULL
) {
234 deb_mem("freeing URB no. %d.\n",i
);
236 usb_free_urb(stream
->urb_list
[i
]);
239 stream
->urbs_initialized
= 0;
241 usb_free_stream_buffers(stream
);