summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
diff options
context:
space:
mode:
authorPatrick Boettcher <devnull@localhost>2004-12-26 21:36:25 +0000
committerPatrick Boettcher <devnull@localhost>2004-12-26 21:36:25 +0000
commita6f918f6a12f1f47ee17ec62a0844dea8c3ab33b (patch)
tree1f6e7ec0623e3ff3b30d456a339845cd5ed6d3c5 /linux/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
parentec61b5437a9c1b58d31e84eb725d08f4bd4fbeac (diff)
downloadmediapointer-dvb-s2-a6f918f6a12f1f47ee17ec62a0844dea8c3ab33b.tar.gz
mediapointer-dvb-s2-a6f918f6a12f1f47ee17ec62a0844dea8c3ab33b.tar.bz2
- enabled i2c-address probing for frontends
- refactored the dibusb driver, split into separate, code-dependent files, should have done this from the beginning, sorry for possible inconveniences in advance; I'm still learning
Diffstat (limited to 'linux/drivers/media/dvb/dibusb/dvb-dibusb-usb.c')
-rw-r--r--linux/drivers/media/dvb/dibusb/dvb-dibusb-usb.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-usb.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
new file mode 100644
index 000000000..7176859fe
--- /dev/null
+++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
@@ -0,0 +1,216 @@
+/*
+ * dvb-dibusb-usb.c is part of the driver for mobile USB Budget DVB-T devices
+ * based on reference design made by DiBcom (http://www.dibcom.fr/)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * see dvb-dibusb-core.c for more copyright details.
+ *
+ * This file contains functions for initializing and handling the
+ * usb specific stuff.
+ */
+#include "dvb-dibusb.h"
+
+#include <linux/version.h>
+#include <linux/pci.h>
+
+int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
+ u16 rlen)
+{
+ int actlen,ret = -ENOMEM;
+
+ if (wbuf == NULL || wlen == 0)
+ return -EINVAL;
+
+ if ((ret = down_interruptible(&dib->usb_sem)))
+ return ret;
+
+ if (dib->feedcount &&
+ wbuf[0] == DIBUSB_REQ_I2C_WRITE &&
+ dib->dibdev->parm->type == DIBUSB1_1)
+ deb_err("BUG: writing to i2c, while TS-streaming destroys the stream."
+ "(%x reg: %x %x)\n", wbuf[0],wbuf[2],wbuf[3]);
+
+ debug_dump(wbuf,wlen);
+
+ ret = usb_bulk_msg(dib->udev,usb_sndbulkpipe(dib->udev,
+ dib->dibdev->parm->cmd_pipe), wbuf,wlen,&actlen,
+ DIBUSB_I2C_TIMEOUT);
+
+ if (ret)
+ err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
+ else
+ ret = actlen != wlen ? -1 : 0;
+
+ /* an answer is expected, and no error before */
+ if (!ret && rbuf && rlen) {
+ ret = usb_bulk_msg(dib->udev,usb_rcvbulkpipe(dib->udev,
+ dib->dibdev->parm->result_pipe),rbuf,rlen,&actlen,
+ DIBUSB_I2C_TIMEOUT);
+
+ if (ret)
+ err("recv bulk message failed: %d",ret);
+ else {
+ deb_alot("rlen: %d\n",rlen);
+ debug_dump(rbuf,actlen);
+ }
+ }
+
+ up(&dib->usb_sem);
+ return ret;
+}
+
+/*
+ * Cypress controls
+ */
+
+#if 0
+/*
+ * #if 0'ing the following functions as they are not in use _now_,
+ * but probably will be sometime.
+ */
+
+/*
+ * do not use this, just a workaround for a bug,
+ * which will hopefully never occur :).
+ */
+int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
+{
+ u8 b[1] = { DIBUSB_REQ_INTR_READ };
+ return dibusb_write_usb(dib,b,1);
+}
+
+/*
+ * ioctl for power control
+ */
+int dibusb_hw_sleep(struct usb_dibusb *dib)
+{
+ u8 b[1] = { DIBUSB_IOCTL_POWER_SLEEP };
+ return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
+}
+
+#endif
+static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
+{
+ return dibusb_readwrite_usb(dib,buf,len,NULL,0);
+}
+
+/*
+ * ioctl for the firmware
+ */
+static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen)
+{
+ u8 b[34];
+ int size = plen > 32 ? 32 : plen;
+ b[0] = DIBUSB_REQ_SET_IOCTL;
+ b[1] = cmd;
+
+ if (size > 0)
+ memcpy(&b[2],param,size);
+
+ return dibusb_write_usb(dib,b,34); //2+size);
+}
+
+int dibusb_hw_wakeup(struct usb_dibusb *dib)
+{
+ u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP };
+ return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
+}
+
+int dibusb_set_streaming_mode(struct usb_dibusb *dib,u8 mode)
+{
+ u8 b[2] = { DIBUSB_REQ_SET_STREAMING_MODE, mode };
+ return dibusb_readwrite_usb(dib,b,2,NULL,0);
+}
+
+int dibusb_streaming(struct usb_dibusb *dib,int onoff)
+{
+ if (onoff)
+ return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_ENABLE_STREAM,NULL,0);
+ else
+ return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_DISABLE_STREAM,NULL,0);
+}
+
+int dibusb_usb_init(struct usb_dibusb *dib)
+{
+ int ret,i,bufsize;
+
+ /*
+ * when reloading the driver w/o replugging the device
+ * a timeout occures, this helps
+ */
+ usb_clear_halt(dib->udev,usb_sndbulkpipe(dib->udev,dib->dibdev->parm->cmd_pipe));
+ usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->parm->result_pipe));
+ usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->parm->data_pipe));
+
+ /* allocate the array for the data transfer URBs */
+ dib->urb_list = kmalloc(dib->dibdev->parm->num_urbs*sizeof(struct urb *),GFP_KERNEL);
+ if (dib->urb_list == NULL)
+ return -ENOMEM;
+ memset(dib->urb_list,0,dib->dibdev->parm->num_urbs*sizeof(struct urb *));
+
+ bufsize = dib->dibdev->parm->num_urbs*dib->dibdev->parm->urb_buf_size;
+ deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
+ /* allocate the actual buffer for the URBs */
+ if ((dib->buffer = pci_alloc_consistent(NULL,bufsize,&dib->dma_handle)) == NULL) {
+ deb_info("not enough memory.\n");
+ return -ENOMEM;
+ }
+ deb_info("allocation complete\n");
+ memset(dib->buffer,0,bufsize);
+
+ /* allocate and submit the URBs */
+ for (i = 0; i < dib->dibdev->parm->num_urbs; i++) {
+ if (!(dib->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
+ return -ENOMEM;
+ }
+ deb_info("submitting URB no. %d\n",i);
+
+ usb_fill_bulk_urb( dib->urb_list[i], dib->udev,
+ usb_rcvbulkpipe(dib->udev,dib->dibdev->parm->data_pipe),
+ &dib->buffer[i*dib->dibdev->parm->urb_buf_size],
+ dib->dibdev->parm->urb_buf_size,
+ dibusb_urb_complete, dib);
+
+ dib->urb_list[i]->transfer_flags = 0;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,7)
+ dib->urb_list[i]->timeout = 0;
+#endif
+
+ if ((ret = usb_submit_urb(dib->urb_list[i],GFP_ATOMIC))) {
+ err("could not submit buffer urb no. %d\n",i);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+int dibusb_usb_exit(struct usb_dibusb *dib)
+{
+ int i;
+ if (dib->urb_list != NULL) {
+ for (i = 0; i < dib->dibdev->parm->num_urbs; i++) {
+ if (dib->urb_list[i] != NULL) {
+ deb_info("killing URB no. %d.\n",i);
+
+ /* stop the URBs */
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,7)
+ usb_unlink_urb(dib->urb_list[i]);
+#else
+ usb_kill_urb(dib->urb_list[i]);
+#endif
+
+ deb_info("freeing URB no. %d.\n",i);
+ /* free the URBs */
+ usb_free_urb(dib->urb_list[i]);
+ }
+ }
+ /* free the urb array */
+ kfree(dib->urb_list);
+ }
+
+ pci_free_consistent(NULL,
+ dib->dibdev->parm->urb_buf_size*dib->dibdev->parm->num_urbs,dib->buffer,
+ dib->dma_handle);
+ return 0;
+}