Merge git://git.skbuff.net/gitroot/yoshfuji/linux-2.6.14+advapi-fix/
[powerpc.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 = down_interruptible(&d->usb_sem)))
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         up(&d->usb_sem);
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 = kmalloc(num*sizeof(u8 *), GFP_ATOMIC)) == NULL)
179                 return -ENOMEM;
180
181         if ((d->dma_addr = kmalloc(num*sizeof(dma_addr_t), GFP_ATOMIC)) == NULL) {
182                 kfree(d->buf_list);
183                 return -ENOMEM;
184         }
185         memset(d->buf_list,0,num*sizeof(u8 *));
186         memset(d->dma_addr,0,num*sizeof(dma_addr_t));
187
188         d->state |= DVB_USB_STATE_URB_BUF;
189
190         for (d->buf_num = 0; d->buf_num < num; d->buf_num++) {
191                 deb_mem("allocating buffer %d\n",d->buf_num);
192                 if (( d->buf_list[d->buf_num] =
193                                         usb_buffer_alloc(d->udev, size, SLAB_ATOMIC,
194                                         &d->dma_addr[d->buf_num]) ) == NULL) {
195                         deb_mem("not enough memory for urb-buffer allocation.\n");
196                         dvb_usb_free_stream_buffers(d);
197                         return -ENOMEM;
198                 }
199                 deb_mem("buffer %d: %p (dma: %llu)\n",
200                         d->buf_num, d->buf_list[d->buf_num],
201                         (unsigned long long)d->dma_addr[d->buf_num]);
202                 memset(d->buf_list[d->buf_num],0,size);
203         }
204         deb_mem("allocation successful\n");
205
206         return 0;
207 }
208
209 static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d)
210 {
211         int i;
212
213         if ((i = dvb_usb_allocate_stream_buffers(d,d->props.urb.count,
214                                         d->props.urb.u.bulk.buffersize)) < 0)
215                 return i;
216
217         /* allocate the URBs */
218         for (i = 0; i < d->props.urb.count; i++) {
219                 if ((d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC)) == NULL)
220                         return -ENOMEM;
221
222                 usb_fill_bulk_urb( d->urb_list[i], d->udev,
223                                 usb_rcvbulkpipe(d->udev,d->props.urb.endpoint),
224                                 d->buf_list[i],
225                                 d->props.urb.u.bulk.buffersize,
226                                 dvb_usb_urb_complete, d);
227
228                 d->urb_list[i]->transfer_flags = 0;
229                 d->urbs_initialized++;
230         }
231         return 0;
232 }
233
234 static int dvb_usb_isoc_urb_init(struct dvb_usb_device *d)
235 {
236         int i,j;
237
238         if ((i = dvb_usb_allocate_stream_buffers(d,d->props.urb.count,
239                                         d->props.urb.u.isoc.framesize*d->props.urb.u.isoc.framesperurb)) < 0)
240                 return i;
241
242         /* allocate the URBs */
243         for (i = 0; i < d->props.urb.count; i++) {
244                 struct urb *urb;
245                 int frame_offset = 0;
246                 if ((d->urb_list[i] =
247                                         usb_alloc_urb(d->props.urb.u.isoc.framesperurb,GFP_ATOMIC)) == NULL)
248                         return -ENOMEM;
249
250                 urb = d->urb_list[i];
251
252                 urb->dev = d->udev;
253                 urb->context = d;
254                 urb->complete = dvb_usb_urb_complete;
255                 urb->pipe = usb_rcvisocpipe(d->udev,d->props.urb.endpoint);
256                 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
257                 urb->interval = d->props.urb.u.isoc.interval;
258                 urb->number_of_packets = d->props.urb.u.isoc.framesperurb;
259                 urb->transfer_buffer_length = d->buf_size;
260                 urb->transfer_buffer = d->buf_list[i];
261                 urb->transfer_dma = d->dma_addr[i];
262
263                 for (j = 0; j < d->props.urb.u.isoc.framesperurb; j++) {
264                         urb->iso_frame_desc[j].offset = frame_offset;
265                         urb->iso_frame_desc[j].length = d->props.urb.u.isoc.framesize;
266                         frame_offset += d->props.urb.u.isoc.framesize;
267                 }
268
269                 d->urbs_initialized++;
270         }
271         return 0;
272
273 }
274
275 int dvb_usb_urb_init(struct dvb_usb_device *d)
276 {
277         /*
278          * when reloading the driver w/o replugging the device
279          * sometimes a timeout occures, this helps
280          */
281         if (d->props.generic_bulk_ctrl_endpoint != 0) {
282                 usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
283                 usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
284         }
285         usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint));
286
287         /* allocate the array for the data transfer URBs */
288         d->urb_list = kmalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
289         if (d->urb_list == NULL)
290                 return -ENOMEM;
291         memset(d->urb_list,0,d->props.urb.count * sizeof(struct urb *));
292         d->state |= DVB_USB_STATE_URB_LIST;
293
294         switch (d->props.urb.type) {
295                 case DVB_USB_BULK:
296                         return dvb_usb_bulk_urb_init(d);
297                 case DVB_USB_ISOC:
298                         return dvb_usb_isoc_urb_init(d);
299                 default:
300                         err("unkown URB-type for data transfer.");
301                         return -EINVAL;
302         }
303 }
304
305 int dvb_usb_urb_exit(struct dvb_usb_device *d)
306 {
307         int i;
308
309         dvb_usb_urb_kill(d);
310
311         if (d->state & DVB_USB_STATE_URB_LIST) {
312                 for (i = 0; i < d->urbs_initialized; i++) {
313                         if (d->urb_list[i] != NULL) {
314                                 deb_mem("freeing URB no. %d.\n",i);
315                                 /* free the URBs */
316                                 usb_free_urb(d->urb_list[i]);
317                         }
318                 }
319                 d->urbs_initialized = 0;
320                 /* free the urb array */
321                 kfree(d->urb_list);
322                 d->state &= ~DVB_USB_STATE_URB_LIST;
323         }
324
325         dvb_usb_free_stream_buffers(d);
326         return 0;
327 }