vserver 2.0 rc7
[linux-2.6.git] / drivers / media / dvb / dibusb / dvb-dibusb-usb.c
1 /*
2  * dvb-dibusb-usb.c is part of the driver for mobile USB Budget DVB-T devices
3  * based on reference design made by DiBcom (http://www.dibcom.fr/)
4  *
5  * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
6  *
7  * see dvb-dibusb-core.c for more copyright details.
8  *
9  * This file contains functions for initializing and handling the
10  * usb specific stuff.
11  */
12 #include "dvb-dibusb.h"
13
14 #include <linux/version.h>
15 #include <linux/pci.h>
16
17 int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
18                 u16 rlen)
19 {
20         int actlen,ret = -ENOMEM;
21
22         if (wbuf == NULL || wlen == 0)
23                 return -EINVAL;
24
25         if ((ret = down_interruptible(&dib->usb_sem)))
26                 return ret;
27
28         debug_dump(wbuf,wlen);
29
30         ret = usb_bulk_msg(dib->udev,usb_sndbulkpipe(dib->udev,
31                         dib->dibdev->dev_cl->pipe_cmd), wbuf,wlen,&actlen,
32                         DIBUSB_I2C_TIMEOUT);
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                 ret = usb_bulk_msg(dib->udev,usb_rcvbulkpipe(dib->udev,
42                                 dib->dibdev->dev_cl->pipe_cmd),rbuf,rlen,&actlen,
43                                 DIBUSB_I2C_TIMEOUT);
44
45                 if (ret)
46                         err("recv bulk message failed: %d",ret);
47                 else {
48                         deb_alot("rlen: %d\n",rlen);
49                         debug_dump(rbuf,actlen);
50                 }
51         }
52
53         up(&dib->usb_sem);
54         return ret;
55 }
56
57 /*
58  * Cypress controls
59  */
60 int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
61 {
62         return dibusb_readwrite_usb(dib,buf,len,NULL,0);
63 }
64
65 #if 0
66 /*
67  * #if 0'ing the following functions as they are not in use _now_,
68  * but probably will be sometime.
69  */
70 /*
71  * do not use this, just a workaround for a bug,
72  * which will hopefully never occur :).
73  */
74 int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
75 {
76         u8 b[1] = { DIBUSB_REQ_INTR_READ };
77         return dibusb_write_usb(dib,b,1);
78 }
79 #endif
80
81 /*
82  * ioctl for the firmware
83  */
84 static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen)
85 {
86         u8 b[34];
87         int size = plen > 32 ? 32 : plen;
88         memset(b,0,34);
89         b[0] = DIBUSB_REQ_SET_IOCTL;
90         b[1] = cmd;
91
92         if (size > 0)
93                 memcpy(&b[2],param,size);
94
95         return dibusb_write_usb(dib,b,34); //2+size);
96 }
97
98 /*
99  * ioctl for power control
100  */
101 int dibusb_hw_wakeup(struct dvb_frontend *fe)
102 {
103         struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
104         u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP };
105         deb_info("dibusb-device is getting up.\n");
106
107         switch (dib->dibdev->dev_cl->id) {
108                 case DTT200U:
109                         break;
110                 default:
111                         dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
112                         break;
113         }
114
115         if (dib->fe_init)
116                 return dib->fe_init(fe);
117
118         return 0;
119 }
120
121 int dibusb_hw_sleep(struct dvb_frontend *fe)
122 {
123         struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
124         u8 b[1] = { DIBUSB_IOCTL_POWER_SLEEP };
125         deb_info("dibusb-device is going to bed.\n");
126         /* workaround, something is wrong, when dibusb 1.1 device are going to bed too late */
127         switch (dib->dibdev->dev_cl->id) {
128                 case DIBUSB1_1:
129                 case NOVAT_USB2:
130                 case DTT200U:
131                         break;
132                 default:
133                         dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
134                         break;
135         }
136         if (dib->fe_sleep)
137                 return dib->fe_sleep(fe);
138
139         return 0;
140 }
141
142 int dibusb_set_streaming_mode(struct usb_dibusb *dib,u8 mode)
143 {
144         u8 b[2] = { DIBUSB_REQ_SET_STREAMING_MODE, mode };
145         return dibusb_readwrite_usb(dib,b,2,NULL,0);
146 }
147
148 static int dibusb_urb_kill(struct usb_dibusb *dib)
149 {
150         int i;
151 deb_info("trying to kill urbs\n");
152         if (dib->init_state & DIBUSB_STATE_URB_SUBMIT) {
153                 for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
154                         deb_info("killing URB no. %d.\n",i);
155
156                         /* stop the URB */
157                         usb_kill_urb(dib->urb_list[i]);
158                 }
159         } else
160         deb_info(" URBs not killed.\n");
161         dib->init_state &= ~DIBUSB_STATE_URB_SUBMIT;
162         return 0;
163 }
164
165 static int dibusb_urb_submit(struct usb_dibusb *dib)
166 {
167         int i,ret;
168         if (dib->init_state & DIBUSB_STATE_URB_INIT) {
169                 for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
170                         deb_info("submitting URB no. %d\n",i);
171                         if ((ret = usb_submit_urb(dib->urb_list[i],GFP_ATOMIC))) {
172                                 err("could not submit buffer urb no. %d - get them all back\n",i);
173                                 dibusb_urb_kill(dib);
174                                 return ret;
175                         }
176                         dib->init_state |= DIBUSB_STATE_URB_SUBMIT;
177                 }
178         }
179         return 0;
180 }
181
182 int dibusb_streaming(struct usb_dibusb *dib,int onoff)
183 {
184         if (onoff)
185                 dibusb_urb_submit(dib);
186         else
187                 dibusb_urb_kill(dib);
188
189         switch (dib->dibdev->dev_cl->id) {
190                 case DIBUSB2_0:
191                 case DIBUSB2_0B:
192                 case NOVAT_USB2:
193                 case UMT2_0:
194                         if (onoff)
195                                 return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_ENABLE_STREAM,NULL,0);
196                         else
197                                 return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_DISABLE_STREAM,NULL,0);
198                         break;
199                 default:
200                         break;
201         }
202         return 0;
203 }
204
205 int dibusb_urb_init(struct usb_dibusb *dib)
206 {
207         int i,bufsize,def_pid_parse = 1;
208
209         /*
210          * when reloading the driver w/o replugging the device
211          * a timeout occures, this helps
212          */
213         usb_clear_halt(dib->udev,usb_sndbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));
214         usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));
215         usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data));
216
217         /* allocate the array for the data transfer URBs */
218         dib->urb_list = kmalloc(dib->dibdev->dev_cl->urb_count*sizeof(struct urb *),GFP_KERNEL);
219         if (dib->urb_list == NULL)
220                 return -ENOMEM;
221         memset(dib->urb_list,0,dib->dibdev->dev_cl->urb_count*sizeof(struct urb *));
222
223         dib->init_state |= DIBUSB_STATE_URB_LIST;
224
225         bufsize = dib->dibdev->dev_cl->urb_count*dib->dibdev->dev_cl->urb_buffer_size;
226         deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
227         /* allocate the actual buffer for the URBs */
228         if ((dib->buffer = pci_alloc_consistent(NULL,bufsize,&dib->dma_handle)) == NULL) {
229                 deb_info("not enough memory.\n");
230                 return -ENOMEM;
231         }
232         deb_info("allocation complete\n");
233         memset(dib->buffer,0,bufsize);
234
235         dib->init_state |= DIBUSB_STATE_URB_BUF;
236
237         /* allocate and submit the URBs */
238         for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
239                 if (!(dib->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
240                         return -ENOMEM;
241                 }
242
243                 usb_fill_bulk_urb( dib->urb_list[i], dib->udev,
244                                 usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data),
245                                 &dib->buffer[i*dib->dibdev->dev_cl->urb_buffer_size],
246                                 dib->dibdev->dev_cl->urb_buffer_size,
247                                 dibusb_urb_complete, dib);
248
249                 dib->urb_list[i]->transfer_flags = 0;
250
251                 dib->init_state |= DIBUSB_STATE_URB_INIT;
252         }
253
254         /* dib->pid_parse here contains the value of the module parameter */
255         /* decide if pid parsing can be deactivated:
256          * is possible (by device type) and wanted (by user)
257          */
258         switch (dib->dibdev->dev_cl->id) {
259                 case DIBUSB2_0:
260                 case DIBUSB2_0B:
261                         if (dib->udev->speed == USB_SPEED_HIGH && !dib->pid_parse) {
262                                 def_pid_parse = 0;
263                                 info("running at HIGH speed, will deliver the complete TS.");
264                         } else
265                                 info("will use pid_parsing.");
266                         break;
267                 default:
268                         break;
269         }
270         /* from here on it contains the device and user decision */
271         dib->pid_parse = def_pid_parse;
272
273         return 0;
274 }
275
276 int dibusb_urb_exit(struct usb_dibusb *dib)
277 {
278         int i;
279
280         dibusb_urb_kill(dib);
281
282         if (dib->init_state & DIBUSB_STATE_URB_LIST) {
283                 for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
284                         if (dib->urb_list[i] != NULL) {
285                                 deb_info("freeing URB no. %d.\n",i);
286                                 /* free the URBs */
287                                 usb_free_urb(dib->urb_list[i]);
288                         }
289                 }
290                 /* free the urb array */
291                 kfree(dib->urb_list);
292                 dib->init_state &= ~DIBUSB_STATE_URB_LIST;
293         }
294
295         if (dib->init_state & DIBUSB_STATE_URB_BUF)
296                 pci_free_consistent(NULL,
297                         dib->dibdev->dev_cl->urb_buffer_size*dib->dibdev->dev_cl->urb_count,
298                         dib->buffer,dib->dma_handle);
299
300         dib->init_state &= ~DIBUSB_STATE_URB_BUF;
301         dib->init_state &= ~DIBUSB_STATE_URB_INIT;
302         return 0;
303 }