This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / media / dvb / dvb-usb / dvb-usb-urb.c
1 /* dvb-usb-urb.c is part of the DVB USB library.
2  *
3  * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
4  * see dvb-usb-init.c for copyright information.
5  *
6  * This file contains functions for initializing and handling the
7  * USB and URB stuff.
8  */
9 #include "dvb-usb-common.h"
10
11 int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
12         u16 rlen, int delay_ms)
13 {
14         int actlen,ret = -ENOMEM;
15
16         if (d->props.generic_bulk_ctrl_endpoint == 0) {
17                 err("endpoint for generic control not specified.");
18                 return -EINVAL;
19         }
20
21         if (wbuf == NULL || wlen == 0)
22                 return -EINVAL;
23
24         if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
25                 return ret;
26
27         deb_xfer(">>> ");
28         debug_dump(wbuf,wlen,deb_xfer);
29
30         ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev,
31                         d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen,
32                         2000);
33
34         if (ret)
35                 err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
36         else
37                 ret = actlen != wlen ? -1 : 0;
38
39         /* an answer is expected, and no error before */
40         if (!ret && rbuf && rlen) {
41                 if (delay_ms)
42                         msleep(delay_ms);
43
44                 ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev,
45                                 d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen,
46                                 2000);
47
48                 if (ret)
49                         err("recv bulk message failed: %d",ret);
50                 else {
51                         deb_xfer("<<< ");
52                         debug_dump(rbuf,actlen,deb_xfer);
53                 }
54         }
55
56         mutex_unlock(&d->usb_mutex);
57         return ret;
58 }
59 EXPORT_SYMBOL(dvb_usb_generic_rw);
60
61 int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
62 {
63         return dvb_usb_generic_rw(d,buf,len,NULL,0,0);
64 }
65 EXPORT_SYMBOL(dvb_usb_generic_write);
66
67
68 /* URB stuff for streaming */
69 static void dvb_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
70 {
71         struct dvb_usb_device *d = urb->context;
72         int ptype = usb_pipetype(urb->pipe);
73         int i;
74         u8 *b;
75
76         deb_ts("'%s' urb completed. feedcount: %d, status: %d, length: %d/%d, pack_num: %d, errors: %d\n",
77                         ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk", d->feedcount,
78                         urb->status,urb->actual_length,urb->transfer_buffer_length,
79                         urb->number_of_packets,urb->error_count);
80
81         switch (urb->status) {
82                 case 0:         /* success */
83                 case -ETIMEDOUT:    /* NAK */
84                         break;
85                 case -ECONNRESET:   /* kill */
86                 case -ENOENT:
87                 case -ESHUTDOWN:
88                         return;
89                 default:        /* error */
90                         deb_ts("urb completition error %d.", urb->status);
91                         break;
92         }
93
94         if (d->feedcount > 0) {
95                 if (d->state & DVB_USB_STATE_DVB) {
96                         switch (ptype) {
97                                 case PIPE_ISOCHRONOUS:
98                                         b = (u8 *) urb->transfer_buffer;
99                                         for (i = 0; i < urb->number_of_packets; i++) {
100                                                 if (urb->iso_frame_desc[i].status != 0)
101                                                         deb_ts("iso frame descriptor has an error: %d\n",urb->iso_frame_desc[i].status);
102                                                 else if (urb->iso_frame_desc[i].actual_length > 0) {
103                                                                 dvb_dmx_swfilter(&d->demux,b + urb->iso_frame_desc[i].offset,
104                                                                                 urb->iso_frame_desc[i].actual_length);
105                                                         }
106                                                 urb->iso_frame_desc[i].status = 0;
107                                                 urb->iso_frame_desc[i].actual_length = 0;
108                                         }
109                                         debug_dump(b,20,deb_ts);
110                                         break;
111                                 case PIPE_BULK:
112                                         if (urb->actual_length > 0)
113                                                 dvb_dmx_swfilter(&d->demux, (u8 *) urb->transfer_buffer,urb->actual_length);
114                                         break;
115                                 default:
116                                         err("unkown endpoint type in completition handler.");
117                                         return;
118                         }
119                 }
120         }
121
122         usb_submit_urb(urb,GFP_ATOMIC);
123 }
124
125 int dvb_usb_urb_kill(struct dvb_usb_device *d)
126 {
127         int i;
128         for (i = 0; i < d->urbs_submitted; i++) {
129                 deb_ts("killing URB no. %d.\n",i);
130
131                 /* stop the URB */
132                 usb_kill_urb(d->urb_list[i]);
133         }
134         d->urbs_submitted = 0;
135         return 0;
136 }
137
138 int dvb_usb_urb_submit(struct dvb_usb_device *d)
139 {
140         int i,ret;
141         for (i = 0; i < d->urbs_initialized; i++) {
142                 deb_ts("submitting URB no. %d\n",i);
143                 if ((ret = usb_submit_urb(d->urb_list[i],GFP_ATOMIC))) {
144                         err("could not submit URB no. %d - get them all back",i);
145                         dvb_usb_urb_kill(d);
146                         return ret;
147                 }
148                 d->urbs_submitted++;
149         }
150         return 0;
151 }
152
153 static int dvb_usb_free_stream_buffers(struct dvb_usb_device *d)
154 {
155         if (d->state & DVB_USB_STATE_URB_BUF) {
156                 while (d->buf_num) {
157                         d->buf_num--;
158                         deb_mem("freeing buffer %d\n",d->buf_num);
159                         usb_buffer_free(d->udev, d->buf_size,
160                                         d->buf_list[d->buf_num], d->dma_addr[d->buf_num]);
161                 }
162                 kfree(d->buf_list);
163                 kfree(d->dma_addr);
164         }
165
166         d->state &= ~DVB_USB_STATE_URB_BUF;
167
168         return 0;
169 }
170
171 static int dvb_usb_allocate_stream_buffers(struct dvb_usb_device *d, int num, unsigned long size)
172 {
173         d->buf_num = 0;
174         d->buf_size = size;
175
176         deb_mem("all in all I will use %lu bytes for streaming\n",num*size);
177
178         if ((d->buf_list = kcalloc(num, sizeof(u8 *), GFP_ATOMIC)) == NULL)
179                 return -ENOMEM;
180
181         if ((d->dma_addr = kcalloc(num, sizeof(dma_addr_t), GFP_ATOMIC)) == NULL) {
182                 kfree(d->buf_list);
183                 return -ENOMEM;
184         }
185
186         d->state |= DVB_USB_STATE_URB_BUF;
187
188         for (d->buf_num = 0; d->buf_num < num; d->buf_num++) {
189                 deb_mem("allocating buffer %d\n",d->buf_num);
190                 if (( d->buf_list[d->buf_num] =
191                                         usb_buffer_alloc(d->udev, size, SLAB_ATOMIC,
192                                         &d->dma_addr[d->buf_num]) ) == NULL) {
193                         deb_mem("not enough memory for urb-buffer allocation.\n");
194                         dvb_usb_free_stream_buffers(d);
195                         return -ENOMEM;
196                 }
197                 deb_mem("buffer %d: %p (dma: %llu)\n",
198                         d->buf_num, d->buf_list[d->buf_num],
199                         (unsigned long long)d->dma_addr[d->buf_num]);
200                 memset(d->buf_list[d->buf_num],0,size);
201         }
202         deb_mem("allocation successful\n");
203
204         return 0;
205 }
206
207 static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d)
208 {
209         int i;
210
211         if ((i = dvb_usb_allocate_stream_buffers(d,d->props.urb.count,
212                                         d->props.urb.u.bulk.buffersize)) < 0)
213                 return i;
214
215         /* allocate the URBs */
216         for (i = 0; i < d->props.urb.count; i++) {
217                 if ((d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC)) == NULL)
218                         return -ENOMEM;
219
220                 usb_fill_bulk_urb( d->urb_list[i], d->udev,
221                                 usb_rcvbulkpipe(d->udev,d->props.urb.endpoint),
222                                 d->buf_list[i],
223                                 d->props.urb.u.bulk.buffersize,
224                                 dvb_usb_urb_complete, d);
225
226                 d->urb_list[i]->transfer_flags = 0;
227                 d->urbs_initialized++;
228         }
229         return 0;
230 }
231
232 static int dvb_usb_isoc_urb_init(struct dvb_usb_device *d)
233 {
234         int i,j;
235
236         if ((i = dvb_usb_allocate_stream_buffers(d,d->props.urb.count,
237                                         d->props.urb.u.isoc.framesize*d->props.urb.u.isoc.framesperurb)) < 0)
238                 return i;
239
240         /* allocate the URBs */
241         for (i = 0; i < d->props.urb.count; i++) {
242                 struct urb *urb;
243                 int frame_offset = 0;
244                 if ((d->urb_list[i] =
245                                         usb_alloc_urb(d->props.urb.u.isoc.framesperurb,GFP_ATOMIC)) == NULL)
246                         return -ENOMEM;
247
248                 urb = d->urb_list[i];
249
250                 urb->dev = d->udev;
251                 urb->context = d;
252                 urb->complete = dvb_usb_urb_complete;
253                 urb->pipe = usb_rcvisocpipe(d->udev,d->props.urb.endpoint);
254                 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
255                 urb->interval = d->props.urb.u.isoc.interval;
256                 urb->number_of_packets = d->props.urb.u.isoc.framesperurb;
257                 urb->transfer_buffer_length = d->buf_size;
258                 urb->transfer_buffer = d->buf_list[i];
259                 urb->transfer_dma = d->dma_addr[i];
260
261                 for (j = 0; j < d->props.urb.u.isoc.framesperurb; j++) {
262                         urb->iso_frame_desc[j].offset = frame_offset;
263                         urb->iso_frame_desc[j].length = d->props.urb.u.isoc.framesize;
264                         frame_offset += d->props.urb.u.isoc.framesize;
265                 }
266
267                 d->urbs_initialized++;
268         }
269         return 0;
270
271 }
272
273 int dvb_usb_urb_init(struct dvb_usb_device *d)
274 {
275         /*
276          * when reloading the driver w/o replugging the device
277          * sometimes a timeout occures, this helps
278          */
279         if (d->props.generic_bulk_ctrl_endpoint != 0) {
280                 usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
281                 usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
282         }
283         usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint));
284
285         /* allocate the array for the data transfer URBs */
286         d->urb_list = kzalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
287         if (d->urb_list == NULL)
288                 return -ENOMEM;
289         d->state |= DVB_USB_STATE_URB_LIST;
290
291         switch (d->props.urb.type) {
292                 case DVB_USB_BULK:
293                         return dvb_usb_bulk_urb_init(d);
294                 case DVB_USB_ISOC:
295                         return dvb_usb_isoc_urb_init(d);
296                 default:
297                         err("unkown URB-type for data transfer.");
298                         return -EINVAL;
299         }
300 }
301
302 int dvb_usb_urb_exit(struct dvb_usb_device *d)
303 {
304         int i;
305
306         dvb_usb_urb_kill(d);
307
308         if (d->state & DVB_USB_STATE_URB_LIST) {
309                 for (i = 0; i < d->urbs_initialized; i++) {
310                         if (d->urb_list[i] != NULL) {
311                                 deb_mem("freeing URB no. %d.\n",i);
312                                 /* free the URBs */
313                                 usb_free_urb(d->urb_list[i]);
314                         }
315                 }
316                 d->urbs_initialized = 0;
317                 /* free the urb array */
318                 kfree(d->urb_list);
319                 d->state &= ~DVB_USB_STATE_URB_LIST;
320         }
321
322         dvb_usb_free_stream_buffers(d);
323         return 0;
324 }