88b283731bb8c84e1dcf7c4a90cc15b0604fd1c6
[pandora-kernel.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                         break;
84                 case -ECONNRESET:   /* kill */
85                 case -ENOENT:
86                 case -ESHUTDOWN:
87                         return;
88                 default:        /* error */
89                         deb_ts("urb completition error %d.", urb->status);
90                         break;
91         }
92
93         if (d->feedcount > 0) {
94                 if (d->state & DVB_USB_STATE_DVB) {
95                         switch (ptype) {
96                                 case PIPE_ISOCHRONOUS:
97                                         b = (u8 *) urb->transfer_buffer;
98                                         for (i = 0; i < urb->number_of_packets; i++) {
99                                                 if (urb->iso_frame_desc[i].status != 0)
100                                                         deb_ts("iso frame descriptor has an error: %d\n",urb->iso_frame_desc[i].status);
101                                                 else if (urb->iso_frame_desc[i].actual_length > 0) {
102                                                                 dvb_dmx_swfilter(&d->demux,b + urb->iso_frame_desc[i].offset,
103                                                                                 urb->iso_frame_desc[i].actual_length);
104                                                         }
105                                                 urb->iso_frame_desc[i].status = 0;
106                                                 urb->iso_frame_desc[i].actual_length = 0;
107                                         }
108                                         debug_dump(b,20,deb_ts);
109                                         break;
110                                 case PIPE_BULK:
111                                         if (urb->actual_length > 0)
112                                                 dvb_dmx_swfilter(&d->demux, (u8 *) urb->transfer_buffer,urb->actual_length);
113                                         break;
114                                 default:
115                                         err("unkown endpoint type in completition handler.");
116                                         return;
117                         }
118                 }
119         }
120
121         usb_submit_urb(urb,GFP_ATOMIC);
122 }
123
124 int dvb_usb_urb_kill(struct dvb_usb_device *d)
125 {
126         int i;
127         for (i = 0; i < d->urbs_submitted; i++) {
128                 deb_ts("killing URB no. %d.\n",i);
129
130                 /* stop the URB */
131                 usb_kill_urb(d->urb_list[i]);
132         }
133         d->urbs_submitted = 0;
134         return 0;
135 }
136
137 int dvb_usb_urb_submit(struct dvb_usb_device *d)
138 {
139         int i,ret;
140         for (i = 0; i < d->urbs_initialized; i++) {
141                 deb_ts("submitting URB no. %d\n",i);
142                 if ((ret = usb_submit_urb(d->urb_list[i],GFP_ATOMIC))) {
143                         err("could not submit URB no. %d - get them all back",i);
144                         dvb_usb_urb_kill(d);
145                         return ret;
146                 }
147                 d->urbs_submitted++;
148         }
149         return 0;
150 }
151
152 static int dvb_usb_free_stream_buffers(struct dvb_usb_device *d)
153 {
154         if (d->state & DVB_USB_STATE_URB_BUF) {
155                 while (d->buf_num) {
156                         d->buf_num--;
157                         deb_mem("freeing buffer %d\n",d->buf_num);
158                         usb_buffer_free(d->udev, d->buf_size,
159                                         d->buf_list[d->buf_num], d->dma_addr[d->buf_num]);
160                 }
161                 kfree(d->buf_list);
162                 kfree(d->dma_addr);
163         }
164
165         d->state &= ~DVB_USB_STATE_URB_BUF;
166
167         return 0;
168 }
169
170 static int dvb_usb_allocate_stream_buffers(struct dvb_usb_device *d, int num, unsigned long size)
171 {
172         d->buf_num = 0;
173         d->buf_size = size;
174
175         deb_mem("all in all I will use %lu bytes for streaming\n",num*size);
176
177         if ((d->buf_list = kcalloc(num, sizeof(u8 *), GFP_ATOMIC)) == NULL)
178                 return -ENOMEM;
179
180         if ((d->dma_addr = kcalloc(num, sizeof(dma_addr_t), GFP_ATOMIC)) == NULL) {
181                 kfree(d->buf_list);
182                 return -ENOMEM;
183         }
184
185         d->state |= DVB_USB_STATE_URB_BUF;
186
187         for (d->buf_num = 0; d->buf_num < num; d->buf_num++) {
188                 deb_mem("allocating buffer %d\n",d->buf_num);
189                 if (( d->buf_list[d->buf_num] =
190                                         usb_buffer_alloc(d->udev, size, SLAB_ATOMIC,
191                                         &d->dma_addr[d->buf_num]) ) == NULL) {
192                         deb_mem("not enough memory for urb-buffer allocation.\n");
193                         dvb_usb_free_stream_buffers(d);
194                         return -ENOMEM;
195                 }
196                 deb_mem("buffer %d: %p (dma: %llu)\n",
197                         d->buf_num, d->buf_list[d->buf_num],
198                         (unsigned long long)d->dma_addr[d->buf_num]);
199                 memset(d->buf_list[d->buf_num],0,size);
200         }
201         deb_mem("allocation successful\n");
202
203         return 0;
204 }
205
206 static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d)
207 {
208         int i;
209
210         if ((i = dvb_usb_allocate_stream_buffers(d,d->props.urb.count,
211                                         d->props.urb.u.bulk.buffersize)) < 0)
212                 return i;
213
214         /* allocate the URBs */
215         for (i = 0; i < d->props.urb.count; i++) {
216                 if ((d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC)) == NULL)
217                         return -ENOMEM;
218
219                 usb_fill_bulk_urb( d->urb_list[i], d->udev,
220                                 usb_rcvbulkpipe(d->udev,d->props.urb.endpoint),
221                                 d->buf_list[i],
222                                 d->props.urb.u.bulk.buffersize,
223                                 dvb_usb_urb_complete, d);
224
225                 d->urb_list[i]->transfer_flags = 0;
226                 d->urbs_initialized++;
227         }
228         return 0;
229 }
230
231 static int dvb_usb_isoc_urb_init(struct dvb_usb_device *d)
232 {
233         int i,j;
234
235         if ((i = dvb_usb_allocate_stream_buffers(d,d->props.urb.count,
236                                         d->props.urb.u.isoc.framesize*d->props.urb.u.isoc.framesperurb)) < 0)
237                 return i;
238
239         /* allocate the URBs */
240         for (i = 0; i < d->props.urb.count; i++) {
241                 struct urb *urb;
242                 int frame_offset = 0;
243                 if ((d->urb_list[i] =
244                                         usb_alloc_urb(d->props.urb.u.isoc.framesperurb,GFP_ATOMIC)) == NULL)
245                         return -ENOMEM;
246
247                 urb = d->urb_list[i];
248
249                 urb->dev = d->udev;
250                 urb->context = d;
251                 urb->complete = dvb_usb_urb_complete;
252                 urb->pipe = usb_rcvisocpipe(d->udev,d->props.urb.endpoint);
253                 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
254                 urb->interval = d->props.urb.u.isoc.interval;
255                 urb->number_of_packets = d->props.urb.u.isoc.framesperurb;
256                 urb->transfer_buffer_length = d->buf_size;
257                 urb->transfer_buffer = d->buf_list[i];
258                 urb->transfer_dma = d->dma_addr[i];
259
260                 for (j = 0; j < d->props.urb.u.isoc.framesperurb; j++) {
261                         urb->iso_frame_desc[j].offset = frame_offset;
262                         urb->iso_frame_desc[j].length = d->props.urb.u.isoc.framesize;
263                         frame_offset += d->props.urb.u.isoc.framesize;
264                 }
265
266                 d->urbs_initialized++;
267         }
268         return 0;
269
270 }
271
272 int dvb_usb_urb_init(struct dvb_usb_device *d)
273 {
274         /*
275          * when reloading the driver w/o replugging the device
276          * sometimes a timeout occures, this helps
277          */
278         if (d->props.generic_bulk_ctrl_endpoint != 0) {
279                 usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
280                 usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
281         }
282         usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint));
283
284         /* allocate the array for the data transfer URBs */
285         d->urb_list = kzalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
286         if (d->urb_list == NULL)
287                 return -ENOMEM;
288         d->state |= DVB_USB_STATE_URB_LIST;
289
290         switch (d->props.urb.type) {
291                 case DVB_USB_BULK:
292                         return dvb_usb_bulk_urb_init(d);
293                 case DVB_USB_ISOC:
294                         return dvb_usb_isoc_urb_init(d);
295                 default:
296                         err("unkown URB-type for data transfer.");
297                         return -EINVAL;
298         }
299 }
300
301 int dvb_usb_urb_exit(struct dvb_usb_device *d)
302 {
303         int i;
304
305         dvb_usb_urb_kill(d);
306
307         if (d->state & DVB_USB_STATE_URB_LIST) {
308                 for (i = 0; i < d->urbs_initialized; i++) {
309                         if (d->urb_list[i] != NULL) {
310                                 deb_mem("freeing URB no. %d.\n",i);
311                                 /* free the URBs */
312                                 usb_free_urb(d->urb_list[i]);
313                         }
314                 }
315                 d->urbs_initialized = 0;
316                 /* free the urb array */
317                 kfree(d->urb_list);
318                 d->state &= ~DVB_USB_STATE_URB_LIST;
319         }
320
321         dvb_usb_free_stream_buffers(d);
322         return 0;
323 }