summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Woods <devnull@localhost>2003-04-03 21:37:56 +0000
committerAlex Woods <devnull@localhost>2003-04-03 21:37:56 +0000
commit7797455e309f859ebc4dc896251ffae4453531d6 (patch)
treefe07d5e3e84e7f5e79b82c1abdafc1e58ea967d3
parent372936a07e6c4b583102e572c1240715afa2134c (diff)
downloadmediapointer-dvb-s2-7797455e309f859ebc4dc896251ffae4453531d6.tar.gz
mediapointer-dvb-s2-7797455e309f859ebc4dc896251ffae4453531d6.tar.bz2
Fixes for usb_bulk_msg timeouts, and urb submission and unlinking errors.
(Spooky that Felix has been working on the same sort of thing!) Zapping process cleaner - doesn't stop and start the iso stream when adding more pid filters.
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c212
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/ttusb_dec.h6
2 files changed, 151 insertions, 67 deletions
diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 0457657f4..18f892542 100644
--- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -42,6 +42,13 @@ ttusb_dec_send_command(ttusb_dec_t * dec, const u8 command, const u8 params[],
dprintk("%s\n", __FUNCTION__);
+ if ((result = down_interruptible(&dec->usb_sem))) {
+
+ printk("%s: Failed to down usb semaphore.\n", __FUNCTION__);
+ return result;
+
+ }
+
b[0] = 0xaa;
b[1] = ++dec->trans_count;
b[2] = command;
@@ -63,16 +70,27 @@ ttusb_dec_send_command(ttusb_dec_t * dec, const u8 command, const u8 params[],
usb_bulk_msg(dec->udev, dec->command_pipe, b, sizeof (b),
&actual_len, HZ);
- if (result < 0)
+ if (result < 0) {
+
+ printk("%s: command bulk message failed: error %d\n",
+ __FUNCTION__, result);
+ up(&dec->usb_sem);
return result;
+ }
+
result =
usb_bulk_msg(dec->udev, dec->result_pipe, c, sizeof (c),
&actual_len, HZ);
- if (result < 0)
+ if (result < 0) {
+
+ printk("%s: result bulk message failed: error %d\n",
+ __FUNCTION__, result);
+ up(&dec->usb_sem);
return result;
- else {
+
+ } else {
if (debug) {
@@ -86,12 +104,25 @@ ttusb_dec_send_command(ttusb_dec_t * dec, const u8 command, const u8 params[],
if (cmd_result && c[3] > 0)
memcpy(cmd_result, &c[4], c[3]);
+ up(&dec->usb_sem);
return c[3];
}
}
+static int
+ttusb_dec_av_pes2ts_cb(void *priv, unsigned char *data)
+{
+
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
+
+ dvbdmxfeed->cb.ts(data, 188, 0, 0, &dvbdmxfeed->feed.ts, DMX_OK);
+
+ return 0;
+
+}
+
static void
ttusb_dec_set_pids(ttusb_dec_t * dec)
{
@@ -112,6 +143,17 @@ ttusb_dec_set_pids(ttusb_dec_t * dec)
ttusb_dec_send_command(dec, 0x50, b, sizeof (b), NULL);
+ if (!down_interruptible(&dec->pes2ts_sem)) {
+
+ dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO],
+ ttusb_dec_av_pes2ts_cb, dec->demux.feed);
+ dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO],
+ ttusb_dec_av_pes2ts_cb, dec->demux.feed);
+
+ up(&dec->pes2ts_sem);
+
+ }
+
}
static int
@@ -192,8 +234,15 @@ ttusb_dec_process_av_pes(ttusb_dec_t * dec, u8 * av_pes, int length)
memcpy(&dec->v_pes[dec->v_pes_length],
&av_pes[12], prebytes);
- dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
- dec->v_pes_length + prebytes);
+ if (!down_interruptible(&dec->pes2ts_sem)) {
+
+ dvb_filter_pes2ts(&dec->v_pes2ts,
+ dec->v_pes,
+ dec->v_pes_length +
+ prebytes);
+
+ up(&dec->pes2ts_sem);
+ }
}
@@ -243,9 +292,19 @@ ttusb_dec_process_av_pes(ttusb_dec_t * dec, u8 * av_pes, int length)
htons(dec->v_pes_length - 6 + postbytes);
memcpy(&dec->v_pes[4], &v_pes_payload_length, 2);
- if (postbytes == 0)
- dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
- dec->v_pes_length);
+ if (postbytes == 0) {
+
+ if (!down_interruptible(&dec->pes2ts_sem)) {
+
+ dvb_filter_pes2ts(&dec->v_pes2ts,
+ dec->v_pes,
+ dec->v_pes_length);
+
+ up(&dec->pes2ts_sem);
+
+ }
+
+ }
break;
@@ -256,7 +315,7 @@ ttusb_dec_process_av_pes(ttusb_dec_t * dec, u8 * av_pes, int length)
break;
default:
- printk("%s: unknown AV_PES type (%02x).\n", __FUNCTION__,
+ printk("%s: unknown AV_PES type: %02x.\n", __FUNCTION__,
av_pes[2]);
break;
@@ -376,9 +435,6 @@ ttusb_dec_process_urb(struct urb *urb)
ttusb_dec_t *dec = urb->context;
- if (!dec->iso_streaming)
- return;
-
if (!urb->status) {
int i;
@@ -399,7 +455,10 @@ ttusb_dec_process_urb(struct urb *urb)
} else {
- dprintk("%s: urb error: %d\n", __FUNCTION__, urb->status);
+ /* -ENOENT is expected when unlinking urbs */
+ if (urb->status != -ENOENT)
+ dprintk("%s: urb error: %d\n", __FUNCTION__,
+ urb->status);
}
@@ -449,74 +508,87 @@ ttusb_dec_stop_iso_xfer(ttusb_dec_t * dec)
dprintk("%s\n", __FUNCTION__);
- if (dec->iso_streaming)
- for (i = 0; i < ISO_BUF_COUNT; i++)
- usb_unlink_urb(dec->iso_urb[i]);
+ if (down_interruptible(&dec->iso_sem))
+ return;
- dec->iso_streaming = 0;
+ dec->iso_stream_count--;
-}
+ if (!dec->iso_stream_count) {
-static int
-ttusb_dec_av_pes2ts_cb(void *priv, unsigned char *data)
-{
+ u8 b0[] = { 0x00 };
- struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
+ for (i = 0; i < ISO_BUF_COUNT; i++)
+ usb_unlink_urb(dec->iso_urb[i]);
- dvbdmxfeed->cb.ts(data, 188, 0, 0, &dvbdmxfeed->feed.ts, DMX_OK);
+ ttusb_dec_send_command(dec, 0x81, b0, sizeof (b0), NULL);
- return 0;
+ }
+
+ up(&dec->iso_sem);
}
static int
-ttusb_dec_start_iso_xfer(ttusb_dec_t * dec)
+ttusb_dec_start_iso_xfer(ttusb_dec_t *dec)
{
int i, result;
- u8 b0[] = { 0x05 };
dprintk("%s\n", __FUNCTION__);
- ttusb_dec_send_command(dec, 0x80, b0, sizeof (b0), NULL);
+ if (down_interruptible(&dec->iso_sem))
+ return -EAGAIN;
- if (dec->iso_streaming) {
+ if (!dec->iso_stream_count) {
- printk("%s: iso xfer already running!\n", __FUNCTION__);
- return 0;
+ u8 b0[] = { 0x05 };
- }
+ ttusb_dec_send_command(dec, 0x80, b0, sizeof (b0), NULL);
- ttusb_dec_setup_urbs(dec);
+ ttusb_dec_setup_urbs(dec);
- for (i = 0; i < ISO_BUF_COUNT; i++) {
+ for (i = 0; i < ISO_BUF_COUNT; i++) {
- if ((result = usb_submit_urb(dec->iso_urb[i]))) {
+ if ((result = usb_submit_urb(dec->iso_urb[i]))) {
- ttusb_dec_stop_iso_xfer(dec);
- printk("%s: failed urb submission (%i: errno = %i)!\n",
- __FUNCTION__, i, result);
- return result;
+ printk("%s: failed urb submission %d: error %d\n",
+ __FUNCTION__, i, result);
+
+ while (i) {
+
+ usb_unlink_urb(dec->iso_urb[i]);
+ i--;
+
+ }
+
+ up(&dec->iso_sem);
+ return result;
+
+ }
}
+ dec->av_pes_state = 0;
+ dec->v_pes_postbytes = 0;
+
}
+ dec->iso_stream_count++;
+
+ up(&dec->iso_sem);
+
if (!dec->interface) {
- usb_set_interface(dec->udev, 0, 8); /* Can't do this at mod init time - weird */
+ /* Can't do this at mod init time - weird.
+ * Don't stick this at the top of this function either -
+ * it will cause the send_command to time out trying to get
+ * a result
+ */
+ usb_set_interface(dec->udev, 0, 8);
dec->interface = 8;
}
- dec->iso_streaming = 1;
- dec->av_pes_state = 0;
- dec->v_pes_postbytes = 0;
-
- dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO],
- ttusb_dec_av_pes2ts_cb, dec->demux.feed);
- dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO],
- ttusb_dec_av_pes2ts_cb, dec->demux.feed);
return 0;
@@ -534,9 +606,6 @@ ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
if (!dvbdmx->dmx.frontend)
return -EINVAL;
- if (dec->iso_streaming)
- ttusb_dec_stop_iso_xfer(dec);
-
dprintk(" pid: 0x%04X\n", dvbdmxfeed->pid);
switch (dvbdmxfeed->type) {
@@ -615,14 +684,11 @@ ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
ttusb_dec_t *dec = dvbdmxfeed->demux->priv;
- u8 b0[] = { 0x00 };
dprintk("%s\n", __FUNCTION__);
ttusb_dec_stop_iso_xfer(dec);
- ttusb_dec_send_command(dec, 0x81, b0, sizeof (b0), NULL);
-
return 0;
}
@@ -710,8 +776,9 @@ ttusb_dec_init_usb(ttusb_dec_t * dec)
dprintk("%s\n", __FUNCTION__);
- usb_set_configuration(dec->udev, 1);
- usb_set_interface(dec->udev, 0, 0);
+ sema_init(&dec->usb_sem, 1);
+ sema_init(&dec->iso_sem, 1);
+ spin_lock_init(&dec->iso_stream_count_lock);
dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE);
dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE);
@@ -794,8 +861,6 @@ ttusb_dec_init_stb(ttusb_dec_t * dec)
dprintk("%s\n", __FUNCTION__);
- usb_set_configuration(dec->udev, 1);
-
result = ttusb_dec_send_command(dec, 0x08, NULL, 0, c);
if (result == 0x10)
@@ -813,7 +878,7 @@ ttusb_dec_init_dvb(ttusb_dec_t * dec)
if ((result = dvb_register_adapter(&dec->adapter, "dec2000")) < 0) {
- printk("%s: dvb_register_adapter failed (errno = %d)\n",
+ printk("%s: dvb_register_adapter failed: error %d\n",
__FUNCTION__, result);
return result;
@@ -847,7 +912,7 @@ ttusb_dec_init_dvb(ttusb_dec_t * dec)
if ((result = dvb_dmx_init(&dec->demux)) < 0) {
- printk("%s: dvb_dmx_init failed (errno = %d)\n", __FUNCTION__,
+ printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
result);
dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter,
@@ -864,7 +929,7 @@ ttusb_dec_init_dvb(ttusb_dec_t * dec)
if ((result = dvb_dmxdev_init(&dec->dmxdev, dec->adapter)) < 0) {
- printk("%s: dvb_dmxdev_init failed (errno = %d)\n",
+ printk("%s: dvb_dmxdev_init failed: error %d\n",
__FUNCTION__, result);
dvb_dmx_release(&dec->demux);
@@ -885,7 +950,7 @@ ttusb_dec_init_dvb(ttusb_dec_t * dec)
dec->demux.dmx.add_frontend(&dec->demux.dmx,
&dec->frontend)) < 0) {
- printk("%s: dvb_dmx_init failed (errno = %d)\n", __FUNCTION__,
+ printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
result);
dvb_dmxdev_release(&dec->dmxdev);
@@ -902,7 +967,7 @@ ttusb_dec_init_dvb(ttusb_dec_t * dec)
dec->demux.dmx.connect_frontend(&dec->demux.dmx,
&dec->frontend)) < 0) {
- printk("%s: dvb_dmx_init failed (errno = %d)\n", __FUNCTION__,
+ printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
result);
dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
@@ -916,6 +981,8 @@ ttusb_dec_init_dvb(ttusb_dec_t * dec)
}
+ sema_init(&dec->pes2ts_sem, 1);
+
return 0;
}
@@ -935,6 +1002,21 @@ ttusb_dec_exit_dvb(ttusb_dec_t * dec)
}
+static void
+ttusb_dec_exit_usb(ttusb_dec_t * dec)
+{
+
+ int i;
+
+ dprintk("%s\n", __FUNCTION__);
+
+ for (i = 0; i < ISO_BUF_COUNT; i++)
+ usb_unlink_urb(dec->iso_urb[i]);
+
+ ttusb_dec_free_iso_urbs(dec);
+
+}
+
static void *
ttusb_dec_probe(struct usb_device *udev, unsigned int ifnum,
const struct usb_device_id *id)
@@ -978,12 +1060,10 @@ ttusb_dec_disconnect(struct usb_device *udev, void *data)
ttusb_dec_t *dec = data;
- ttusb_dec_stop_iso_xfer(dec);
+ ttusb_dec_exit_usb(dec);
ttusb_dec_exit_dvb(dec);
- ttusb_dec_free_iso_urbs(dec);
-
kfree(dec);
}
@@ -1014,7 +1094,7 @@ ttusb_dec_init(void)
if ((result = usb_register(&ttusb_dec_driver)) < 0) {
- printk("%s: initialisation failed (Error %d).\n", __FUNCTION__,
+ printk("%s: initialisation failed: error %d.\n", __FUNCTION__,
result);
return result;
diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.h b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.h
index d66edadc6..b658e7ad0 100644
--- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.h
+++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.h
@@ -22,6 +22,7 @@
#ifndef _TTUSB_DEC_H
#define _TTUSB_DEC_H
+#include "asm/semaphore.h"
#include "dmxdev.h"
#include "dvb_demux.h"
#include "dvb_filter.h"
@@ -60,11 +61,13 @@ typedef struct ttusb_dec_s {
unsigned int result_pipe;
unsigned int stream_pipe;
int interface;
+ struct semaphore usb_sem;
void *iso_buffer;
dma_addr_t iso_dma_handle;
struct urb *iso_urb[ISO_BUF_COUNT];
- int iso_streaming;
+ int iso_stream_count;
+ struct semaphore iso_sem;
u8 av_pes[MAX_AV_PES_LENGTH + 4];
int av_pes_state;
@@ -73,6 +76,7 @@ typedef struct ttusb_dec_s {
dvb_filter_pes2ts_t a_pes2ts;
dvb_filter_pes2ts_t v_pes2ts;
+ struct semaphore pes2ts_sem;
u8 v_pes[16 + MAX_AV_PES_LENGTH];
int v_pes_length;