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 stream
->urb_list
[i
] = usb_alloc_urb(0, GFP_ATOMIC
);
147 if (!stream
->urb_list
[i
]) {
148 deb_mem("not enough memory for urb_alloc_urb!.\n");
149 for (j
= 0; j
< i
; j
++)
150 usb_free_urb(stream
->urb_list
[i
]);
153 usb_fill_bulk_urb( stream
->urb_list
[i
], stream
->udev
,
154 usb_rcvbulkpipe(stream
->udev
,stream
->props
.endpoint
),
156 stream
->props
.u
.bulk
.buffersize
,
157 usb_urb_complete
, stream
);
159 stream
->urb_list
[i
]->transfer_flags
= URB_NO_TRANSFER_DMA_MAP
;
160 stream
->urb_list
[i
]->transfer_dma
= stream
->dma_addr
[i
];
161 stream
->urbs_initialized
++;
166 static int usb_isoc_urb_init(struct usb_data_stream
*stream
)
170 if ((i
= usb_allocate_stream_buffers(stream
,stream
->props
.count
,
171 stream
->props
.u
.isoc
.framesize
*stream
->props
.u
.isoc
.framesperurb
)) < 0)
174 /* allocate the URBs */
175 for (i
= 0; i
< stream
->props
.count
; i
++) {
177 int frame_offset
= 0;
179 stream
->urb_list
[i
] = usb_alloc_urb(stream
->props
.u
.isoc
.framesperurb
, GFP_ATOMIC
);
180 if (!stream
->urb_list
[i
]) {
181 deb_mem("not enough memory for urb_alloc_urb!\n");
182 for (j
= 0; j
< i
; j
++)
183 usb_free_urb(stream
->urb_list
[i
]);
187 urb
= stream
->urb_list
[i
];
189 urb
->dev
= stream
->udev
;
190 urb
->context
= stream
;
191 urb
->complete
= usb_urb_complete
;
192 urb
->pipe
= usb_rcvisocpipe(stream
->udev
,stream
->props
.endpoint
);
193 urb
->transfer_flags
= URB_ISO_ASAP
| URB_NO_TRANSFER_DMA_MAP
;
194 urb
->interval
= stream
->props
.u
.isoc
.interval
;
195 urb
->number_of_packets
= stream
->props
.u
.isoc
.framesperurb
;
196 urb
->transfer_buffer_length
= stream
->buf_size
;
197 urb
->transfer_buffer
= stream
->buf_list
[i
];
198 urb
->transfer_dma
= stream
->dma_addr
[i
];
200 for (j
= 0; j
< stream
->props
.u
.isoc
.framesperurb
; j
++) {
201 urb
->iso_frame_desc
[j
].offset
= frame_offset
;
202 urb
->iso_frame_desc
[j
].length
= stream
->props
.u
.isoc
.framesize
;
203 frame_offset
+= stream
->props
.u
.isoc
.framesize
;
206 stream
->urbs_initialized
++;
211 int usb_urb_init(struct usb_data_stream
*stream
, struct usb_data_stream_properties
*props
)
213 if (stream
== NULL
|| props
== NULL
)
216 memcpy(&stream
->props
, props
, sizeof(*props
));
218 usb_clear_halt(stream
->udev
,usb_rcvbulkpipe(stream
->udev
,stream
->props
.endpoint
));
220 if (stream
->complete
== NULL
) {
221 err("there is no data callback - this doesn't make sense.");
225 switch (stream
->props
.type
) {
227 return usb_bulk_urb_init(stream
);
229 return usb_isoc_urb_init(stream
);
231 err("unkown URB-type for data transfer.");
236 int usb_urb_exit(struct usb_data_stream
*stream
)
240 usb_urb_kill(stream
);
242 for (i
= 0; i
< stream
->urbs_initialized
; i
++) {
243 if (stream
->urb_list
[i
] != NULL
) {
244 deb_mem("freeing URB no. %d.\n",i
);
246 usb_free_urb(stream
->urb_list
[i
]);
249 stream
->urbs_initialized
= 0;
251 usb_free_stream_buffers(stream
);