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/)
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
7 * see dvb-dibusb-core.c for more copyright details.
9 * This file contains functions for initializing and handling the
12 #include "dvb-dibusb.h"
14 #include <linux/version.h>
15 #include <linux/pci.h>
17 int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
20 int actlen,ret = -ENOMEM;
22 if (wbuf == NULL || wlen == 0)
25 if ((ret = down_interruptible(&dib->usb_sem)))
29 wbuf[0] == DIBUSB_REQ_I2C_WRITE &&
30 dib->dibdev->dev_cl->id == DIBUSB1_1)
31 deb_err("BUG: writing to i2c, while TS-streaming destroys the stream."
32 "(%x reg: %x %x)\n", wbuf[0],wbuf[2],wbuf[3]);
34 debug_dump(wbuf,wlen);
36 ret = usb_bulk_msg(dib->udev,usb_sndbulkpipe(dib->udev,
37 dib->dibdev->dev_cl->pipe_cmd), wbuf,wlen,&actlen,
41 err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
43 ret = actlen != wlen ? -1 : 0;
45 /* an answer is expected, and no error before */
46 if (!ret && rbuf && rlen) {
47 ret = usb_bulk_msg(dib->udev,usb_rcvbulkpipe(dib->udev,
48 dib->dibdev->dev_cl->pipe_cmd),rbuf,rlen,&actlen,
52 err("recv bulk message failed: %d",ret);
54 deb_alot("rlen: %d\n",rlen);
55 debug_dump(rbuf,actlen);
69 * #if 0'ing the following functions as they are not in use _now_,
70 * but probably will be sometime.
74 * do not use this, just a workaround for a bug,
75 * which will hopefully never occur :).
77 int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
79 u8 b[1] = { DIBUSB_REQ_INTR_READ };
80 return dibusb_write_usb(dib,b,1);
84 static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
86 return dibusb_readwrite_usb(dib,buf,len,NULL,0);
90 * ioctl for the firmware
92 static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen)
95 int size = plen > 32 ? 32 : plen;
97 b[0] = DIBUSB_REQ_SET_IOCTL;
101 memcpy(&b[2],param,size);
103 return dibusb_write_usb(dib,b,34); //2+size);
107 * ioctl for power control
109 int dibusb_hw_wakeup(struct dvb_frontend *fe)
111 struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
112 u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP };
113 deb_info("dibusb-device is getting up.\n");
114 dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
117 return dib->fe_init(fe);
122 int dibusb_hw_sleep(struct dvb_frontend *fe)
124 struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
125 u8 b[1] = { DIBUSB_IOCTL_POWER_SLEEP };
126 deb_info("dibusb-device is going to bed.\n");
127 dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
130 return dib->fe_sleep(fe);
135 int dibusb_set_streaming_mode(struct usb_dibusb *dib,u8 mode)
137 u8 b[2] = { DIBUSB_REQ_SET_STREAMING_MODE, mode };
138 return dibusb_readwrite_usb(dib,b,2,NULL,0);
141 int dibusb_streaming(struct usb_dibusb *dib,int onoff)
143 switch (dib->dibdev->dev_cl->id) {
146 return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_ENABLE_STREAM,NULL,0);
148 return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_DISABLE_STREAM,NULL,0);
151 return dibusb_set_streaming_mode(dib,onoff);
159 int dibusb_urb_init(struct usb_dibusb *dib)
161 int ret,i,bufsize,def_pid_parse = 1;
164 * when reloading the driver w/o replugging the device
165 * a timeout occures, this helps
167 usb_clear_halt(dib->udev,usb_sndbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));
168 usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));
169 usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data));
171 /* allocate the array for the data transfer URBs */
172 dib->urb_list = kmalloc(dib->dibdev->dev_cl->urb_count*sizeof(struct urb *),GFP_KERNEL);
173 if (dib->urb_list == NULL)
175 memset(dib->urb_list,0,dib->dibdev->dev_cl->urb_count*sizeof(struct urb *));
177 dib->init_state |= DIBUSB_STATE_URB_LIST;
179 bufsize = dib->dibdev->dev_cl->urb_count*dib->dibdev->dev_cl->urb_buffer_size;
180 deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
181 /* allocate the actual buffer for the URBs */
182 if ((dib->buffer = pci_alloc_consistent(NULL,bufsize,&dib->dma_handle)) == NULL) {
183 deb_info("not enough memory.\n");
186 deb_info("allocation complete\n");
187 memset(dib->buffer,0,bufsize);
189 dib->init_state |= DIBUSB_STATE_URB_BUF;
191 /* allocate and submit the URBs */
192 for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
193 if (!(dib->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
196 deb_info("submitting URB no. %d\n",i);
198 usb_fill_bulk_urb( dib->urb_list[i], dib->udev,
199 usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data),
200 &dib->buffer[i*dib->dibdev->dev_cl->urb_buffer_size],
201 dib->dibdev->dev_cl->urb_buffer_size,
202 dibusb_urb_complete, dib);
204 dib->urb_list[i]->transfer_flags = 0;
206 if ((ret = usb_submit_urb(dib->urb_list[i],GFP_ATOMIC))) {
207 err("could not submit buffer urb no. %d\n",i);
210 dib->init_state |= DIBUSB_STATE_URB_SUBMIT;
213 /* dib->pid_parse here contains the value of the module parameter */
214 /* decide if pid parsing can be deactivated:
215 * is possible (by speed) and wanted (by user)
217 switch (dib->dibdev->dev_cl->id) {
219 if (dib->udev->speed == USB_SPEED_HIGH && !dib->pid_parse) {
221 info("running at HIGH speed, will deliver the complete TS.");
223 info("will use pid_parsing.");
228 /* from here on it contains the device and user decision */
229 dib->pid_parse = def_pid_parse;
234 int dibusb_urb_exit(struct usb_dibusb *dib)
237 if (dib->init_state & DIBUSB_STATE_URB_LIST) {
238 for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
239 if (dib->urb_list[i] != NULL) {
240 deb_info("killing URB no. %d.\n",i);
243 usb_kill_urb(dib->urb_list[i]);
245 deb_info("freeing URB no. %d.\n",i);
247 usb_free_urb(dib->urb_list[i]);
250 /* free the urb array */
251 kfree(dib->urb_list);
252 dib->init_state &= ~DIBUSB_STATE_URB_SUBMIT;
253 dib->init_state &= ~DIBUSB_STATE_URB_LIST;
256 if (dib->init_state & DIBUSB_STATE_URB_BUF)
257 pci_free_consistent(NULL,
258 dib->dibdev->dev_cl->urb_buffer_size*dib->dibdev->dev_cl->urb_count,
259 dib->buffer,dib->dma_handle);
261 dib->init_state &= ~DIBUSB_STATE_URB_BUF;