summaryrefslogtreecommitdiff
path: root/linux/drivers/media
diff options
context:
space:
mode:
authorMike Isely <isely@pobox.com>2006-03-04 14:01:08 -0600
committerMike Isely <isely@pobox.com>2006-03-04 14:01:08 -0600
commit26a2eb754c7d2b87b75154bf1417c89a32bf390f (patch)
tree4808cf565cd539a80fff83b42e4b13eec33f2c68 /linux/drivers/media
parent5515ed4ac17ca06de145302b8888b9adb09ba32c (diff)
downloadmediapointer-dvb-s2-26a2eb754c7d2b87b75154bf1417c89a32bf390f.tar.gz
mediapointer-dvb-s2-26a2eb754c7d2b87b75154bf1417c89a32bf390f.tar.bz2
Implement new method in pvrusb2 to detect the FX2 firmware
From: Mike Isely <isely@pobox.com> The pvrusb2 driver as part of its initialization might have to load the FX2's firmware image. We must only do this when it is actually needed. The previous method just detected this requirement by noticing something unusual about the USB configuration of the device. Unfortunately with newer PVR USB2 devices this method no longer works. What we do now is also attempt a simple non-destructive endpoint 1 transaction; failure of that transfer will indicate a need to load the firmware. Signed-off-by: Mike Isely <isely@pobox.com>
Diffstat (limited to 'linux/drivers/media')
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c132
-rw-r--r--linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h13
2 files changed, 112 insertions, 33 deletions
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 1ee2fcda4..31fdff2f5 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -1003,11 +1003,55 @@ static unsigned int get_default_error_tolerance(struct pvr2_hdw *hdw)
}
+static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw)
+{
+ /* Try a harmless request to fetch the eeprom's address over
+ endpoint 1. See what happens. Only the full FX2 image can
+ respond to this. If this probe fails then likely the FX2
+ firmware needs be loaded. */
+ int result;
+ LOCK_TAKE(hdw->ctl_lock); do {
+ hdw->cmd_buffer[0] = 0xeb;
+ result = pvr2_send_request_ex(hdw,HZ*1,!0,
+ hdw->cmd_buffer,1,
+ hdw->cmd_buffer,1);
+ if (result < 0) break;
+ } while(0); LOCK_GIVE(hdw->ctl_lock);
+ if (result) {
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Probe of device endpoint 1 result status %d",
+ result);
+ } else {
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Probe of device endpoint 1 succeeded");
+ }
+ return result == 0;
+}
+
+
static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
{
int ret;
unsigned int idx;
- if (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints == 0) {
+ int reloadFl = 0;
+ if (!reloadFl) {
+ reloadFl = (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints
+ == 0);
+ if (reloadFl) {
+ pvr2_trace(PVR2_TRACE_INIT,
+ "USB endpoint config looks strange"
+ "; possibly firmware needs to be loaded");
+ }
+ }
+ if (!reloadFl) {
+ reloadFl = !pvr2_hdw_check_firmware(hdw);
+ if (reloadFl) {
+ pvr2_trace(PVR2_TRACE_INIT,
+ "Check for FX2 firmware failed"
+ "; possibly firmware needs to be loaded");
+ }
+ }
+ if (reloadFl) {
if (pvr2_upload_firmware1(hdw) != 0) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"Failure uploading firmware1");
@@ -1921,31 +1965,33 @@ static void pvr2_ctl_timeout(unsigned long data)
}
-int pvr2_send_request(struct pvr2_hdw *hdw,
- void *write_data,unsigned int write_len,
- void *read_data,unsigned int read_len)
+int pvr2_send_request_ex(struct pvr2_hdw *hdw,
+ unsigned int timeout,int probe_fl,
+ void *write_data,unsigned int write_len,
+ void *read_data,unsigned int read_len)
{
unsigned int idx;
- int status;
+ int status = 0;
struct timer_list timer;
if (!hdw->ctl_lock_held) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"Attempted to execute control transfer"
" without lock!!");
- status = -EINVAL;
- goto done;
+ return -EDEADLK;
}
- if (!hdw->flag_ok) {
+ if ((!hdw->flag_ok) && !probe_fl) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"Attempted to execute control transfer"
" when device not ok");
return -EIO;
}
if (!(hdw->ctl_read_urb && hdw->ctl_write_urb)) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Attempted to execute control transfer"
- " when USB is disconnected");
- return -EIO;
+ if (!probe_fl) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Attempted to execute control transfer"
+ " when USB is disconnected");
+ }
+ return -ENOTTY;
}
/* Ensure that we have sane parameters */
@@ -1989,7 +2035,7 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
hdw->ctl_write_pend_flag = 0;
hdw->ctl_read_pend_flag = 0;
init_timer(&timer);
- timer.expires = jiffies + HZ*4;
+ timer.expires = jiffies + timeout;
timer.data = (unsigned long)hdw;
timer.function = pvr2_ctl_timeout;
@@ -2020,6 +2066,7 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
"Failed to submit write-control"
" URB status=%d",status);
hdw->ctl_write_pend_flag = 0;
+ goto done;
}
}
@@ -2046,6 +2093,7 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
"Failed to submit read-control"
" URB status=%d",status);
hdw->ctl_read_pend_flag = 0;
+ goto done;
}
}
@@ -2067,8 +2115,10 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
if (hdw->ctl_timeout_flag) {
status = -ETIMEDOUT;
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Timed out control-write");
+ if (!probe_fl) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "Timed out control-write");
+ }
goto done;
}
@@ -2081,19 +2131,24 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
/* USB subsystem is reporting some kind of failure
on the write */
status = hdw->ctl_write_urb->status;
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "control-write URB failure, status=%d",
- status);
+ if (!probe_fl) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "control-write URB failure,"
+ " status=%d",
+ status);
+ }
goto done;
}
if (hdw->ctl_write_urb->actual_length < write_len) {
/* Failed to write enough data */
status = -EIO;
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "control-write URB short,"
- " expected=%d got=%d",
- write_len,
- hdw->ctl_write_urb->actual_length);
+ if (!probe_fl) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "control-write URB short,"
+ " expected=%d got=%d",
+ write_len,
+ hdw->ctl_write_urb->actual_length);
+ }
goto done;
}
}
@@ -2106,18 +2161,24 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
/* USB subsystem is reporting some kind of failure
on the read */
status = hdw->ctl_read_urb->status;
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "control-read URB failure, status=%d",
- status);
+ if (!probe_fl) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "control-read URB failure,"
+ " status=%d",
+ status);
+ }
goto done;
}
if (hdw->ctl_read_urb->actual_length < read_len) {
/* Failed to read enough data */
status = -EIO;
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "control-read URB short,"
- " expected=%d got=%d",
- read_len,hdw->ctl_read_urb->actual_length);
+ if (!probe_fl) {
+ pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+ "control-read URB short,"
+ " expected=%d got=%d",
+ read_len,
+ hdw->ctl_read_urb->actual_length);
+ }
goto done;
}
/* Transfer retrieved data out from internal buffer */
@@ -2129,13 +2190,22 @@ int pvr2_send_request(struct pvr2_hdw *hdw,
done:
hdw->cmd_debug_state = 0;
- if (status < 0) {
+ if ((status < 0) && (!probe_fl)) {
pvr2_hdw_render_useless_unlocked(hdw);
}
return status;
}
+int pvr2_send_request(struct pvr2_hdw *hdw,
+ void *write_data,unsigned int write_len,
+ void *read_data,unsigned int read_len)
+{
+ return pvr2_send_request_ex(hdw,HZ*4,0,
+ write_data,write_len,
+ read_data,read_len);
+}
+
int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
{
int ret;
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index 2f9c4cb6d..cfde4a0c5 100644
--- a/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/linux/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -322,8 +322,17 @@ void pvr2_reset_ctl_endpoints(struct pvr2_hdw *hdw);
/* Issue a command and get a response from the device. LOTS of higher
level stuff is built on this. */
-int pvr2_send_request(struct pvr2_hdw *, void *, unsigned int,
- void *, unsigned int);
+int pvr2_send_request(struct pvr2_hdw *,
+ void *write_ptr,unsigned int write_len,
+ void *read_ptr,unsigned int read_len);
+
+/* Issue a command and get a response from the device. This extended
+ version includes a probe flag (which if set means that device errors
+ should not be logged or treated as fatal) and a timeout in jiffies.
+ This can be used to non-lethally probe the health of endpoint 1. */
+int pvr2_send_request_ex(struct pvr2_hdw *,unsigned int timeout,int probe_fl,
+ void *write_ptr,unsigned int write_len,
+ void *read_ptr,unsigned int read_len);
/* Slightly higher level device communication functions. */
int pvr2_write_register(struct pvr2_hdw *, u16, u32);