diff --git a/README.md b/README.md index b01b2eb..04a43cb 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,10 @@ Currently: * RTL2832 with tuner chip FC0013 * MyGica T230 * MyGica (Geniatech) T230C DVB-T/T2/C +* MyGica (Geniatech) T230C2 DVB-T/T2/C +* MyGica (Geniatech) T230A DVB-T/T2/C * MyGica Pad TV Tuner PT360 +* MyGica (Geniatech) Pad TV Tuner PT362 * EVOLVEO XtraTV stick (Some unbranded Android DVB-T sticks) * PCTV AndroiDTV (78e) * Potentially other AF9035 dongles. If your dongle works let me know and I will add it to this list. @@ -78,4 +81,4 @@ If you would like your app to appear here, open a GitHub issue and I will be hap Google Play has very strict rules about apps that can be used to access any TV content. Make sure not to include any TV sceenshots or anything that looks like TV screenshots in your app listing. The description of your app should be very clear that your app does not bundle any content and content is provided by the end user. -Please keep in mind that even if you follow all of the above, your app may still get suspended. The above is just a friendly sugggestion from a developer that has already gone through the worst of this process. This is not official or legal advice. \ No newline at end of file +Please keep in mind that even if you follow all of the above, your app may still get suspended. The above is just a friendly sugggestion from a developer that has already gone through the worst of this process. This is not official or legal advice. diff --git a/app/src/main/java/info/martinmarinov/dvbdriver/DataHandler.java b/app/src/main/java/info/martinmarinov/dvbdriver/DataHandler.java index acedf02..df94b77 100644 --- a/app/src/main/java/info/martinmarinov/dvbdriver/DataHandler.java +++ b/app/src/main/java/info/martinmarinov/dvbdriver/DataHandler.java @@ -81,7 +81,7 @@ public void run() { } } - readB += b.length; + readB += read; } else { try { Thread.sleep(100); diff --git a/drivers/src/main/java/info/martinmarinov/drivers/usb/DvbUsbIds.java b/drivers/src/main/java/info/martinmarinov/drivers/usb/DvbUsbIds.java index 11fad10..ef335d1 100644 --- a/drivers/src/main/java/info/martinmarinov/drivers/usb/DvbUsbIds.java +++ b/drivers/src/main/java/info/martinmarinov/drivers/usb/DvbUsbIds.java @@ -395,7 +395,10 @@ public class DvbUsbIds { public static final int USB_PID_SONY_PLAYTV = 0x0003; public static final int USB_PID_MYGICA_D689 = 0xd811; public static final int USB_PID_MYGICA_T230 = 0xc688; - public static final int USB_PID_GENIATECH_T230C = 0xc689; + public static final int USB_PID_MYGICA_T230C = 0xc689; + public static final int USB_PID_MYGICA_T230C2 = 0xc68a; + public static final int USB_PID_MYGICA_T230C2_LITE = 0xc69a; + public static final int USB_PID_MYGICA_T230A = 0x689a; public static final int USB_PID_ELGATO_EYETV_DIVERSITY = 0x0011; public static final int USB_PID_ELGATO_EYETV_DTT = 0x0021; public static final int USB_PID_ELGATO_EYETV_DTT_2 = 0x003f; diff --git a/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/CxUsbDvbDevice.java b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/CxUsbDvbDevice.java index aa2c04c..c9d4219 100644 --- a/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/CxUsbDvbDevice.java +++ b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/CxUsbDvbDevice.java @@ -73,7 +73,7 @@ public abstract class CxUsbDvbDevice extends AbstractGenericDvbUsbDevice { public static final int SI2168_MP_NOT_USED = 1; public static final int SI2168_MP_A = 2; - public static final int SI2168_MP_B = 3; + public static final int SI2168_MP_B = 3; public static final int SI2168_MP_C = 4; public static final int SI2168_MP_D = 5; @@ -164,6 +164,14 @@ synchronized void cxusb_ctrl_msg(byte cmd, @NonNull byte[] wbuf, int wlen, @Null } } + synchronized void cxusb_gpio_ctrl(int gpio, int value) throws DvbException { + byte[] i = new byte[1]; + cxusb_ctrl_msg(CMD_GPIO_WRITE, new byte[] { (byte)gpio, (byte)value}, 2, i, 1); + if (i[0] != 0x01) { + Log.w(TAG, "gpio_write failed for gpio=0x" + Integer.toHexString(gpio)); + } + } + private void cxusb_gpio_tuner(boolean onoff) throws DvbException { if (gpio_tuner_write_state == onoff) { return; diff --git a/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/CxUsbDvbDeviceCreator.java b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/CxUsbDvbDeviceCreator.java index 4275695..1ce513c 100644 --- a/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/CxUsbDvbDeviceCreator.java +++ b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/CxUsbDvbDeviceCreator.java @@ -32,9 +32,18 @@ import static info.martinmarinov.drivers.tools.SetUtils.setOf; import static info.martinmarinov.drivers.usb.cxusb.MygicaT230.MYGICA_T230; import static info.martinmarinov.drivers.usb.cxusb.MygicaT230C.MYGICA_T230C; +import static info.martinmarinov.drivers.usb.cxusb.MygicaT230A.MYGICA_T230A; +import static info.martinmarinov.drivers.usb.cxusb.MygicaT230C2.MYGICA_T230C2; +import static info.martinmarinov.drivers.usb.cxusb.MygicaT230C2.MYGICA_T230C2_LITE; public class CxUsbDvbDeviceCreator implements DvbUsbDevice.Creator { - private final static Set CXUSB_DEVICES = setOf(MYGICA_T230, MYGICA_T230C); + private final static Set CXUSB_DEVICES = setOf( + MYGICA_T230, + MYGICA_T230C, + MYGICA_T230C2, + MYGICA_T230C2_LITE, + MYGICA_T230A + ); @Override public Set getSupportedDevices() { @@ -43,14 +52,14 @@ public Set getSupportedDevices() { @Override public DvbUsbDevice create(UsbDevice usbDevice, Context context, DeviceFilter filter) throws DvbException { - if (MYGICA_T230C.matches(usbDevice)) { - + if (MYGICA_T230A.equals(filter)) { + return new MygicaT230A(usbDevice, context, filter); + } else if (MYGICA_T230C2.equals(filter) || MYGICA_T230C2_LITE.equals(filter)) { + return new MygicaT230C2(usbDevice, context, filter); + } else if (MYGICA_T230C.equals(filter)) { return new MygicaT230C(usbDevice, context); - } else { - return new MygicaT230(usbDevice, context); - } } } diff --git a/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230.java b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230.java index 63df1cc..959cd2d 100644 --- a/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230.java +++ b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230.java @@ -44,6 +44,10 @@ class MygicaT230 extends CxUsbDvbDevice { super(usbDevice, context, MYGICA_T230); } + MygicaT230(UsbDevice usbDevice, Context context, DeviceFilter deviceFilter) throws DvbException { + super(usbDevice, context, deviceFilter); + } + @Override public String getDebugString() { return MYGICA_NAME; diff --git a/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230A.java b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230A.java new file mode 100644 index 0000000..d830b48 --- /dev/null +++ b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230A.java @@ -0,0 +1,47 @@ +package info.martinmarinov.drivers.usb.cxusb; + +import android.content.Context; +import android.hardware.usb.UsbDevice; + +import info.martinmarinov.drivers.DeviceFilter; +import info.martinmarinov.drivers.DvbException; +import info.martinmarinov.drivers.tools.SleepUtils; +import info.martinmarinov.drivers.usb.DvbUsbIds; + +public class MygicaT230A extends MygicaT230C2 { + public static final String MYGICA_T230A_NAME = "Mygica T230A DVB-T/T2/C"; + static final DeviceFilter MYGICA_T230A = new DeviceFilter(DvbUsbIds.USB_VID_CONEXANT, DvbUsbIds.USB_PID_MYGICA_T230A, MYGICA_T230A_NAME); + + MygicaT230A(UsbDevice usbDevice, Context context, DeviceFilter deviceFilter) throws DvbException { + super(usbDevice, context, deviceFilter); + } + + @Override + public String getDebugString() { + return MYGICA_T230A_NAME; + } + + @Override + synchronized protected void powerControl(boolean onoff) throws DvbException { + if (!onoff) { + cxusb_power_ctrl(false); + cxusb_streaming_ctrl(false); + return; + } + + // dvbsky_identify_state() for USB_PID_MYGICA_T230A + cxusb_gpio_ctrl(0x87, 0); + SleepUtils.mdelay(20); + cxusb_gpio_ctrl(0x86, 1); + cxusb_gpio_ctrl(0x80, 0); + SleepUtils.mdelay(100); + cxusb_gpio_ctrl(0x80, 1); + SleepUtils.mdelay(50); + + SleepUtils.mdelay(128); + cxusb_ctrl_msg(CMD_DIGITAL, new byte[0], 0, new byte[1], 1); + SleepUtils.mdelay(100); + + cxusb_streaming_ctrl(true); + } +} \ No newline at end of file diff --git a/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230C.java b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230C.java index dfc3ecf..e82284f 100644 --- a/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230C.java +++ b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230C.java @@ -18,9 +18,9 @@ /** * @author dmgouriev */ -public class MygicaT230C extends CxUsbDvbDevice { +public class MygicaT230C extends MygicaT230 { public final static String MYGICA_NAME = "Mygica T230C DVB-T/T2/C"; - final static DeviceFilter MYGICA_T230C = new DeviceFilter(DvbUsbIds.USB_VID_CONEXANT, DvbUsbIds.USB_PID_GENIATECH_T230C, MYGICA_NAME); + final static DeviceFilter MYGICA_T230C = new DeviceFilter(DvbUsbIds.USB_VID_CONEXANT, DvbUsbIds.USB_PID_MYGICA_T230C, MYGICA_NAME); private Si2168 frontend; @@ -33,26 +33,6 @@ public String getDebugString() { return MYGICA_NAME; } - @Override - synchronized protected void powerControl(boolean onoff) throws DvbException { - cxusb_d680_dmb_power_ctrl(onoff); - cxusb_streaming_ctrl(onoff); - } - - private void cxusb_d680_dmb_power_ctrl(boolean onoff) throws DvbException { - cxusb_power_ctrl(onoff); - if (!onoff) return; - - SleepUtils.mdelay(128); - cxusb_ctrl_msg(CMD_DIGITAL, new byte[0], 0, new byte[1], 1); - SleepUtils.mdelay(100); - } - - @Override - protected void readConfig() throws DvbException { - // no-op - } - @Override protected DvbFrontend frontendAttatch() throws DvbException { return frontend = new Si2168(this, resources, i2CAdapter, 0x64, SI2168_TS_PARALLEL, true, SI2168_TS_CLK_AUTO_ADAPT, false); @@ -62,11 +42,4 @@ protected DvbFrontend frontendAttatch() throws DvbException { protected DvbTuner tunerAttatch() throws DvbException { return new Si2157(resources, i2CAdapter, frontend.gateControl(), 0x60, false, SI2157_CHIPTYPE_SI2141); } - - @Override - protected void init() throws DvbException { - // no-op - } - - } diff --git a/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230C2.java b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230C2.java new file mode 100644 index 0000000..c967a21 --- /dev/null +++ b/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230C2.java @@ -0,0 +1,42 @@ +package info.martinmarinov.drivers.usb.cxusb; + +import static info.martinmarinov.drivers.usb.silabs.Si2157.Type.SI2157_CHIPTYPE_SI2141; + +import android.content.Context; +import android.hardware.usb.UsbDevice; + +import info.martinmarinov.drivers.DeviceFilter; +import info.martinmarinov.drivers.DvbException; +import info.martinmarinov.drivers.usb.DvbFrontend; +import info.martinmarinov.drivers.usb.DvbTuner; +import info.martinmarinov.drivers.usb.DvbUsbIds; +import info.martinmarinov.drivers.usb.silabs.Si2157; +import info.martinmarinov.drivers.usb.silabs.Si2168; + +public class MygicaT230C2 extends MygicaT230 { + public final static String MYGICA_NAME = "Mygica T230C2 DVB-T/T2/C"; + final static DeviceFilter MYGICA_T230C2 = new DeviceFilter(DvbUsbIds.USB_VID_CONEXANT, DvbUsbIds.USB_PID_MYGICA_T230C2, MYGICA_NAME); + final static DeviceFilter MYGICA_T230C2_LITE = new DeviceFilter(DvbUsbIds.USB_VID_CONEXANT, DvbUsbIds.USB_PID_MYGICA_T230C2_LITE, MYGICA_NAME); + + private Si2168 frontend; + + MygicaT230C2(UsbDevice usbDevice, Context context, DeviceFilter deviceFilter) throws DvbException { + super(usbDevice, context, deviceFilter); + } + + @Override + public String getDebugString() { + return MYGICA_NAME; + } + + @Override + protected DvbFrontend frontendAttatch() throws DvbException { + return frontend = new Si2168(this, resources, i2CAdapter, 0x64, SI2168_TS_PARALLEL, true, SI2168_TS_CLK_MANUAL, false); + } + + @Override + protected DvbTuner tunerAttatch() throws DvbException { + return new Si2157(resources, i2CAdapter, frontend.gateControl(), 0x60, false, SI2157_CHIPTYPE_SI2141); + } + +} diff --git a/drivers/src/main/java/info/martinmarinov/drivers/usb/silabs/Si2168.java b/drivers/src/main/java/info/martinmarinov/drivers/usb/silabs/Si2168.java index 5f5f8a2..0c09f68 100644 --- a/drivers/src/main/java/info/martinmarinov/drivers/usb/silabs/Si2168.java +++ b/drivers/src/main/java/info/martinmarinov/drivers/usb/silabs/Si2168.java @@ -32,6 +32,7 @@ import static info.martinmarinov.drivers.DvbStatus.FE_HAS_SYNC; import static info.martinmarinov.drivers.DvbStatus.FE_HAS_VITERBI; import static info.martinmarinov.drivers.usb.cxusb.CxUsbDvbDevice.SI2168_ARGLEN; +import static info.martinmarinov.drivers.usb.cxusb.CxUsbDvbDevice.SI2168_TS_CLK_MANUAL; import android.content.res.Resources; import android.util.Log; @@ -99,6 +100,10 @@ private void si2168_cmd_execute_wr(byte[] wargs, int wlen) throws DvbException { si2168_cmd_execute(wargs, wlen, 0); } + private boolean useUpstreamTsClockPolarity() { + return chip == Si2168Data.Si2168Chip.SI2168_CHIP_ID_D60 || (((version >> 24) & 0xFF) == 'D'); + } + private synchronized @NonNull byte[] si2168_cmd_execute(@NonNull byte[] wargs, int wlen, int rlen) throws DvbException { if (wlen > 0 && wlen == wargs.length) { i2c.send(addr, wargs, wlen); @@ -237,6 +242,12 @@ public synchronized void init(DvbTuner tuner) throws DvbException { version = (((fwVerRaw[9] & 0xFF) + '@') << 24) | (((fwVerRaw[6] & 0xFF) - '0') << 16) | (((fwVerRaw[7] & 0xFF) - '0') << 8) | (fwVerRaw[8] & 0xFF); Log.d(TAG, "firmware version: "+((char) ((version >> 24) & 0xff))+" "+((version >> 16) & 0xff)+"."+((version >> 8) & 0xff)+"."+(version & 0xff)); + if (ts_clock_mode == SI2168_TS_CLK_MANUAL) { + /* set ts freq to 10Mhz + * for CLK_MANUAL, follow upstream kernel ordering: set TS freq before TS mode. */ + si2168_cmd_execute(new byte[] {(byte) 0x14, (byte) 0x00, (byte) 0x0d, (byte) 0x10, (byte) 0xe8, (byte) 0x03}, 6, 4); + } + /* set ts mode */ byte[] args = new byte[] {(byte) 0x14, (byte) 0x00, (byte) 0x01, (byte) 0x10, (byte) 0x00, (byte) 0x00}; args[4] |= ts_mode; @@ -246,8 +257,11 @@ public synchronized void init(DvbTuner tuner) throws DvbException { } si2168_cmd_execute(args, 6, 4); - /* set ts freq to 10Mhz*/ - si2168_cmd_execute(new byte[] {(byte) 0x14, (byte) 0x00, (byte) 0x0d, (byte) 0x10, (byte) 0xe8, (byte) 0x03}, 6, 4); + if (ts_clock_mode != SI2168_TS_CLK_MANUAL) { + /* set ts freq to 10Mhz + * preserve legacy non-MANUAL behavior until AUTO_* hardware is verified. */ + si2168_cmd_execute(new byte[] {(byte) 0x14, (byte) 0x00, (byte) 0x0d, (byte) 0x10, (byte) 0xe8, (byte) 0x03}, 6, 4); + } warm = true; } @@ -361,7 +375,12 @@ public synchronized void setParams(long frequency, long bandwidthHz, @NonNull De si2168_cmd_execute(new byte[] {(byte) 0x14, (byte) 0x00, (byte) 0x09, (byte) 0x10, (byte) 0xe3, (byte) (0x08 | (ts_clock_inv ? 0x00 : 0x10))}, 6, 4); byte[] cmd = new byte[] {(byte) 0x14, (byte) 0x00, (byte) 0x08, (byte) 0x10, (byte) 0xd7, (byte) 0x05}; - cmd[5] |= ts_clock_inv ? 0xd7 : 0xcf; + if (useUpstreamTsClockPolarity()) { + cmd[5] |= ts_clock_inv ? 0x00 : 0x10; + } else { + // Keep legacy behavior for older non-D devices that are long field-tested. + cmd[5] |= ts_clock_inv ? 0xd7 : 0xcf; + } si2168_cmd_execute(cmd, 6, 4); si2168_cmd_execute(new byte[] {(byte) 0x14, (byte) 0x00, (byte) 0x01, (byte) 0x12, (byte) 0x00, (byte) 0x00}, 6, 4); diff --git a/dvbservice/src/main/res/xml/device_filter.xml b/dvbservice/src/main/res/xml/device_filter.xml index 25a67d3..8d8b015 100644 --- a/dvbservice/src/main/res/xml/device_filter.xml +++ b/dvbservice/src/main/res/xml/device_filter.xml @@ -28,6 +28,9 @@ + + +