---
 drivers/media/usb/dvb-usb/gp8psk-fe.c | 111 +++++++++++++++++++++++++++++++++-
 drivers/media/usb/dvb-usb/gp8psk.h    |   1 +
 include/uapi/linux/dvb/frontend.h     |   1 +
 3 files changed, 111 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/dvb-usb/gp8psk-fe.c 
b/drivers/media/usb/dvb-usb/gp8psk-fe.c
index fcdf82c..4e61c48 100644
--- a/drivers/media/usb/dvb-usb/gp8psk-fe.c
+++ b/drivers/media/usb/dvb-usb/gp8psk-fe.c
@@ -53,7 +53,42 @@ static int gp8psk_fe_update_status(struct gp8psk_fe_state 
*st)
 
 static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
 {
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct gp8psk_fe_state *st = fe->demodulator_priv;
+
+       u8 buf[32];
+       int frequency;
+       int carrier_error;
+       int carrier_offset;
+       int rate_error;
+       int rate_offset;
+       int symbol_rate;
+
+       int fe_gp8psk_system_return[] = {
+               SYS_DVBS,
+               SYS_TURBO,
+               SYS_TURBO,
+               SYS_TURBO,
+               SYS_DCII_C_QPSK,
+               SYS_DCII_I_QPSK,
+               SYS_DCII_Q_QPSK,
+               SYS_DCII_C_OQPSK,
+               SYS_DSS,
+               SYS_UNDEFINED
+       };
+
+       int fe_gp8psk_modulation_return[] = {
+               QPSK,
+               QPSK,
+               PSK_8,
+               QAM_16,
+               QPSK,
+               QPSK,
+               QPSK,
+               QPSK,
+               QPSK,
+       };
+
        gp8psk_fe_update_status(st);
 
        if (st->lock)
@@ -61,10 +96,82 @@ static int gp8psk_fe_read_status(struct dvb_frontend* fe, 
fe_status_t *status)
        else
                *status = 0;
 
-       if (*status & FE_HAS_LOCK)
+       if (*status & FE_HAS_LOCK) {
+               gp8psk_usb_in_op(st->d, GET_SIGNAL_STAT, 0, 0, buf, 32);
+               frequency               = ((buf[11] << 24) + (buf[10] << 16) + 
(buf[9] << 8) + buf[8]) / 1000;
+               carrier_error   = ((buf[15] << 24) + (buf[14] << 16) + (buf[13] 
<< 8) + buf[12]) / 1000;
+               carrier_offset  =  (buf[19] << 24) + (buf[18] << 16) + (buf[17] 
<< 8) + buf[16];
+               rate_error              =  (buf[23] << 24) + (buf[22] << 16) + 
(buf[21] << 8) + buf[20];
+               rate_offset             =  (buf[27] << 24) + (buf[26] << 16) + 
(buf[25] << 8) + buf[24];
+               symbol_rate             =  (buf[31] << 24) + (buf[30] << 16) + 
(buf[29] << 8) + buf[28];
+
+               c->frequency            = frequency - carrier_error;
+               c->symbol_rate          = symbol_rate + rate_error;
+
+               switch (c->delivery_system) {
+               case SYS_DSS:
+               case SYS_DVBS:
+                       c->delivery_system      = 
fe_gp8psk_system_return[buf[1]];
+                       c->modulation           = 
fe_gp8psk_modulation_return[buf[1]];
+                       switch (buf[2]) {
+                       case 0:  c->fec_inner = FEC_1_2;  break;
+                       case 1:  c->fec_inner = FEC_2_3;  break;
+                       case 2:  c->fec_inner = FEC_3_4;  break;
+                       case 3:  c->fec_inner = FEC_5_6;  break;
+                       case 4:  c->fec_inner = FEC_6_7;  break;
+                       case 5:  c->fec_inner = FEC_7_8;  break;
+                       default: c->fec_inner = FEC_AUTO; break;
+                       }
+                       break;
+               case SYS_TURBO:
+                       c->delivery_system      = 
fe_gp8psk_system_return[buf[1]];
+                       c->modulation           = 
fe_gp8psk_modulation_return[buf[1]];
+                       if (c->modulation == QPSK) {
+                               switch (buf[2]) {
+                               case 0:  c->fec_inner = FEC_7_8;  break;
+                               case 1:  c->fec_inner = FEC_1_2;  break;
+                               case 2:  c->fec_inner = FEC_3_4;  break;
+                               case 3:  c->fec_inner = FEC_2_3;  break;
+                               case 4:  c->fec_inner = FEC_5_6;  break;
+                               default: c->fec_inner = FEC_AUTO; break;
+                               }
+                       } else {
+                               switch (buf[2]) {
+                               case 0:  c->fec_inner = FEC_2_3;  break;
+                               case 1:  c->fec_inner = FEC_3_4;  break;
+                               case 2:  c->fec_inner = FEC_3_4;  break;
+                               case 3:  c->fec_inner = FEC_5_6;  break;
+                               case 4:  c->fec_inner = FEC_8_9;  break;
+                               default: c->fec_inner = FEC_AUTO; break;
+                               }
+                       }
+                       break;
+               case SYS_DCII_C_QPSK:
+               case SYS_DCII_I_QPSK:
+               case SYS_DCII_Q_QPSK:
+               case SYS_DCII_C_OQPSK:
+                       c->modulation           = 
fe_gp8psk_modulation_return[buf[1]];
+                       switch (buf[2]) {
+                       case 0:  c->fec_inner = FEC_5_11; break;
+                       case 1:  c->fec_inner = FEC_1_2;  break;
+                       case 2:  c->fec_inner = FEC_3_5;  break;
+                       case 3:  c->fec_inner = FEC_2_3;  break;
+                       case 4:  c->fec_inner = FEC_3_4;  break;
+                       case 5:  c->fec_inner = FEC_4_5;  break;
+                       case 6:  c->fec_inner = FEC_5_6;  break;
+                       case 7:  c->fec_inner = FEC_7_8;  break;
+                       default: c->fec_inner = FEC_AUTO; break;
+                       }
+                       break;
+               default:
+                       c->fec_inner = FEC_AUTO;
+                       break;
+               }
+
                st->status_check_interval = 1000;
-       else
+       } else {
                st->status_check_interval = 100;
+       }
        return 0;
 }
 
diff --git a/drivers/media/usb/dvb-usb/gp8psk.h 
b/drivers/media/usb/dvb-usb/gp8psk.h
index ff6bb3c..dbab86d 100644
--- a/drivers/media/usb/dvb-usb/gp8psk.h
+++ b/drivers/media/usb/dvb-usb/gp8psk.h
@@ -52,6 +52,7 @@ extern int dvb_usb_gp8psk_debug;
 #define GET_SERIAL_NUMBER               0x93    /* in */
 #define USE_EXTRA_VOLT                  0x94
 #define GET_FPGA_VERS                  0x95
+#define GET_SIGNAL_STAT                        0x9A
 #define GET_BER_RATE                   0x9B
 #define CW3K_INIT                      0x9d
 
diff --git a/include/uapi/linux/dvb/frontend.h 
b/include/uapi/linux/dvb/frontend.h
index ada08a8..f123671 100644
--- a/include/uapi/linux/dvb/frontend.h
+++ b/include/uapi/linux/dvb/frontend.h
@@ -165,6 +165,7 @@ typedef enum fe_code_rate {
        FEC_3_5,
        FEC_9_10,
        FEC_2_5,
+       FEC_5_11,
 } fe_code_rate_t;
 
 
-- 
1.8.1.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to