9 |
10 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Android DVB-T Driver
4 |
5 | This driver provides a simple TCP based API that allows
6 | controlling USB DVB-T/DVB-T2 tuners on Android. It gives other apps access to
7 | the raw DVB MPEG-2 TS stream.
8 |
9 | The driver is a simplified user space port of a subset of
10 | the V4L2 Linux kernel drivers. Under the hood it uses Android USB Host API
11 | with a small helper library that allows fast kernel controlled USB bulk transfers.
12 |
13 | # Download
14 |
15 | * [Download DVB-T Driver on Google Play](https://play.google.com/store/apps/details?id=info.martinmarinov.dvbdriver)
16 | * [Download DVB-T Driver on Amazon](https://www.amazon.com/gp/mas/dl/android?p=info.martinmarinov.dvbdriver)
17 | * Download latest pre-compiled APK from GitHub: [app-release.apk](https://github.com/martinmarinov/AndroidDvbDriver/releases/latest)
18 |
19 | # Usage
20 |
21 | The driver has an Activity that demonstrates direct connection to hardware
22 | and allows dumping the raw DVB-T/T2 transport stream to a file.
23 |
24 | A socket interface is built on top of that functionality to allow the driver
25 | to be used by third party apps over TCP. If you want to use the driver via the
26 | exposed TCP interface, you have to do the following steps from your own app:
27 |
28 | 1. Launch an android intent
29 | ```java
30 | startActivityForResult(new Intent(Intent.ACTION_VIEW)
31 | .setData(new Uri.Builder().scheme("dtvdriver").build()), SOME_CODE);
32 | ```
33 | 1. If the activity returns successfully, you will receive two TCP port numbers to bind to.
34 | One of them is the control port where you can send commands and receive responses.
35 | The other port will provide the raw TS stream.
36 | 1. You can then start sending commands over the control port and process the TS stream.
37 |
38 | For actual details on the protocol, take a look at the `dvbservice` module. There
39 | are no official docs provided, if you would like to volunteer to write one get in touch with me.
40 |
41 | There is also a handy "debug" mode that allows the driver to play the pre-recorded TS dumps
42 | as if they are coming from a real device. This mode is extremely useful during development.
43 |
44 | Note that this driver does not provide channel/programme scanning/playback capabilities or any transport stream processing.
45 | If you would like to write an app for DVB playback, you have to implement all of these yourself.
46 |
47 | # Auto start
48 |
49 | The driver will emmit `info.martinmarinov.dvbdriver.DVB_DEVICE_ATTACHED` action when a compatible USB tuner has
50 | been connected to the Android device. You can use this intent to launch your application automatically.
51 |
52 | # Supported hardware
53 |
54 | Currently:
55 | * RTL2832 with tuner chip R820t
56 | * RTL2832 with tuner chip E4000
57 | * RTL2832 with tuner chip R828D (DVB-T2 support for MN88473, MN88472, CXD2837ER & CXD2841ER devices)
58 | * RTL2832 with tuner chip FC0012
59 | * RTL2832 with tuner chip FC0013
60 | * MyGica T230
61 | * MyGica (Geniatech) T230C DVB-T/T2/C
62 | * MyGica Pad TV Tuner PT360
63 | * EVOLVEO XtraTV stick (Some unbranded Android DVB-T sticks)
64 | * PCTV AndroiDTV (78e)
65 | * Potentially other AF9035 dongles. If your dongle works let me know and I will add it to this list.
66 |
67 | The driver is not limited to these devices only. If a device has a Linux kernel driver, then it probably could be ported.
68 | If you have ported a driver for a device, get in touch with me so we can add it to the main driver.
69 |
70 | # Apps that use the driver
71 |
72 | * [Aerial TV](http://aerialtv.eu/)
73 | * [DVBTTelevizor](https://play.google.com/store/apps/details?id=net.petrjanousek.DVBTTelevizor)
74 |
75 | If you would like your app to appear here, open a GitHub issue and I will be happy to add it!
76 |
77 | # Important advice
78 |
79 | 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.
80 |
81 | 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.
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/app/app-release.apk
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | plugins {
22 | id 'com.android.application'
23 | }
24 |
25 | android {
26 | namespace 'info.martinmarinov.dvbdriver'
27 | compileSdk 34
28 |
29 | defaultConfig {
30 | applicationId "info.martinmarinov.dvbdriver"
31 | minSdk 21
32 | targetSdk 34
33 | versionCode 29
34 | versionName "1.43"
35 |
36 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
37 | }
38 |
39 | buildTypes {
40 | release {
41 | minifyEnabled false
42 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
43 | }
44 | }
45 | compileOptions {
46 | sourceCompatibility JavaVersion.VERSION_1_8
47 | targetCompatibility JavaVersion.VERSION_1_8
48 | }
49 | }
50 |
51 | dependencies {
52 | implementation 'androidx.appcompat:appcompat:1.5.1'
53 | implementation 'com.google.android.material:material:1.7.0'
54 | testImplementation 'junit:junit:4.13.2'
55 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
56 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
57 | implementation project(path: ':drivers')
58 | implementation project(path: ':dvbservice')
59 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/martinmarinov/Android/Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
23 |
24 |
25 |
31 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/java/info/martinmarinov/dvbdriver/DataHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbdriver;
22 |
23 | import java.io.File;
24 | import java.io.FileNotFoundException;
25 | import java.io.FileOutputStream;
26 | import java.io.IOException;
27 | import java.io.InputStream;
28 | import java.util.Date;
29 |
30 | import info.martinmarinov.dvbservice.tools.TsDumpFileUtils;
31 |
32 | class DataHandler extends Thread {
33 | private final DvbFrontendActivity dvbFrontendActivity;
34 | private final Object recordingLock = new Object();
35 | private final InputStream is;
36 |
37 | private boolean recording = false;
38 | private File file;
39 | private FileOutputStream fos;
40 | private int recordedSize = 0;
41 |
42 | private long readB = 0;
43 | private long currFreq;
44 | private long currBandwidth;
45 |
46 | DataHandler(DvbFrontendActivity dvbFrontendActivity, InputStream is) {
47 | this.dvbFrontendActivity = dvbFrontendActivity;
48 | this.is = is;
49 | }
50 |
51 | void reset() {
52 | readB = 0;
53 | }
54 |
55 | void setFreqAndBandwidth(long freq, long bandwidth) {
56 | this.currFreq = freq;
57 | this.currBandwidth = bandwidth;
58 | }
59 |
60 | @Override
61 | public void interrupt() {
62 | super.interrupt();
63 | try {
64 | is.close();
65 | } catch (IOException ignored) {}
66 | }
67 |
68 | @Override
69 | public void run() {
70 | try {
71 | long nextUpdate = System.currentTimeMillis() + 1_000;
72 | byte[] b = new byte[1024];
73 | while (!isInterrupted()) {
74 |
75 | int read = is.read(b);
76 | if (read > 0) {
77 | synchronized (recordingLock) {
78 | if (recording) {
79 | fos.write(b, 0, read);
80 | recordedSize += read;
81 | }
82 | }
83 |
84 | readB += b.length;
85 | } else {
86 | try {
87 | Thread.sleep(100);
88 | } catch (InterruptedException e) {
89 | interrupt();
90 | }
91 | continue;
92 | }
93 |
94 | if (System.currentTimeMillis() > nextUpdate) {
95 | nextUpdate = System.currentTimeMillis() + 1_000;
96 | if (recording) {
97 | dvbFrontendActivity.announceRecorded(file, recordedSize);
98 | } else {
99 | dvbFrontendActivity.announceBitRate(readB);
100 | }
101 | readB = 0;
102 | }
103 | }
104 | } catch (IOException e) {
105 | if (!isInterrupted()) {
106 | throw new RuntimeException(e);
107 | }
108 | } finally {
109 | try {
110 | if (fos != null) fos.close();
111 | } catch (IOException ignored) {
112 | }
113 | }
114 | }
115 |
116 | boolean isRecording() {
117 | return recording;
118 | }
119 |
120 | void startRecording() throws FileNotFoundException {
121 | synchronized (recordingLock) {
122 | file = TsDumpFileUtils.getFor(dvbFrontendActivity.getApplicationContext(), currFreq, currBandwidth, new Date());
123 | fos = new FileOutputStream(file, false);
124 | recordedSize = 0;
125 | recording = true;
126 | }
127 | }
128 |
129 | void stopRecording() throws IOException {
130 | synchronized (recordingLock) {
131 | recording = false;
132 | fos.close();
133 | fos = null;
134 | file = null;
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/app/src/main/java/info/martinmarinov/dvbdriver/GplLicenseActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbdriver;
22 |
23 | import android.os.Bundle;
24 | import android.app.Activity;
25 | import android.view.View;
26 | import android.widget.TextView;
27 |
28 | import java.io.Closeable;
29 | import java.io.IOException;
30 | import java.io.InputStream;
31 | import java.util.Scanner;
32 |
33 | public class GplLicenseActivity extends Activity {
34 |
35 | @Override
36 | protected void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | setContentView(R.layout.activity_gpl_license);
39 |
40 | findViewById(R.id.license_btnOk).setOnClickListener(new View.OnClickListener() {
41 | @Override
42 | public void onClick(View v) {
43 | finish();
44 | }
45 | });
46 |
47 | ((TextView) findViewById(R.id.license_Txt)).setText(readToText(getResources().openRawResource(R.raw.copying)));
48 | }
49 |
50 | private String readToText(InputStream inputStream) {
51 | try {
52 | Scanner s = new Scanner(inputStream, "UTF-8").useDelimiter("\\A");
53 | return s.next();
54 | } finally {
55 | closeOrDie(inputStream);
56 | }
57 | }
58 |
59 | private static void closeOrDie(Closeable c) {
60 | try {
61 | c.close();
62 | } catch (IOException e) {
63 | throw new RuntimeException(e);
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/info/martinmarinov/dvbdriver/WelcomeActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbdriver;
22 |
23 | import android.content.Intent;
24 | import android.net.Uri;
25 | import android.os.Bundle;
26 | import android.app.Activity;
27 | import android.view.View;
28 |
29 | public class WelcomeActivity extends Activity {
30 | private final static Uri SOURCE_URL = Uri.parse("https://github.com/signalwareltd/AndroidDvbDriver");
31 |
32 | @Override
33 | protected void onCreate(Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.activity_welcome);
36 |
37 | findViewById(R.id.btn_close).setOnClickListener(v -> finish());
38 |
39 | findViewById(R.id.btn_advanced_mode).setOnClickListener(v -> startActivity(new Intent(WelcomeActivity.this, DvbFrontendActivity.class)));
40 |
41 | findViewById(R.id.btn_source_code).setOnClickListener(v -> startActivity(new Intent(Intent.ACTION_VIEW, SOURCE_URL)));
42 |
43 | findViewById(R.id.btn_license).setOnClickListener(v -> startActivity(new Intent(WelcomeActivity.this, GplLicenseActivity.class)));
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_gpl_license.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
29 |
30 |
34 |
35 |
38 |
39 |
45 |
46 |
47 |
48 |
49 |
50 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_welcome.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
29 |
30 |
38 |
42 |
43 |
44 |
49 |
50 |
55 |
56 |
61 |
62 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-nb/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | DVB-T Driver
3 | Ingen enheter funnet
4 | Start
5 | Stopp
6 | Still inn
7 | 506
8 | Maskinvaren er klar
9 | Funnet signal
10 | Mottar signal
11 | Synkronisert
12 | Låst fast
13 | - - - - -
14 | Ingen unntak
15 | Signalstyrke
16 | SNR: %1$d
17 | Kvalitet
18 | Droppet av USB: %1$d FPS
19 | Frekvens: %1$.2f MB/s
20 | Tar opp til %1$s (%2$.2f MB)
21 | Ingen enheter er åpne
22 | Ta opp en TS-fil
23 | Stopp opptaket
24 | MHz
25 |
26 | Takk for at du installerte DVB-T Driver. Vennligst bemerk at denne appen ikke er ment å brukes manuelt.
27 | Den brukes automatisk av andre apper for å styre USB DVB-T-enheter som f.eks. RTL2832U.
28 | Du kan nå lukke dette vinduet og starte opp din favoritt-TV-app som benytter seg av DVB-T Driver.
29 |
30 | Diagnostisering (Avansert modus)
31 | Lisens
32 | Kildekode
33 | Lukk
34 | Ingen E-postapper ble funnet. Kan ikke sende E-post.
35 | Meld i fra
36 | driver@aerialtv.eu
37 | DVB-T-driverkrasjrapportering
38 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
25 | 64dp
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
23 |
24 | 8
25 | 7
26 | 6
27 |
28 |
29 | DVBT
30 | DVBT2
31 | DVBC
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
23 | #3F51B5
24 | #303F9F
25 | #FF4081
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 | 16dp
24 | 16dp
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 | DVB-T Driver
23 | No devices found
24 | Start
25 | Stop
26 | Tune
27 | 506
28 | Hardware ready
29 | Has signal
30 | Carrier
31 | Sync
32 | Lock
33 | - - - - -
34 | No exception
35 | Signal strength
36 | SNR: %1$d
37 | Quality
38 | Dropped USB: %1$d FPS
39 | Rate %1$.2f MB/s
40 | Recording to %1$s (%2$.2f MB)
41 | No device open
42 | Record TS
43 | Stop recording
44 | MHz
45 |
46 | Thank you for installing DVB-T Driver. Please note that this app is not meant to be used manually.
47 | It is automatically used by other apps in order to control USB DVB-T devices such as the RTL2832U.
48 | You can now close this window and launch your favourite TV app that uses DVB-T Driver.
49 |
50 | Diagnostic (Advanced mode)
51 | License
52 | Source code
53 | Close
54 | No email app found. Cannot send email.
55 | Report
56 | driver@aerialtv.eu
57 | DVB-T driver crash report
58 |
69 |
70 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 |
27 |
28 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
22 | plugins {
23 | id 'com.android.application' version '8.5.2' apply false
24 | id 'com.android.library' version '8.5.2' apply false
25 | }
--------------------------------------------------------------------------------
/drivers/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/drivers/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | plugins {
22 | id 'com.android.library'
23 | }
24 |
25 | android {
26 | namespace 'info.martinmarinov.drivers'
27 | compileSdk 34
28 |
29 | defaultConfig {
30 | minSdk 21
31 | targetSdk 34
32 |
33 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
34 | consumerProguardFiles "consumer-rules.pro"
35 | }
36 |
37 | buildTypes {
38 | release {
39 | minifyEnabled false
40 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
41 | }
42 | }
43 | compileOptions {
44 | sourceCompatibility JavaVersion.VERSION_1_8
45 | targetCompatibility JavaVersion.VERSION_1_8
46 | }
47 | }
48 |
49 | dependencies {
50 | implementation 'androidx.appcompat:appcompat:1.5.1'
51 | implementation 'com.google.android.material:material:1.7.0'
52 | testImplementation 'junit:junit:4.13.2'
53 | testImplementation 'org.mockito:mockito-core:1.10.19'
54 | testImplementation 'org.powermock:powermock:1.6.5'
55 | testImplementation 'org.powermock:powermock-module-junit4:1.6.5'
56 | testImplementation 'org.powermock:powermock-api-mockito:1.6.5'
57 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
58 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
59 | implementation project(path: ':usbxfer')
60 | }
--------------------------------------------------------------------------------
/drivers/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/martinmarinov/Android/Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/drivers/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
26 |
27 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/DeliverySystem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers;
22 |
23 | public enum DeliverySystem {
24 | // Warning: Do not reorder!
25 | // The order is used by the TCP clients so any reordering will cause API incompatibilities
26 | DVBT, DVBT2, DVBC
27 | }
28 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/DeviceFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers;
22 |
23 | import android.hardware.usb.UsbDevice;
24 |
25 | import androidx.annotation.NonNull;
26 |
27 | import java.io.Serializable;
28 |
29 | public class DeviceFilter implements Serializable {
30 | private final int vendorId;
31 | private final int productId;
32 | private final String name;
33 |
34 | public DeviceFilter(int vendorId, int productId, String name) {
35 | this.vendorId = vendorId;
36 | this.productId = productId;
37 | this.name = name;
38 | }
39 |
40 | public boolean matches(@NonNull UsbDevice usbDevice) {
41 | return usbDevice.getVendorId() == vendorId && usbDevice.getProductId() == productId;
42 | }
43 |
44 | public int getVendorId() {
45 | return vendorId;
46 | }
47 |
48 | public int getProductId() {
49 | return productId;
50 | }
51 |
52 | public String getName() {
53 | return name;
54 | }
55 |
56 | @SuppressWarnings("SimplifiableIfStatement")
57 | @Override
58 | public boolean equals(Object o) {
59 | if (this == o) return true;
60 | if (o == null || getClass() != o.getClass()) return false;
61 |
62 | DeviceFilter that = (DeviceFilter) o;
63 |
64 | if (vendorId != that.vendorId) return false;
65 | return productId == that.productId;
66 | }
67 |
68 | @Override
69 | public int hashCode() {
70 | int result = vendorId;
71 | result = 31 * result + productId;
72 | return result;
73 | }
74 |
75 | @Override
76 | public String toString() {
77 | return name;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/DvbCapabilities.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers;
22 |
23 |
24 | import androidx.annotation.NonNull;
25 |
26 | import java.util.Set;
27 |
28 | public class DvbCapabilities {
29 | private final long frequencyMin;
30 | private final long frequencyMax;
31 | private final long frequencyStepSize;
32 | private final @NonNull Set supportedDeliverySystems;
33 |
34 | public DvbCapabilities(long frequencyMin, long frequencyMax, long frequencyStepSize, @NonNull Set supportedDeliverySystems) {
35 | this.frequencyMin = frequencyMin;
36 | this.frequencyMax = frequencyMax;
37 | this.frequencyStepSize = frequencyStepSize;
38 | this.supportedDeliverySystems = supportedDeliverySystems;
39 | }
40 |
41 | public long getFrequencyMin() {
42 | return frequencyMin;
43 | }
44 |
45 | public long getFrequencyMax() {
46 | return frequencyMax;
47 | }
48 |
49 | public long getFrequencyStepSize() {
50 | return frequencyStepSize;
51 | }
52 |
53 | public @NonNull Set getSupportedDeliverySystems() {
54 | return supportedDeliverySystems;
55 | }
56 |
57 | @Override
58 | public String toString() {
59 | return "DvbCapabilities{" +
60 | "frequencyMin=" + frequencyMin +
61 | ", frequencyMax=" + frequencyMax +
62 | ", frequencyStepSize=" + frequencyStepSize +
63 | ", supportedDeliverySystems=" + supportedDeliverySystems +
64 | '}';
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/DvbException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers;
22 |
23 | import java.io.IOException;
24 |
25 | public class DvbException extends IOException {
26 | public enum ErrorCode {
27 | BAD_API_USAGE,
28 | IO_EXCEPTION,
29 | NO_DVB_DEVICES_FOUND,
30 | UNSUPPORTED_PLATFORM,
31 | USB_PERMISSION_DENIED,
32 | CANNOT_OPEN_USB,
33 | HARDWARE_EXCEPTION,
34 | CANNOT_TUNE_TO_FREQ,
35 | UNSUPPORTED_BANDWIDTH,
36 | DVB_DEVICE_UNSUPPORTED
37 | }
38 |
39 | private final ErrorCode errorCode;
40 |
41 | public DvbException(ErrorCode errorCode, String message) {
42 | super(message);
43 | this.errorCode = errorCode;
44 | }
45 |
46 | public DvbException(ErrorCode errorCode, String message, Exception e) {
47 | super(message, e);
48 | this.errorCode = errorCode;
49 | }
50 |
51 | public DvbException(ErrorCode errorCode, Exception e) {
52 | super(e);
53 | this.errorCode = errorCode;
54 | }
55 |
56 | public ErrorCode getErrorCode() {
57 | return errorCode;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/DvbStatus.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers;
22 |
23 | public enum DvbStatus {
24 | FE_HAS_SIGNAL,
25 | FE_HAS_CARRIER,
26 | FE_HAS_VITERBI,
27 | FE_HAS_SYNC,
28 | FE_HAS_LOCK,
29 | FE_TIMEDOUT,
30 | FE_REINIT
31 | }
32 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/file/DvbFileDevice.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.file;
22 |
23 | import android.content.res.Resources;
24 | import androidx.annotation.NonNull;
25 |
26 | import java.io.File;
27 | import java.io.IOException;
28 | import java.util.Set;
29 |
30 | import info.martinmarinov.drivers.DeviceFilter;
31 | import info.martinmarinov.drivers.DvbCapabilities;
32 | import info.martinmarinov.drivers.DvbDemux;
33 | import info.martinmarinov.drivers.DvbDevice;
34 | import info.martinmarinov.drivers.DvbException;
35 | import info.martinmarinov.drivers.DvbStatus;
36 | import info.martinmarinov.drivers.R;
37 | import info.martinmarinov.drivers.tools.SetUtils;
38 | import info.martinmarinov.usbxfer.ByteSource;
39 | import info.martinmarinov.drivers.tools.io.ThrottledTsSource;
40 | import info.martinmarinov.drivers.DeliverySystem;
41 |
42 | import static info.martinmarinov.drivers.DvbException.ErrorCode.CANNOT_OPEN_USB;
43 |
44 | /**
45 | * This is a DvbDevice that can be used for debugging purposes.
46 | * It takes a file and streams it as if it is a stream coming from a real USB device.
47 | */
48 | public class DvbFileDevice extends DvbDevice {
49 | private final static DvbCapabilities CAPABILITIES = new DvbCapabilities(174000000L, 862000000L, 166667L, SetUtils.setOf(DeliverySystem.values()));
50 |
51 | private final Resources resources;
52 | private final File file;
53 | private final long freq;
54 | private final long bandwidth;
55 |
56 | private boolean isTuned = false;
57 |
58 | public DvbFileDevice(Resources resources, File file, long freq, long bandwidth) {
59 | super(DvbDemux.DvbDmxSwfilter());
60 | this.resources = resources;
61 | this.file = file;
62 | this.freq = freq;
63 | this.bandwidth = bandwidth;
64 | }
65 |
66 | @Override
67 | public void open() throws DvbException {
68 | if (!file.canRead()) throw new DvbException(CANNOT_OPEN_USB, new IOException());
69 | }
70 |
71 | @Override
72 | public DeviceFilter getDeviceFilter() {
73 | return new FileDeviceFilter(resources.getString(R.string.rec_name, freq / 1_000_000.0, bandwidth / 1_000_000.0), file);
74 | }
75 |
76 | @Override
77 | protected void tuneTo(long freqHz, long bandwidthHz, @NonNull DeliverySystem deliverySystem) throws DvbException {
78 | this.isTuned = freqHz == this.freq && bandwidthHz == this.bandwidth;
79 | }
80 |
81 | @Override
82 | public DvbCapabilities readCapabilities() throws DvbException {
83 | return CAPABILITIES;
84 | }
85 |
86 | @Override
87 | public int readSnr() throws DvbException {
88 | return isTuned ? 400 : 0;
89 | }
90 |
91 | @Override
92 | public int readRfStrengthPercentage() throws DvbException {
93 | return isTuned ? 100 : 0;
94 | }
95 |
96 | @Override
97 | public int readBitErrorRate() throws DvbException {
98 | return isTuned ? 0 : 0xFFFF;
99 | }
100 |
101 | @Override
102 | public Set getStatus() throws DvbException {
103 | if (isTuned) return SetUtils.setOf(DvbStatus.FE_HAS_SIGNAL, DvbStatus.FE_HAS_CARRIER, DvbStatus.FE_HAS_VITERBI, DvbStatus.FE_HAS_SYNC, DvbStatus.FE_HAS_LOCK);
104 | return SetUtils.setOf();
105 | }
106 |
107 | @Override
108 | protected ByteSource createTsSource() {
109 | return new ThrottledTsSource(file);
110 | }
111 |
112 | @Override
113 | public String getDebugString() {
114 | return "File - "+file.getAbsolutePath();
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/file/FileDeviceFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.file;
22 |
23 | import java.io.File;
24 | import java.util.Objects;
25 |
26 | import info.martinmarinov.drivers.DeviceFilter;
27 |
28 | class FileDeviceFilter extends DeviceFilter {
29 | private final File file;
30 |
31 | FileDeviceFilter(String name, File file) {
32 | super(-1, -1, name);
33 | this.file = file;
34 | }
35 |
36 | @Override
37 | public boolean equals(Object o) {
38 | if (this == o) return true;
39 | if (o == null || getClass() != o.getClass()) return false;
40 | if (!super.equals(o)) return false;
41 |
42 | FileDeviceFilter that = (FileDeviceFilter) o;
43 |
44 | return Objects.equals(file, that.file);
45 |
46 | }
47 |
48 | @Override
49 | public int hashCode() {
50 | int result = super.hashCode();
51 | result = 31 * result + (file != null ? file.hashCode() : 0);
52 | return result;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/AsyncFuture.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 |
24 | import androidx.annotation.NonNull;
25 |
26 | import java.util.concurrent.ExecutionException;
27 | import java.util.concurrent.Future;
28 | import java.util.concurrent.TimeUnit;
29 | import java.util.concurrent.TimeoutException;
30 |
31 | public class AsyncFuture implements Future {
32 | private final Object locker = new Object();
33 | private V object;
34 | private boolean ready = false;
35 |
36 | @Override
37 | public boolean cancel(boolean mayInterruptIfRunning) {
38 | return false;
39 | }
40 |
41 | @Override
42 | public boolean isCancelled() {
43 | return false;
44 | }
45 |
46 | @Override
47 | public boolean isDone() {
48 | synchronized (locker) {
49 | return ready;
50 | }
51 | }
52 |
53 | @Override
54 | public V get() throws InterruptedException, ExecutionException {
55 | synchronized (locker) {
56 | if (ready) return object;
57 | locker.wait();
58 | return object;
59 | }
60 | }
61 |
62 | @Override
63 | public V get(long timeout, @NonNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
64 | synchronized (locker) {
65 | if (ready) return object;
66 | locker.wait(unit.toMillis(timeout));
67 | return object;
68 | }
69 | }
70 |
71 | public void setDone(V object) {
72 | synchronized (locker) {
73 | this.object = object;
74 | this.ready = true;
75 | locker.notify();
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/Check.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | public class Check {
24 |
25 | public static T notNull(T o) {
26 | return notNull(o, null);
27 | }
28 |
29 | public static T notNull(T o, String msg) {
30 | if (o == null) exception(msg);
31 | return o;
32 | }
33 |
34 | private static void exception(String s) {
35 | if (s == null) throw new RuntimeException();
36 | throw new RuntimeException(s);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/CompletedFuture.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | import java.util.concurrent.ExecutionException;
24 | import java.util.concurrent.Future;
25 | import java.util.concurrent.TimeUnit;
26 | import java.util.concurrent.TimeoutException;
27 |
28 | public class CompletedFuture implements Future {
29 |
30 | private final T result;
31 |
32 | public CompletedFuture(T result) {
33 | this.result = result;
34 | }
35 |
36 | @Override
37 | public boolean cancel(boolean mayInterruptIfRunning) {
38 | return false;
39 | }
40 |
41 | @Override
42 | public boolean isCancelled() {
43 | return false;
44 | }
45 |
46 | @Override
47 | public boolean isDone() {
48 | return true;
49 | }
50 |
51 | @Override
52 | public T get() throws InterruptedException, ExecutionException {
53 | return result;
54 | }
55 |
56 | @Override
57 | public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
58 | return result;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/DeviceFilterMatcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | import android.annotation.SuppressLint;
24 | import android.hardware.usb.UsbDevice;
25 |
26 | import java.util.HashMap;
27 | import java.util.Map;
28 | import java.util.Set;
29 |
30 | import info.martinmarinov.drivers.DeviceFilter;
31 |
32 | public class DeviceFilterMatcher {
33 |
34 | @SuppressLint("UseSparseArrays") // Use SparseArrays and unit testing is impossible
35 | private final Map filterMap = new HashMap<>();
36 |
37 | public DeviceFilterMatcher(Set filters) {
38 | for (DeviceFilter deviceFilter : filters) {
39 | filterMap.put(hash(deviceFilter), deviceFilter);
40 | }
41 | }
42 |
43 | public DeviceFilter getFilter(UsbDevice usbDevice) {
44 | return filterMap.get(hash(usbDevice));
45 | }
46 |
47 | private static int hash(DeviceFilter deviceFilter) {
48 | return hash(deviceFilter.getVendorId(), deviceFilter.getProductId());
49 | }
50 |
51 | private static int hash(UsbDevice usbDevice) {
52 | return hash(usbDevice.getVendorId(), usbDevice.getProductId());
53 | }
54 |
55 | private static int hash(int vendorId, int productId) {
56 | return (vendorId << 16) | (productId & 0xFFFF);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/FastIntFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | public class FastIntFilter {
24 | private final byte[] bitmap;
25 | private int[] filter = new int[0];
26 |
27 | public FastIntFilter(int size) {
28 | int bitmapSize = (size + 7) >> 3;
29 | this.bitmap = new byte[bitmapSize];
30 | }
31 |
32 | public void setFilter(int ... ids) {
33 | synchronized (bitmap) {
34 | for (int aFilter : filter) setFilterOff(aFilter);
35 | this.filter = ids;
36 | for (int aFilter : filter) setFilterOn(aFilter);
37 | }
38 | }
39 |
40 | public boolean isFiltered(int id) {
41 | int bid = id >> 3;
42 | int rem = id - (bid << 3);
43 |
44 | int mask = 1 << rem;
45 | return (bitmap[bid] & mask) != 0;
46 | }
47 |
48 | private void setFilterOn(int id) {
49 | int bid = id >> 3;
50 | int rem = id - (bid << 3);
51 |
52 | int mask = 1 << rem;
53 | bitmap[bid] |= mask;
54 | }
55 |
56 | private void setFilterOff(int id) {
57 | int bid = id >> 3;
58 | int rem = id - (bid << 3);
59 |
60 | int mask = 1 << rem;
61 | bitmap[bid] &= ~mask;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/RegMap.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | import androidx.annotation.VisibleForTesting;
24 |
25 | import info.martinmarinov.drivers.DvbException;
26 |
27 | import static info.martinmarinov.drivers.tools.I2cAdapter.I2cMessage.I2C_M_RD;
28 |
29 | public class RegMap {
30 | private final int address;
31 | private final int reg_bytes;
32 | private final I2cAdapter i2CAdapter;
33 |
34 | private final Object locker = new Object();
35 | private final byte[] regbuff;
36 | private byte[] tmpbuff = new byte[0];
37 |
38 | public RegMap(int address, int reg_bits, I2cAdapter i2CAdapter) {
39 | this.address = address;
40 | this.reg_bytes = reg_bits >> 3;
41 |
42 | if (reg_bytes > 8) {
43 | throw new IllegalArgumentException("Only up to 64 bit register supported");
44 | }
45 | this.regbuff = new byte[reg_bytes];
46 |
47 | this.i2CAdapter = i2CAdapter;
48 | }
49 |
50 | public void read_regs(long reg, byte[] vals, int offset, int length) throws DvbException {
51 | synchronized (locker) {
52 | writeValue(regbuff, reg);
53 |
54 | byte[] buf = offset == 0 ? vals : getTmpBuffer(length);
55 | i2CAdapter.transfer(
56 | address, 0, regbuff, regbuff.length,
57 | address, I2C_M_RD, buf, length
58 | );
59 |
60 | if (offset != 0) {
61 | System.arraycopy(buf, 0, vals, offset, length);
62 | }
63 | }
64 | }
65 |
66 | public int read_reg(long reg) throws DvbException {
67 | byte[] ans = new byte[1];
68 | read_regs(reg, ans, 0, 1);
69 | return ans[0] & 0xFF;
70 | }
71 |
72 | public void write_reg(long reg, int val) throws DvbException {
73 | if ((val & 0xFF) != val) throw new IllegalArgumentException();
74 | bulk_write(reg, new byte[] { (byte) val });
75 | }
76 |
77 | public void bulk_write(long reg, byte[] vals) throws DvbException {
78 | bulk_write(reg, vals, vals.length);
79 | }
80 |
81 | public void bulk_write(long reg, byte[] vals, int len) throws DvbException {
82 | synchronized (locker) {
83 | writeValue(regbuff, reg);
84 | byte[] buf = getTmpBuffer(regbuff.length + len);
85 | System.arraycopy(regbuff, 0, buf, 0, regbuff.length);
86 | System.arraycopy(vals, 0, buf, regbuff.length, len);
87 | i2CAdapter.transfer(address, 0, buf, regbuff.length + len);
88 | }
89 | }
90 |
91 | @VisibleForTesting
92 | static long readValue(byte[] buff) {
93 | long res = 0;
94 | for (int i = 0; i < buff.length; i++) {
95 | res |= ((long) (buff[i] & 0xFF)) << ((buff.length - i - 1) * 8);
96 | }
97 | return res;
98 | }
99 |
100 | @VisibleForTesting
101 | static void writeValue(byte[] buff, long value) {
102 | for (int i = 0; i < buff.length; i++) {
103 | buff[i] = (byte) (value >> ((buff.length - i - 1) * 8));
104 | }
105 | }
106 |
107 | private byte[] getTmpBuffer(int size) {
108 | if (tmpbuff.length < size) {
109 | tmpbuff = new byte[size];
110 | }
111 | return tmpbuff;
112 | }
113 |
114 | public void update_bits(int reg, int mask, int val) throws DvbException {
115 | synchronized (locker) {
116 | /* no need for read if whole reg is written */
117 | if (mask != 0xff) {
118 | int tmp = read_reg(reg);
119 |
120 | val &= mask;
121 | tmp &= ~mask;
122 | val |= tmp;
123 | }
124 | write_reg(reg, val);
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/Retry.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | import android.util.Log;
24 |
25 | public class Retry {
26 | private final static String TAG = Retry.class.getSimpleName();
27 |
28 | public static void retry(int times, final ThrowingRunnable throwingRunnable) throws T {
29 | retry(times, new ThrowingCallable() {
30 | @Override
31 | public Void call() throws T {
32 | throwingRunnable.run();
33 | return null;
34 | }
35 | });
36 | }
37 |
38 | public static R retry(int times, ThrowingCallable throwingCallable) throws T {
39 | long sleep = 100;
40 | while (true) {
41 | try {
42 | return throwingCallable.call();
43 | } catch (RuntimeException e) {
44 | throw e;
45 | } catch (Throwable e) {
46 | if (times-- <= 0) {
47 | throw e;
48 | } else {
49 | Log.d(TAG, "Retries left: "+times+", exception "+e);
50 | try {
51 | Thread.sleep(sleep);
52 | } catch (InterruptedException e1) {
53 | return throwingCallable.call();
54 | }
55 | sleep *= 3;
56 | }
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/SetUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | import java.util.Collections;
24 | import java.util.HashSet;
25 | import java.util.Set;
26 |
27 | public class SetUtils {
28 | public static Set union(Set a, Set b) {
29 | Set result = new HashSet<>();
30 | result.addAll(a);
31 | result.addAll(b);
32 | return result;
33 | }
34 |
35 | @SafeVarargs
36 | public static Set setOf(T ... data) {
37 | Set result = new HashSet<>();
38 | Collections.addAll(result, data);
39 | return result;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/SleepUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 |
24 | public class SleepUtils {
25 | public static void mdelay(long millis) {
26 | safeSleep(millis * 1_000_000L);
27 | }
28 |
29 | public static void usleep(long micros) {
30 | safeSleep(micros * 1_000L);
31 | }
32 |
33 | private static void safeSleep(long toSleepNs) {
34 | long toSleepMs = (toSleepNs + 999_999L) / 1_000_000L;
35 | if (toSleepMs > 0) {
36 | try {
37 | Thread.sleep(toSleepMs);
38 | } catch (InterruptedException e) {
39 | e.printStackTrace();
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/ThrowingCallable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | public interface ThrowingCallable {
24 | R call() throws T;
25 | }
26 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/ThrowingRunnable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | public interface ThrowingRunnable {
24 | void run() throws T;
25 | }
26 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/tools/io/NativePipe.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools.io;
22 |
23 | import android.os.ParcelFileDescriptor;
24 |
25 | import java.io.Closeable;
26 | import java.io.IOException;
27 | import java.io.InputStream;
28 | import java.io.OutputStream;
29 |
30 | public class NativePipe implements Closeable {
31 | private final InputStream inputStream;
32 | private final OutputStream outputStream;
33 |
34 | public NativePipe() {
35 | try {
36 | ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
37 | inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pipe[0]) {
38 | private boolean closed = false;
39 |
40 | @Override
41 | public void close() throws IOException {
42 | if (closed) return;
43 | closed = true;
44 | super.close();
45 | outputStream.close();
46 | }
47 | };
48 | outputStream = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]) {
49 | private boolean closed = false;
50 |
51 | @Override
52 | public void close() throws IOException {
53 | if (closed) return;
54 | closed = true;
55 | super.close();
56 | inputStream.close();
57 | }
58 | };
59 | } catch (IOException e) {
60 | throw new RuntimeException(e);
61 | }
62 | }
63 |
64 | public InputStream getInputStream() {
65 | return inputStream;
66 | }
67 |
68 | public OutputStream getOutputStream() {
69 | return outputStream;
70 | }
71 |
72 | @Override
73 | public void close() throws IOException {
74 | inputStream.close();
75 | outputStream.close();
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/usb/DvbFrontend.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.usb;
22 |
23 | import androidx.annotation.NonNull;
24 |
25 | import java.util.Set;
26 |
27 | import info.martinmarinov.drivers.DeliverySystem;
28 | import info.martinmarinov.drivers.DvbCapabilities;
29 | import info.martinmarinov.drivers.DvbException;
30 | import info.martinmarinov.drivers.DvbStatus;
31 |
32 | public interface DvbFrontend {
33 | // TODO these capabilities contain frequency min and max which is actually determined by tuner
34 | DvbCapabilities getCapabilities();
35 |
36 | void attach() throws DvbException;
37 | void release(); // release should always succeed or fail catastrophically
38 |
39 | // don't forget to call tuner.init() from here!
40 | void init(DvbTuner tuner) throws DvbException;
41 |
42 | void setParams(long frequency, long bandwidthHz, @NonNull DeliverySystem deliverySystem) throws DvbException;
43 | int readSnr() throws DvbException;
44 | int readRfStrengthPercentage() throws DvbException;
45 | int readBer() throws DvbException;
46 | Set getStatus() throws DvbException;
47 | void setPids(int ... pids) throws DvbException;
48 | void disablePidFilter() throws DvbException;
49 | }
50 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/usb/DvbTuner.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.usb;
22 |
23 | import info.martinmarinov.drivers.DeliverySystem;
24 | import info.martinmarinov.drivers.DvbException;
25 |
26 | public interface DvbTuner {
27 | void attatch() throws DvbException;
28 | void release(); // release should always succeed or fail catastrophically
29 | void init() throws DvbException;
30 | void setParams(long frequency, long bandwidthHz, DeliverySystem deliverySystem) throws DvbException;
31 | long getIfFrequency() throws DvbException;
32 | int readRfStrengthPercentage() throws DvbException;
33 | }
34 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/usb/DvbUsbDeviceRegistry.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.usb;
22 |
23 | import android.content.Context;
24 | import android.hardware.usb.UsbDevice;
25 | import android.hardware.usb.UsbManager;
26 |
27 | import java.util.ArrayList;
28 | import java.util.Collection;
29 | import java.util.List;
30 |
31 | import info.martinmarinov.drivers.DeviceFilter;
32 | import info.martinmarinov.drivers.DvbDevice;
33 | import info.martinmarinov.drivers.DvbException;
34 | import info.martinmarinov.drivers.tools.DeviceFilterMatcher;
35 | import info.martinmarinov.drivers.usb.af9035.Af9035DvbDeviceCreator;
36 | import info.martinmarinov.drivers.usb.cxusb.CxUsbDvbDeviceCreator;
37 | import info.martinmarinov.drivers.usb.rtl28xx.Rtl2xx2DvbDeviceCreator;
38 |
39 | public class DvbUsbDeviceRegistry {
40 |
41 | public static DvbUsbDevice.Creator[] AVAILABLE_DRIVERS = new DvbUsbDevice.Creator[] {
42 | new Rtl2xx2DvbDeviceCreator(),
43 | new CxUsbDvbDeviceCreator(),
44 | new Af9035DvbDeviceCreator()
45 | };
46 |
47 | /**
48 | * Checks if the {@link UsbDevice} could be handled by the available drivers and returns a
49 | * {@link DvbDevice} if the device is supported.
50 | * @param usbDevice a {@link UsbDevice} device that is attached to the system
51 | * @param context the application context, used for accessing usb system service and obtaining permissions
52 | * @return a valid {@link DvbDevice} to control the {@link UsbDevice} as a DVB frontend or
53 | * a null if none of the available drivers can handle the provided {@link UsbDevice}
54 | */
55 | private static DvbDevice getDvbUsbDeviceFor(UsbDevice usbDevice, Context context) throws DvbException {
56 | for (DvbUsbDevice.Creator c : AVAILABLE_DRIVERS) {
57 | DeviceFilterMatcher deviceFilterMatcher = new DeviceFilterMatcher(c.getSupportedDevices());
58 | DeviceFilter filter = deviceFilterMatcher.getFilter(usbDevice);
59 |
60 | if (filter != null) {
61 | DvbDevice dvbDevice = c.create(usbDevice, context, filter);
62 | if (dvbDevice != null) return dvbDevice;
63 | }
64 | }
65 | return null;
66 | }
67 |
68 | /**
69 | * Gets a {@link DvbDevice} if a supported DVB USB dongle is connected to the system.
70 | * If multiple dongles are connected, a {@link Collection} would be returned
71 | * @param context a context for obtaining {@link Context#USB_SERVICE}
72 | * @return a {@link Collection} of available {@link DvbDevice} devices. Can be empty.
73 | */
74 | public static List getUsbDvbDevices(Context context) throws DvbException {
75 | List availableDvbDevices = new ArrayList<>();
76 |
77 | UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
78 | Collection availableDevices = manager.getDeviceList().values();
79 | DvbException lastException = null;
80 | for (UsbDevice usbDevice : availableDevices) {
81 | try {
82 | DvbDevice frontend = getDvbUsbDeviceFor(usbDevice, context);
83 | if (frontend != null) availableDvbDevices.add(frontend);
84 | } catch (DvbException e) {
85 | // Failed to initialize this device, try next and capture exception
86 | e.printStackTrace();
87 | lastException = e;
88 | }
89 | }
90 | if (availableDvbDevices.isEmpty()) {
91 | if (lastException != null) throw lastException;
92 | }
93 | return availableDvbDevices;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/usb/af9035/Af9033Config.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.usb.af9035;
22 |
23 | class Af9033Config {
24 | /*
25 | * clock Hz
26 | * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000,
27 | * 30000000, 36000000, 20480000, 16384000
28 | */
29 | final int clock;
30 |
31 | final boolean dyn0_clk;
32 | final boolean speck_inv;
33 |
34 | /*
35 | * ADC multiplier
36 | */
37 | static final int AF9033_ADC_MULTIPLIER_1X = 0;
38 | static final int AF9033_ADC_MULTIPLIER_2X = 1;
39 | final int adc_multiplier;
40 |
41 | /*
42 | * tuner
43 | */
44 | static final int AF9033_TUNER_TUA9001 = 0x27; /* Infineon TUA 9001 */
45 | static final int AF9033_TUNER_FC0011 = 0x28; /* Fitipower FC0011 */
46 | static final int AF9033_TUNER_FC0012 = 0x2e; /* Fitipower FC0012 */
47 | static final int AF9033_TUNER_MXL5007T = 0xa0; /* MaxLinear MxL5007T */
48 | static final int AF9033_TUNER_TDA18218 = 0xa1; /* NXP TDA 18218HN */
49 | static final int AF9033_TUNER_FC2580 = 0x32; /* FCI FC2580 */
50 | /* 50-5f Omega */
51 | static final int AF9033_TUNER_IT9135_38 = 0x38; /* Omega */
52 | static final int AF9033_TUNER_IT9135_51 = 0x51; /* Omega LNA config 1 */
53 | static final int AF9033_TUNER_IT9135_52 = 0x52; /* Omega LNA config 2 */
54 | /* 60-6f Omega v2 */
55 | static final int AF9033_TUNER_IT9135_60 = 0x60; /* Omega v2 */
56 | static final int AF9033_TUNER_IT9135_61 = 0x61; /* Omega v2 LNA config 1 */
57 | static final int AF9033_TUNER_IT9135_62 = 0x62; /* Omega v2 LNA config 2 */
58 | final int tuner;
59 |
60 | /*
61 | * TS settings
62 | */
63 | static final int AF9033_TS_MODE_USB = 0;
64 | static final int AF9033_TS_MODE_PARALLEL = 1;
65 | static final int AF9033_TS_MODE_SERIAL = 2;
66 | final int ts_mode;
67 |
68 | Af9033Config(boolean dyn0_clk, int adc_multiplier, int tuner, int ts_mode, int clock, boolean speck_inv) {
69 | this.dyn0_clk = dyn0_clk;
70 | this.adc_multiplier = adc_multiplier;
71 | this.tuner = tuner;
72 | this.ts_mode = ts_mode;
73 | this.clock = clock;
74 | this.speck_inv = speck_inv;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/CxUsbDvbDeviceCreator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.usb.cxusb;
22 |
23 | import android.content.Context;
24 | import android.hardware.usb.UsbDevice;
25 |
26 | import java.util.Set;
27 |
28 | import info.martinmarinov.drivers.DeviceFilter;
29 | import info.martinmarinov.drivers.DvbException;
30 | import info.martinmarinov.drivers.usb.DvbUsbDevice;
31 |
32 | import static info.martinmarinov.drivers.tools.SetUtils.setOf;
33 | import static info.martinmarinov.drivers.usb.cxusb.MygicaT230.MYGICA_T230;
34 | import static info.martinmarinov.drivers.usb.cxusb.MygicaT230C.MYGICA_T230C;
35 |
36 | public class CxUsbDvbDeviceCreator implements DvbUsbDevice.Creator {
37 | private final static Set CXUSB_DEVICES = setOf(MYGICA_T230, MYGICA_T230C);
38 |
39 | @Override
40 | public Set getSupportedDevices() {
41 | return CXUSB_DEVICES;
42 | }
43 |
44 | @Override
45 | public DvbUsbDevice create(UsbDevice usbDevice, Context context, DeviceFilter filter) throws DvbException {
46 | if (MYGICA_T230C.matches(usbDevice)) {
47 |
48 | return new MygicaT230C(usbDevice, context);
49 |
50 | } else {
51 |
52 | return new MygicaT230(usbDevice, context);
53 |
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.usb.cxusb;
22 |
23 | import android.content.Context;
24 | import android.hardware.usb.UsbDevice;
25 |
26 | import info.martinmarinov.drivers.DeviceFilter;
27 | import info.martinmarinov.drivers.DvbException;
28 | import info.martinmarinov.drivers.tools.SleepUtils;
29 | import info.martinmarinov.drivers.usb.DvbFrontend;
30 | import info.martinmarinov.drivers.usb.DvbTuner;
31 | import info.martinmarinov.drivers.usb.DvbUsbIds;
32 | import info.martinmarinov.drivers.usb.silabs.Si2157;
33 | import info.martinmarinov.drivers.usb.silabs.Si2168;
34 |
35 | import static info.martinmarinov.drivers.usb.silabs.Si2157.Type.SI2157_CHIPTYPE_SI2157;
36 |
37 | class MygicaT230 extends CxUsbDvbDevice {
38 | private final static String MYGICA_NAME = "Mygica T230 DVB-T/T2/C";
39 | final static DeviceFilter MYGICA_T230 = new DeviceFilter(DvbUsbIds.USB_VID_CONEXANT, DvbUsbIds.USB_PID_MYGICA_T230, MYGICA_NAME);
40 |
41 | private Si2168 frontend;
42 |
43 | MygicaT230(UsbDevice usbDevice, Context context) throws DvbException {
44 | super(usbDevice, context, MYGICA_T230);
45 | }
46 |
47 | @Override
48 | public String getDebugString() {
49 | return MYGICA_NAME;
50 | }
51 |
52 | @Override
53 | synchronized protected void powerControl(boolean onoff) throws DvbException {
54 | cxusb_d680_dmb_power_ctrl(onoff);
55 | cxusb_streaming_ctrl(onoff);
56 | }
57 |
58 | private void cxusb_d680_dmb_power_ctrl(boolean onoff) throws DvbException {
59 | cxusb_power_ctrl(onoff);
60 | if (!onoff) return;
61 |
62 | SleepUtils.mdelay(128);
63 | cxusb_ctrl_msg(CMD_DIGITAL, new byte[0], 0, new byte[1], 1);
64 | SleepUtils.mdelay(100);
65 | }
66 |
67 | @Override
68 | protected void readConfig() throws DvbException {
69 | // no-op
70 | }
71 |
72 | @Override
73 | protected DvbFrontend frontendAttatch() throws DvbException {
74 | return frontend = new Si2168(this, resources, i2CAdapter, 0x64, SI2168_TS_PARALLEL, true, SI2168_TS_CLK_AUTO_FIXED, false);
75 | }
76 |
77 | @Override
78 | protected DvbTuner tunerAttatch() throws DvbException {
79 | return new Si2157(resources, i2CAdapter, frontend.gateControl(), 0x60, true, SI2157_CHIPTYPE_SI2157);
80 | }
81 |
82 | @Override
83 | protected void init() throws DvbException {
84 | // no-op
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/usb/cxusb/MygicaT230C.java:
--------------------------------------------------------------------------------
1 | package info.martinmarinov.drivers.usb.cxusb;
2 |
3 | import android.content.Context;
4 | import android.hardware.usb.UsbDevice;
5 |
6 | import info.martinmarinov.drivers.DeviceFilter;
7 | import info.martinmarinov.drivers.DvbException;
8 | import info.martinmarinov.drivers.tools.SleepUtils;
9 | import info.martinmarinov.drivers.usb.DvbFrontend;
10 | import info.martinmarinov.drivers.usb.DvbTuner;
11 | import info.martinmarinov.drivers.usb.DvbUsbIds;
12 | import info.martinmarinov.drivers.usb.silabs.Si2157;
13 | import info.martinmarinov.drivers.usb.silabs.Si2168;
14 |
15 | import static info.martinmarinov.drivers.usb.silabs.Si2157.Type.SI2157_CHIPTYPE_SI2141;
16 |
17 |
18 | /**
19 | * @author dmgouriev
20 | */
21 | public class MygicaT230C extends CxUsbDvbDevice {
22 | public final static String MYGICA_NAME = "Mygica T230C DVB-T/T2/C";
23 | final static DeviceFilter MYGICA_T230C = new DeviceFilter(DvbUsbIds.USB_VID_CONEXANT, DvbUsbIds.USB_PID_GENIATECH_T230C, MYGICA_NAME);
24 |
25 | private Si2168 frontend;
26 |
27 | MygicaT230C(UsbDevice usbDevice, Context context) throws DvbException {
28 | super(usbDevice, context, MYGICA_T230C);
29 | }
30 |
31 | @Override
32 | public String getDebugString() {
33 | return MYGICA_NAME;
34 | }
35 |
36 | @Override
37 | synchronized protected void powerControl(boolean onoff) throws DvbException {
38 | cxusb_d680_dmb_power_ctrl(onoff);
39 | cxusb_streaming_ctrl(onoff);
40 | }
41 |
42 | private void cxusb_d680_dmb_power_ctrl(boolean onoff) throws DvbException {
43 | cxusb_power_ctrl(onoff);
44 | if (!onoff) return;
45 |
46 | SleepUtils.mdelay(128);
47 | cxusb_ctrl_msg(CMD_DIGITAL, new byte[0], 0, new byte[1], 1);
48 | SleepUtils.mdelay(100);
49 | }
50 |
51 | @Override
52 | protected void readConfig() throws DvbException {
53 | // no-op
54 | }
55 |
56 | @Override
57 | protected DvbFrontend frontendAttatch() throws DvbException {
58 | return frontend = new Si2168(this, resources, i2CAdapter, 0x64, SI2168_TS_PARALLEL, true, SI2168_TS_CLK_AUTO_ADAPT, false);
59 | }
60 |
61 | @Override
62 | protected DvbTuner tunerAttatch() throws DvbException {
63 | return new Si2157(resources, i2CAdapter, frontend.gateControl(), 0x60, false, SI2157_CHIPTYPE_SI2141);
64 | }
65 |
66 | @Override
67 | protected void init() throws DvbException {
68 | // no-op
69 | }
70 |
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/usb/generic/AbstractGenericDvbUsbDevice.java:
--------------------------------------------------------------------------------
1 | package info.martinmarinov.drivers.usb.generic;
2 |
3 | import static android.hardware.usb.UsbConstants.USB_DIR_OUT;
4 | import static info.martinmarinov.drivers.DvbException.ErrorCode.HARDWARE_EXCEPTION;
5 |
6 | import android.content.Context;
7 | import android.hardware.usb.UsbDevice;
8 | import android.hardware.usb.UsbEndpoint;
9 | import android.os.Build;
10 |
11 | import androidx.annotation.NonNull;
12 | import androidx.annotation.Nullable;
13 |
14 | import java.util.concurrent.locks.ReentrantLock;
15 |
16 | import info.martinmarinov.drivers.DeviceFilter;
17 | import info.martinmarinov.drivers.DvbDemux;
18 | import info.martinmarinov.drivers.DvbException;
19 | import info.martinmarinov.drivers.R;
20 | import info.martinmarinov.drivers.usb.DvbUsbDevice;
21 |
22 | public abstract class AbstractGenericDvbUsbDevice extends DvbUsbDevice {
23 | private final static int DEFAULT_USB_COMM_TIMEOUT_MS = 100;
24 | private final static long DEFAULT_READ_OR_WRITE_TIMEOUT_MS = 700L;
25 |
26 | private final ReentrantLock usbReentrantLock = new ReentrantLock();
27 | protected final UsbEndpoint controlEndpointIn;
28 | protected final UsbEndpoint controlEndpointOut;
29 |
30 | protected AbstractGenericDvbUsbDevice(
31 | UsbDevice usbDevice,
32 | Context context,
33 | DeviceFilter deviceFilter,
34 | DvbDemux dvbDemux,
35 | UsbEndpoint controlEndpointIn,
36 | UsbEndpoint controlEndpointOut
37 | ) throws DvbException {
38 | super(usbDevice, context, deviceFilter, dvbDemux);
39 | this.controlEndpointIn = controlEndpointIn;
40 | this.controlEndpointOut = controlEndpointOut;
41 | }
42 |
43 | private int bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int offset, int length) {
44 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
45 | return usbDeviceConnection.bulkTransfer(endpoint, buffer, offset, length, DEFAULT_USB_COMM_TIMEOUT_MS);
46 | } else if (offset == 0) {
47 | return usbDeviceConnection.bulkTransfer(endpoint, buffer, length, DEFAULT_USB_COMM_TIMEOUT_MS);
48 | } else {
49 | byte[] tempbuff = new byte[length - offset];
50 | if (endpoint.getDirection() == USB_DIR_OUT) {
51 | System.arraycopy(buffer, offset, tempbuff, 0, length - offset);
52 | return usbDeviceConnection.bulkTransfer(endpoint, tempbuff, tempbuff.length, DEFAULT_USB_COMM_TIMEOUT_MS);
53 | } else {
54 | int read = usbDeviceConnection.bulkTransfer(endpoint, tempbuff, tempbuff.length, DEFAULT_USB_COMM_TIMEOUT_MS);
55 | if (read <= 0) {
56 | return read;
57 | }
58 | System.arraycopy(tempbuff, 0, buffer, offset, read);
59 | return read;
60 | }
61 | }
62 | }
63 |
64 | protected void dvb_usb_generic_rw(@NonNull byte[] wbuf, int wlen, @Nullable byte[] rbuf, int rlen) throws DvbException {
65 | long startTime = System.currentTimeMillis();
66 | usbReentrantLock.lock();
67 | try {
68 | int bytesTransferred = 0;
69 | while (bytesTransferred < wlen) {
70 | int actlen = bulkTransfer(controlEndpointOut, wbuf, bytesTransferred, wlen - bytesTransferred);
71 | if (System.currentTimeMillis() - startTime > DEFAULT_READ_OR_WRITE_TIMEOUT_MS) {
72 | actlen = -99999999;
73 | }
74 | if (actlen < 0) {
75 | throw new DvbException(HARDWARE_EXCEPTION, resources.getString(R.string.cannot_send_control_message, actlen));
76 | }
77 | bytesTransferred += actlen;
78 | }
79 |
80 | if (rbuf != null && rlen >= 0) {
81 | bytesTransferred = 0;
82 |
83 | while (bytesTransferred < rlen) {
84 | int actlen = bulkTransfer(controlEndpointIn, rbuf, bytesTransferred, rlen - bytesTransferred);
85 | if (System.currentTimeMillis() - startTime > 2*DEFAULT_READ_OR_WRITE_TIMEOUT_MS) {
86 | actlen = -99999999;
87 | }
88 | if (actlen < 0) {
89 | throw new DvbException(HARDWARE_EXCEPTION, resources.getString(R.string.cannot_send_control_message, actlen));
90 | }
91 | bytesTransferred += actlen;
92 | }
93 | }
94 | } finally {
95 | usbReentrantLock.unlock();
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/usb/rtl28xx/Rtl28xxSlaveType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.usb.rtl28xx;
22 |
23 | import android.content.res.Resources;
24 |
25 | import info.martinmarinov.drivers.DvbException;
26 | import info.martinmarinov.drivers.R;
27 | import info.martinmarinov.drivers.usb.DvbFrontend;
28 |
29 | enum Rtl28xxSlaveType {
30 | SLAVE_DEMOD_NONE((rtl28xxDvbDevice, tuner, i2CAdapter, resources) -> new Rtl2832Frontend(tuner, i2CAdapter, resources)),
31 | SLAVE_DEMOD_MN88472((rtl28xxDvbDevice, tuner, i2CAdapter, resources) -> {
32 | if (tuner != Rtl28xxTunerType.RTL2832_R828D)
33 | throw new DvbException(DvbException.ErrorCode.BAD_API_USAGE, resources.getString(R.string.unsupported_slave_on_tuner));
34 |
35 | Rtl2832Frontend master = new Rtl2832Frontend(tuner, i2CAdapter, resources);
36 | Mn88472 slave = new Mn88472(i2CAdapter, resources);
37 | return new Rtl2832pFrontend(master, rtl28xxDvbDevice, slave, false);
38 | }),
39 | SLAVE_DEMOD_MN88473((rtl28xxDvbDevice, tuner, i2CAdapter, resources) -> {
40 | if (tuner != Rtl28xxTunerType.RTL2832_R828D)
41 | throw new DvbException(DvbException.ErrorCode.BAD_API_USAGE, resources.getString(R.string.unsupported_slave_on_tuner));
42 |
43 | Rtl2832Frontend master = new Rtl2832Frontend(tuner, i2CAdapter, resources);
44 | Mn88473 slave = new Mn88473(i2CAdapter, resources);
45 | return new Rtl2832pFrontend(master, rtl28xxDvbDevice, slave, false);
46 | }),
47 | SLAVE_DEMOD_CXD2837ER((rtl28xxDvbDevice, tuner, i2CAdapter, resources) -> {
48 | if (tuner != Rtl28xxTunerType.RTL2832_R828D)
49 | throw new DvbException(DvbException.ErrorCode.BAD_API_USAGE, resources.getString(R.string.unsupported_slave_on_tuner));
50 |
51 | Rtl2832Frontend master = new Rtl2832Frontend(tuner, i2CAdapter, resources);
52 | Cxd2841er slave = new Cxd2841er(
53 | i2CAdapter,
54 | resources,
55 | Cxd2841er.Xtal.SONY_XTAL_20500,
56 | 0xd8,
57 | true,
58 | true,
59 | true,
60 | true);
61 | return new Rtl2832pFrontend(master, rtl28xxDvbDevice, slave, true);
62 | });
63 |
64 | private final FrontendCreator frontendCreator;
65 |
66 | Rtl28xxSlaveType(FrontendCreator frontendCreator) {
67 | this.frontendCreator = frontendCreator;
68 | }
69 |
70 | DvbFrontend createFrontend(Rtl28xxDvbDevice rtl28xxDvbDevice, Rtl28xxTunerType tunerType, Rtl28xxDvbDevice.Rtl28xxI2cAdapter i2cAdapter, Resources resources) throws DvbException {
71 | return frontendCreator.createFrontend(rtl28xxDvbDevice, tunerType, i2cAdapter, resources);
72 | }
73 |
74 | private interface FrontendCreator {
75 | DvbFrontend createFrontend(Rtl28xxDvbDevice rtl28xxDvbDevice, Rtl28xxTunerType tunerType, Rtl28xxDvbDevice.Rtl28xxI2cAdapter i2cAdapter, Resources resources) throws DvbException;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/drivers/src/main/java/info/martinmarinov/drivers/usb/silabs/Si2168Data.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.usb.silabs;
22 |
23 | import androidx.annotation.Nullable;
24 |
25 | import info.martinmarinov.drivers.DeliverySystem;
26 | import info.martinmarinov.drivers.DvbCapabilities;
27 | import info.martinmarinov.drivers.R;
28 | import info.martinmarinov.drivers.tools.SetUtils;
29 |
30 | public class Si2168Data {
31 | enum Si2168Chip {
32 | SI2168_CHIP_ID_A20(('A' << 24) | (68 << 16) | ('2' << 8) | '0', R.raw.dvbdemodsi2168a2001fw),
33 | SI2168_CHIP_ID_A30(('A' << 24) | (68 << 16) | ('3' << 8) | '0', R.raw.dvbdemodsi2168a3001fw),
34 | SI2168_CHIP_ID_B40(('B' << 24) | (68 << 16) | ('4' << 8) | '0', R.raw.dvbdemodsi2168b4001fw),
35 | SI2168_CHIP_ID_D60(('D' << 24) | (68 << 16) | ('6' << 8) | '0', R.raw.dvbdemodsi2168d6001fw);
36 |
37 | private final int id;
38 | final int firmwareFile;
39 |
40 | Si2168Chip(int id, int firmwareFile) {
41 | this.id = id;
42 | this.firmwareFile = firmwareFile;
43 | }
44 |
45 | static @Nullable Si2168Chip fromId(int id) {
46 | for (Si2168Chip chip : values()) {
47 | if (chip.id == id) return chip;
48 | }
49 | return null;
50 | }
51 | }
52 |
53 | final static DvbCapabilities CAPABILITIES = new DvbCapabilities(
54 | 42_000_000L,
55 | 870_000_000L,
56 | 166667L,
57 | SetUtils.setOf(DeliverySystem.DVBT, DeliverySystem.DVBT2, DeliverySystem.DVBC));
58 | }
59 |
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/dvbdemodsi2168a2001fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/dvbdemodsi2168a2001fw
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/dvbdemodsi2168a3001fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/dvbdemodsi2168a3001fw
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/dvbdemodsi2168b4001fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/dvbdemodsi2168b4001fw
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/dvbdemodsi2168d6001fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/dvbdemodsi2168d6001fw
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/dvbtunersi2141a1001fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/dvbtunersi2141a1001fw
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/dvbtunersi2158a2001fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/dvbtunersi2158a2001fw
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/dvbusbaf903502fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/dvbusbaf903502fw
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/dvbusbit913501fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/dvbusbit913501fw
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/dvbusbit913502fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/dvbusbit913502fw
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/dvbusbit930301fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/dvbusbit930301fw
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/mn8847202fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/mn8847202fw
--------------------------------------------------------------------------------
/drivers/src/main/res/raw/mn8847301fw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/drivers/src/main/res/raw/mn8847301fw
--------------------------------------------------------------------------------
/drivers/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 | drivers
23 | No devices found
24 | Cannot open USB device connection
25 | Unexpected USB endpoint
26 | Cannot claim USB interface
27 | Cannot send USB control message. Error code %d
28 | Cannot send USB control message. Checksum failed.
29 | Failed to write to register
30 | Failed to read from register
31 | Timed out reading from register
32 | Cannot turn on device
33 | Unrecognized tuner on USB device
34 | The tuner chip of this device DVB-T dongle is unsupported.
35 | Unsupported i2c operation
36 | I2C communication with tuner failed
37 | Cannot calibrate tuner
38 | A tuner callibration step has failed
39 | Cannot tune to %1$d MHz
40 | Invalid bandwidth
41 | Cannot read SNR
42 | We are sorry to inform you that your Android device is not supported yet.
43 | TS rec at %1$.2f MHz bw %2$.2f MHz
44 | Bad API usage. Internal bug.
45 | Unexpected chip id
46 | Chip has unsupported clock speed
47 | Unsupported slave demodulator on tuner
48 | Cannot load device firmware
49 | The hardware does not support the selected delivery system
50 |
51 |
--------------------------------------------------------------------------------
/drivers/src/test/java/info/martinmarinov/drivers/DeviceFilterMatcherTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers;
22 |
23 | import android.hardware.usb.UsbDevice;
24 |
25 | import org.junit.Test;
26 | import org.mockito.Mockito;
27 |
28 | import info.martinmarinov.drivers.tools.DeviceFilterMatcher;
29 |
30 | import static info.martinmarinov.drivers.usb.DvbUsbIds.USB_PID_AVERMEDIA_A835;
31 | import static info.martinmarinov.drivers.usb.DvbUsbIds.USB_PID_HAUPPAUGE_MYTV_T;
32 | import static info.martinmarinov.drivers.usb.DvbUsbIds.USB_PID_REALTEK_RTL2831U;
33 | import static info.martinmarinov.drivers.usb.DvbUsbIds.USB_PID_REALTEK_RTL2832U;
34 | import static info.martinmarinov.drivers.usb.DvbUsbIds.USB_VID_AVERMEDIA;
35 | import static info.martinmarinov.drivers.usb.DvbUsbIds.USB_VID_HAUPPAUGE;
36 | import static info.martinmarinov.drivers.usb.DvbUsbIds.USB_VID_REALTEK;
37 | import static info.martinmarinov.drivers.tools.SetUtils.setOf;
38 | import static org.hamcrest.CoreMatchers.equalTo;
39 | import static org.hamcrest.CoreMatchers.nullValue;
40 | import static org.junit.Assert.assertThat;
41 | import static org.mockito.Mockito.when;
42 |
43 | public class DeviceFilterMatcherTest {
44 | private final static DeviceFilterMatcher TEST_MATCHER = new DeviceFilterMatcher(setOf(
45 | new DeviceFilter(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T, "HAUPPAUGE"),
46 | new DeviceFilter(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U, "RTL2831U"),
47 | new DeviceFilter(0xFFFF, 0xFFFF, "Edge case")
48 | ));
49 |
50 | @Test
51 | public void whenMatches() throws Exception {
52 | assertThat(TEST_MATCHER.getFilter(mockUsbDevice(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T)).getName(), equalTo("HAUPPAUGE"));
53 | assertThat(TEST_MATCHER.getFilter(mockUsbDevice(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U)).getName(), equalTo("RTL2831U"));
54 | assertThat(TEST_MATCHER.getFilter(mockUsbDevice(0xFFFF, 0xFFFF)).getName(), equalTo("Edge case"));
55 | }
56 |
57 | @Test
58 | public void whenDoesntMatch() throws Exception {
59 | assertThat(TEST_MATCHER.getFilter(mockUsbDevice(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835)), nullValue());
60 | assertThat(TEST_MATCHER.getFilter(mockUsbDevice(USB_VID_REALTEK, USB_PID_REALTEK_RTL2832U)), nullValue());
61 | assertThat(TEST_MATCHER.getFilter(mockUsbDevice(0xFFFF, USB_PID_HAUPPAUGE_MYTV_T)), nullValue());
62 | assertThat(TEST_MATCHER.getFilter(mockUsbDevice(USB_VID_HAUPPAUGE, 0xFFFF)), nullValue());
63 | }
64 |
65 | private static UsbDevice mockUsbDevice(int vendorId, int productId) {
66 | UsbDevice mockUsbDevice = Mockito.mock(UsbDevice.class);
67 | when(mockUsbDevice.getVendorId()).thenReturn(vendorId);
68 | when(mockUsbDevice.getProductId()).thenReturn(productId);
69 | return mockUsbDevice;
70 | }
71 | }
--------------------------------------------------------------------------------
/drivers/src/test/java/info/martinmarinov/drivers/tools/BitReverseTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | import org.junit.Test;
24 |
25 | import static org.hamcrest.CoreMatchers.is;
26 | import static org.junit.Assert.*;
27 |
28 | public class BitReverseTest {
29 | @Test
30 | public void bitRev8() throws Exception {
31 | assertThat(BitReverse.bitRev8((byte) 0x00), is((byte) 0x00));
32 | assertThat(BitReverse.bitRev8((byte) 0xFF), is((byte) 0xFF));
33 | assertThat(BitReverse.bitRev8((byte) 0x40), is((byte) 0x02));
34 | assertThat(BitReverse.bitRev8((byte) 0x02), is((byte) 0x40));
35 | assertThat(BitReverse.bitRev8((byte) 0x80), is((byte) 0x01));
36 | assertThat(BitReverse.bitRev8((byte) 0x01), is((byte) 0x80));
37 | assertThat(BitReverse.bitRev8((byte) 0xA0), is((byte) 0x05));
38 | assertThat(BitReverse.bitRev8((byte) 0x18), is((byte) 0x18));
39 | assertThat(BitReverse.bitRev8((byte) 0x1C), is((byte) 0x38));
40 | assertThat(BitReverse.bitRev8((byte) 0x38), is((byte) 0x1C));
41 | }
42 |
43 | @Test
44 | public void bitRev16() throws Exception {
45 | assertThat(BitReverse.bitRev16((short) 0x0001), is((short) 0x8000));
46 | assertThat(BitReverse.bitRev16((short) 0x8000), is((short) 0x0001));
47 | assertThat(BitReverse.bitRev16((short) 0xFF00), is((short) 0x00FF));
48 | assertThat(BitReverse.bitRev16((short) 0xFFF0), is((short) 0x0FFF));
49 | assertThat(BitReverse.bitRev16((short) 0x000F), is((short) 0xF000));
50 | }
51 |
52 | @Test
53 | public void bitRev32() throws Exception {
54 | assertThat(BitReverse.bitRev32(0x00000001), is(0x80000000));
55 | assertThat(BitReverse.bitRev32(0x80000000), is(0x00000001));
56 | assertThat(BitReverse.bitRev32(0x0F000000), is(0x000000F0));
57 | assertThat(BitReverse.bitRev32(0x000000F0), is(0x0F000000));
58 | assertThat(BitReverse.bitRev32(0xF0000000), is(0x0000000F));
59 | assertThat(BitReverse.bitRev32(0x0000000F), is(0xF0000000));
60 | assertThat(BitReverse.bitRev32(0xFF000000), is(0x000000FF));
61 | assertThat(BitReverse.bitRev32(0x000000FF), is(0xFF000000));
62 | assertThat(BitReverse.bitRev32(0xFFFFF0FF), is(0xFF0FFFFF));
63 | assertThat(BitReverse.bitRev32(0xFF0FFFFF), is(0xFFFFF0FF));
64 | assertThat(BitReverse.bitRev32(0xFFFFFFF0), is(0x0FFFFFFF));
65 | assertThat(BitReverse.bitRev32(0x0FFFFFFF), is(0xFFFFFFF0));
66 | }
67 |
68 | }
--------------------------------------------------------------------------------
/drivers/src/test/java/info/martinmarinov/drivers/tools/ConvertCStringToJavaArrayTool.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | import org.junit.Test;
24 |
25 | // This is an abuse of JUnit tests but it is handy so it is ok
26 | public class ConvertCStringToJavaArrayTool {
27 | @Test
28 | public void doConvert() {
29 | convert("\\xc0\\x00\\x0c\\x00\\x00\\x01\\x01\\x01\\x01\\x01\\x01\\x02\\x00\\x00\\x01");
30 | }
31 |
32 | private void convert(String s) {
33 | System.out.println(s.replace("\\", ", (byte) 0"));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/drivers/src/test/java/info/martinmarinov/drivers/tools/DvbMathTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | import org.junit.Test;
24 |
25 | import static org.hamcrest.CoreMatchers.is;
26 | import static org.junit.Assert.assertThat;
27 |
28 | public class DvbMathTest {
29 | @Test
30 | public void fls() throws Exception {
31 | assertThat(DvbMath.fls(1), is(1));
32 | assertThat(DvbMath.fls(0), is(0));
33 | assertThat(DvbMath.fls(0x80000000), is(32));
34 | }
35 |
36 | @Test
37 | public void intlog2() throws Exception {
38 | assertThat(DvbMath.intlog2(8), is(3 << 24));
39 | assertThat(DvbMath.intlog2(1024), is(10 << 24));
40 | assertThat(DvbMath.intlog2(0x80000000), is(31 << 24));
41 | }
42 |
43 | @Test
44 | public void intlog10() throws Exception {
45 | //example: intlog10(1000) will give 3 << 24 = 3 * 2^24
46 | // due to the implementation intlog10(1000) might be not exactly 3 * 2^24
47 | assertThat(DvbMath.intlog10(1_000), is(50331675));
48 | }
49 | }
--------------------------------------------------------------------------------
/drivers/src/test/java/info/martinmarinov/drivers/tools/FastIntFilterTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | import org.junit.Before;
24 | import org.junit.Test;
25 |
26 | import java.util.HashSet;
27 | import java.util.Set;
28 |
29 | import static org.hamcrest.core.Is.is;
30 | import static org.junit.Assert.assertThat;
31 |
32 | public class FastIntFilterTest {
33 | private FastIntFilter f;
34 |
35 | @Before
36 | public void setUp() {
37 | f = new FastIntFilter(20);
38 | }
39 |
40 | @Test
41 | public void testSimpleCase() {
42 | f.setFilter(0, 3, 8, 18, 19);
43 | confirmOnlyFiltered(0, 3, 8, 18, 19);
44 | }
45 |
46 | @Test
47 | public void testWithReset() {
48 | f.setFilter(1, 7, 8, 17);
49 | confirmOnlyFiltered(1, 7, 8, 17);
50 | f.setFilter(0);
51 | confirmOnlyFiltered(0);
52 | f.setFilter(13, 19);
53 | confirmOnlyFiltered(13, 19);
54 | }
55 |
56 | @Test
57 | public void testSlightlyOverSize() {
58 | f.setFilter(23); // Doesn't throw exception
59 | }
60 |
61 | @Test(expected = ArrayIndexOutOfBoundsException.class)
62 | public void testTrulyOverSize() {
63 | f.setFilter(24);
64 | }
65 |
66 | private void confirmOnlyFiltered(int ... vals) {
67 | Set set = new HashSet<>();
68 | for (int val : vals) set.add(val);
69 | int filteredCount = 0;
70 | for (int i = 0; i < 20; i++) {
71 | boolean isActuallyFiltered = set.contains(i);
72 | boolean isFiltered = f.isFiltered(i);
73 |
74 | if (isFiltered) filteredCount++;
75 | assertThat(isFiltered, is(isActuallyFiltered));
76 | }
77 | assertThat(filteredCount, is(vals.length));
78 | }
79 | }
--------------------------------------------------------------------------------
/drivers/src/test/java/info/martinmarinov/drivers/tools/RegMapTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.drivers.tools;
22 |
23 | import org.junit.Test;
24 |
25 | import static org.hamcrest.MatcherAssert.assertThat;
26 | import static org.hamcrest.core.Is.is;
27 |
28 | public class RegMapTest {
29 | @Test
30 | public void readValueTest64bit() {
31 | long expected = 0x123456789ABCDEFFL;
32 | long actual = RegMap.readValue(new byte[] {
33 | (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78,
34 | (byte) 0x9A, (byte) 0xBC, (byte) 0xDE, (byte) 0xFF
35 | });
36 |
37 | assertThat(actual, is(expected));
38 | }
39 |
40 | @Test
41 | public void writeValueTest64bit() {
42 | byte[] expected = new byte[] {
43 | (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78,
44 | (byte) 0x9A, (byte) 0xBC, (byte) 0xDE, (byte) 0xFF
45 | };
46 | byte[] actual;
47 | RegMap.writeValue(actual = new byte[8], 0x123456789ABCDEFFL);
48 |
49 | assertThat(actual, is(expected));
50 | }
51 |
52 | @Test
53 | public void readValueTest16bit() {
54 | long expected = 0x1234L;
55 | long actual = RegMap.readValue(new byte[] {
56 | (byte) 0x12, (byte) 0x34
57 | });
58 |
59 | assertThat(actual, is(expected));
60 | }
61 |
62 | @Test
63 | public void writeValueTest16bit() {
64 | byte[] expected = new byte[] {
65 | (byte) 0x12, (byte) 0x34
66 | };
67 | byte[] actual;
68 | RegMap.writeValue(actual = new byte[2], 0x1234L);
69 |
70 | assertThat(actual, is(expected));
71 | }
72 | }
--------------------------------------------------------------------------------
/dvbservice/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/dvbservice/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | plugins {
22 | id 'com.android.library'
23 | }
24 |
25 | android {
26 | namespace 'info.martinmarinov.dvbservice'
27 | compileSdk 34
28 |
29 | defaultConfig {
30 | minSdk 21
31 | targetSdk 34
32 |
33 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
34 | consumerProguardFiles "consumer-rules.pro"
35 | }
36 |
37 | buildTypes {
38 | release {
39 | minifyEnabled false
40 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
41 | }
42 | }
43 | compileOptions {
44 | sourceCompatibility JavaVersion.VERSION_1_8
45 | targetCompatibility JavaVersion.VERSION_1_8
46 | }
47 | }
48 |
49 | dependencies {
50 | implementation 'androidx.appcompat:appcompat:1.5.1'
51 | implementation 'com.google.android.material:material:1.7.0'
52 | testImplementation 'junit:junit:4.13.2'
53 | testImplementation 'org.powermock:powermock:1.6.5'
54 | testImplementation 'org.powermock:powermock-module-junit4:1.6.5'
55 | testImplementation 'org.powermock:powermock-api-mockito:1.6.5'
56 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
57 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
58 | implementation project(path: ':drivers')
59 | }
--------------------------------------------------------------------------------
/dvbservice/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/martinmarinov/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/dvbservice/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
45 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
60 |
64 |
65 |
66 |
67 |
68 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/dvbservice/src/main/java/info/martinmarinov/dvbservice/DvbServerPorts.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbservice;
22 |
23 | import java.io.Serializable;
24 |
25 | class DvbServerPorts implements Serializable {
26 | private final int controlPort;
27 | private final int transferPort;
28 |
29 | DvbServerPorts(int controlPort, int transferPort) {
30 | this.controlPort = controlPort;
31 | this.transferPort = transferPort;
32 | }
33 |
34 | int getControlPort() {
35 | return controlPort;
36 | }
37 |
38 | int getTransferPort() {
39 | return transferPort;
40 | }
41 | }
--------------------------------------------------------------------------------
/dvbservice/src/main/java/info/martinmarinov/dvbservice/Response.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbservice;
22 |
23 | import java.io.IOException;
24 | import java.io.OutputStream;
25 |
26 | /**
27 | * This is send to the client as a result of every Request received
28 | *
29 | * byte 0 will be the Request.ordinal of the Request
30 | * byte 1 will be N the number of longs in the payload
31 | * byte 3 to byte 6 will be the success flag (0 or 1). This indicates whether the request was succesful.
32 | * byte 7 till the end the rest of the longs in the payload follow
33 | *
34 | * Basically the success flag is always part of the payload, so the payload
35 | * always consists of at least one value.
36 | */
37 | class Response {
38 | static Response ERROR = error();
39 | static Response SUCCESS = success();
40 |
41 | private final boolean success;
42 | private final long[] payload;
43 |
44 | static Response success(long... payload) {
45 | return new Response(true, payload);
46 | }
47 |
48 | private static Response error(long... payload) {
49 | return new Response(false, payload);
50 | }
51 |
52 | private Response(boolean success, long ... payload) {
53 | this.success = success;
54 | this.payload = payload;
55 | }
56 |
57 | private static void writeLong(byte[] buff, int off, long v) {
58 | buff[off] = (byte)(v >>> 56);
59 | buff[off+1] = (byte)(v >>> 48);
60 | buff[off+2] = (byte)(v >>> 40);
61 | buff[off+3] = (byte)(v >>> 32);
62 | buff[off+4] = (byte)(v >>> 24);
63 | buff[off+5] = (byte)(v >>> 16);
64 | buff[off+6] = (byte)(v >>> 8);
65 | buff[off+7] = (byte)(v);
66 | }
67 |
68 | void serialize(Request request, OutputStream dataOutputStream) throws IOException {
69 | byte[] payload_raw = new byte[2 + 8 + payload.length * 8];
70 |
71 | payload_raw[0] = (byte) request.ordinal(); // what request called it
72 | payload_raw[1] = (byte) (payload.length + 1); // the success flag is part of the payload
73 | writeLong(payload_raw, 2, success ? 1 : 0); // success flag
74 | for (int i = 0; i < payload.length; i++) {
75 | writeLong(payload_raw, 2 + 8 + i * 8, payload[i]); // write actual payload if any
76 | }
77 |
78 | dataOutputStream.write(payload_raw); // raw payload in one chunk to avoid any TCP partitioning
79 | dataOutputStream.flush(); // force send over the pipe, don't wait
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/dvbservice/src/main/java/info/martinmarinov/dvbservice/UsbDelegate.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbservice;
22 |
23 | import android.app.Activity;
24 | import android.content.ActivityNotFoundException;
25 | import android.content.Intent;
26 | import android.hardware.usb.UsbDevice;
27 | import android.hardware.usb.UsbManager;
28 | import android.os.Bundle;
29 | import android.util.Log;
30 |
31 | public class UsbDelegate extends Activity {
32 | private static final String TAG = UsbDelegate.class.getSimpleName();
33 | private static final String ACTION_DVB_DEVICE_ATTACHED = "info.martinmarinov.dvbdriver.DVB_DEVICE_ATTACHED";
34 |
35 | @Override
36 | public void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 |
39 | Intent intent = getIntent();
40 | if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
41 | UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
42 | Log.d(TAG, "USB DVB-T attached: " + usbDevice.getDeviceName());
43 | Intent newIntent = new Intent(ACTION_DVB_DEVICE_ATTACHED);
44 | newIntent.putExtra(UsbManager.EXTRA_DEVICE, usbDevice);
45 | try {
46 | startActivity(newIntent);
47 | } catch (ActivityNotFoundException e) {
48 | Log.d(TAG, "No activity found for DVB-T handling");
49 | }
50 | }
51 |
52 | finish();
53 | }
54 | }
--------------------------------------------------------------------------------
/dvbservice/src/main/java/info/martinmarinov/dvbservice/dialogs/ListPickerFragmentDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbservice.dialogs;
22 |
23 | import android.app.AlertDialog;
24 | import android.app.Dialog;
25 | import android.content.Context;
26 | import android.content.DialogInterface;
27 | import android.os.Bundle;
28 | import androidx.annotation.NonNull;
29 | import androidx.fragment.app.FragmentManager;
30 |
31 | import java.io.Serializable;
32 | import java.util.ArrayList;
33 | import java.util.List;
34 |
35 | public class ListPickerFragmentDialog extends ShowOneInstanceFragmentDialog {
36 | private static final String DIALOG_TAG = ListPickerFragmentDialog.class.getSimpleName();
37 |
38 | private static final String ARGS_SIZE = "argsSize";
39 | private static final String ARG_ID = "arg";
40 |
41 | private static String getArgKey(int id) {
42 | return ARG_ID + id;
43 | }
44 |
45 | public static void showOneInstanceOnly(FragmentManager fragmentManager, List options) {
46 | ListPickerFragmentDialog dialog = new ListPickerFragmentDialog<>();
47 |
48 | Bundle args = new Bundle();
49 | args.putInt(ARGS_SIZE, options.size());
50 | for (int i = 0; i < options.size(); i++) {
51 | args.putSerializable(getArgKey(i), options.get(i));
52 | }
53 |
54 | dialog.showOneInstanceOnly(fragmentManager, DIALOG_TAG, args);
55 | }
56 |
57 | private OnSelected callback;
58 | private List options;
59 |
60 | @SuppressWarnings("unchecked")
61 | @Override
62 | public void onCreate(Bundle savedInstanceState) {
63 | super.onCreate(savedInstanceState);
64 | Bundle args = getArguments();
65 |
66 | int size = args.getInt(ARGS_SIZE);
67 | options = new ArrayList<>(size);
68 | for (int i = 0; i < size; i++) {
69 | options.add((T) args.getSerializable(getArgKey(i)));
70 | }
71 | }
72 |
73 | @SuppressWarnings("unchecked")
74 | @Override
75 | public void onAttach(Context context) {
76 | super.onAttach(context);
77 | callback = (OnSelected) getActivity();
78 | }
79 |
80 | @Override
81 | public @NonNull Dialog onCreateDialog(Bundle savedInstanceState) {
82 | String[] strings = new String[options.size()];
83 | for (int i = 0; i < strings.length; i++) strings[i] = options.get(i).toString();
84 | return new AlertDialog.Builder(getActivity())
85 | .setCancelable(true)
86 | .setItems(strings, new DialogInterface.OnClickListener() {
87 | @Override
88 | public void onClick(DialogInterface dialog, int which) {
89 | callback.onListPickerDialogItemSelected(options.get(which));
90 | }
91 | })
92 | .create();
93 | }
94 |
95 | @Override
96 | public void onCancel(DialogInterface dialog) {
97 | callback.onListPickerDialogCanceled();
98 | }
99 |
100 | public interface OnSelected {
101 | void onListPickerDialogItemSelected(T item);
102 | void onListPickerDialogCanceled();
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/dvbservice/src/main/java/info/martinmarinov/dvbservice/dialogs/ShowOneInstanceFragmentDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbservice.dialogs;
22 |
23 | import android.os.Bundle;
24 |
25 | import androidx.appcompat.app.AppCompatDialogFragment;
26 | import androidx.fragment.app.Fragment;
27 | import androidx.fragment.app.FragmentManager;
28 | import androidx.fragment.app.FragmentTransaction;
29 |
30 | public class ShowOneInstanceFragmentDialog extends AppCompatDialogFragment {
31 | public void showOneInstanceOnly(FragmentManager fragmentManager, String tag, Bundle args) {
32 | // ensure only one instance is present and close existing instances
33 | FragmentTransaction ft = fragmentManager.beginTransaction();
34 | Fragment prev = fragmentManager.findFragmentByTag(tag);
35 | if (prev != null) ft.remove(prev);
36 | ft.addToBackStack(null);
37 |
38 | // set arguments and launch
39 | setArguments(args);
40 | try {
41 | show(ft, tag);
42 | } catch (IllegalStateException e) {
43 | // If we try to show an exception while driver is dying
44 | e.printStackTrace();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/dvbservice/src/main/java/info/martinmarinov/dvbservice/tools/InetAddressTools.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbservice.tools;
22 |
23 | import java.net.InetAddress;
24 | import java.net.UnknownHostException;
25 |
26 | public class InetAddressTools {
27 | private final static InetAddress LOCAL_LOOPBACK;
28 |
29 | static {
30 | try {
31 | LOCAL_LOOPBACK = InetAddress.getByName("127.0.0.1");
32 | } catch (UnknownHostException e) {
33 | throw new RuntimeException(e);
34 | }
35 | }
36 |
37 | public static InetAddress getLocalLoopback() {
38 | return LOCAL_LOOPBACK;
39 | }
40 | }
--------------------------------------------------------------------------------
/dvbservice/src/main/java/info/martinmarinov/dvbservice/tools/StackTraceSerializer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbservice.tools;
22 |
23 | import java.io.ByteArrayOutputStream;
24 | import java.io.PrintStream;
25 | import java.io.UnsupportedEncodingException;
26 |
27 | public class StackTraceSerializer {
28 | public static String serialize(Throwable t) {
29 | ByteArrayOutputStream buff = new ByteArrayOutputStream();
30 | PrintStream ps = new PrintStream(buff);
31 | t.printStackTrace(ps);
32 | try {
33 | return buff.toString("UTF-8");
34 | } catch (UnsupportedEncodingException e) {
35 | throw new RuntimeException(e);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/dvbservice/src/main/java/info/martinmarinov/dvbservice/tools/TsDumpFileUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbservice.tools;
22 |
23 | import android.content.Context;
24 | import android.content.res.Resources;
25 | import androidx.annotation.VisibleForTesting;
26 | import android.util.Log;
27 |
28 | import java.io.File;
29 | import java.text.DateFormat;
30 | import java.text.SimpleDateFormat;
31 | import java.util.Date;
32 | import java.util.LinkedList;
33 | import java.util.List;
34 | import java.util.Locale;
35 |
36 | import info.martinmarinov.drivers.DvbDevice;
37 | import info.martinmarinov.drivers.file.DvbFileDevice;
38 |
39 | public class TsDumpFileUtils {
40 | private final static String TAG = TsDumpFileUtils.class.getSimpleName();
41 |
42 | private final static Locale DEFAULT_LOCALE = Locale.US;
43 | private final static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss", DEFAULT_LOCALE);
44 |
45 | private static File getRoot(Context ctx) {
46 | return ctx.getExternalFilesDir(null);
47 | }
48 |
49 | public static File getFor(Context ctx, long freq, long bandwidth, Date date) {
50 | File root = getRoot(ctx);
51 | String timestamp = DATE_FORMAT.format(date);
52 | String filename = String.format(DEFAULT_LOCALE, "mux_%d_%d_%s.ts", freq, bandwidth, timestamp);
53 | return new File(root, filename);
54 | }
55 |
56 | public static List getDevicesForAllRecordings(Context ctx) {
57 | LinkedList devices = new LinkedList<>();
58 | Resources resources = ctx.getResources();
59 | File root = getRoot(ctx);
60 | if (root == null) return devices;
61 | Log.d(TAG, "You can place ts files in "+root.getPath());
62 |
63 | File[] files = root.listFiles();
64 | for (File file : files) {
65 | FreqBandwidth freqAndBandwidth = getFreqAndBandwidth(file);
66 | if (freqAndBandwidth != null) {
67 | devices.add(new DvbFileDevice(resources, file, freqAndBandwidth.freq, freqAndBandwidth.bandwidth));
68 | }
69 | }
70 | return devices;
71 | }
72 |
73 | @VisibleForTesting
74 | static FreqBandwidth getFreqAndBandwidth(File file) {
75 | if (!"ts".equals(getExtension(file))) return null;
76 | String[] parts = file.getName().toLowerCase().split("_");
77 | if (parts.length != 4) return null;
78 | if (!"mux".equals(parts[0])) return null;
79 | try {
80 | long freq = Long.parseLong(parts[1]);
81 | long bandwidth = Long.parseLong(parts[2]);
82 | return new FreqBandwidth(freq, bandwidth);
83 | } catch (NumberFormatException ignored) {
84 | return null;
85 | }
86 | }
87 |
88 | private static String getExtension(File file) {
89 | String[] parts = file.getName().toLowerCase().split("\\.");
90 | if (parts.length == 0) return null;
91 | return parts[parts.length-1];
92 | }
93 |
94 | @VisibleForTesting
95 | static class FreqBandwidth {
96 | @VisibleForTesting
97 | final long freq, bandwidth;
98 |
99 | private FreqBandwidth(long freq, long bandwidth) {
100 | this.freq = freq;
101 | this.bandwidth = bandwidth;
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/dvbservice/src/main/res/drawable/ic_notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/dvbservice/src/main/res/drawable/ic_notification.png
--------------------------------------------------------------------------------
/dvbservice/src/main/res/layout/progress.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/dvbservice/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 | DVB-T Driver
23 | Selected device is no longer available
24 | USB TV tuner is running
25 |
26 |
--------------------------------------------------------------------------------
/dvbservice/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
23 |
31 |
--------------------------------------------------------------------------------
/dvbservice/src/test/java/info/martinmarinov/dvbservice/tools/StackTraceSerializerTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbservice.tools;
22 |
23 | import org.junit.Test;
24 |
25 | import java.io.IOException;
26 |
27 | import static junit.framework.Assert.assertTrue;
28 |
29 | public class StackTraceSerializerTest {
30 | @Test
31 | public void testSerialize() throws Exception {
32 | String serialization = StackTraceSerializer.serialize(new IOException("Test message"));
33 | assertTrue(serialization.startsWith("java.io.IOException: Test message\n" +
34 | "\tat "+StackTraceSerializerTest.class.getName()+"."));
35 | }
36 |
37 | }
--------------------------------------------------------------------------------
/dvbservice/src/test/java/info/martinmarinov/dvbservice/tools/TsDumpFileUtilsTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.dvbservice.tools;
22 |
23 | import android.content.Context;
24 |
25 | import org.junit.Before;
26 | import org.junit.Test;
27 | import org.mockito.Mock;
28 |
29 | import java.io.File;
30 | import java.util.Calendar;
31 | import java.util.Date;
32 | import java.util.GregorianCalendar;
33 |
34 | import static org.hamcrest.CoreMatchers.equalTo;
35 | import static org.hamcrest.CoreMatchers.is;
36 | import static org.hamcrest.CoreMatchers.nullValue;
37 | import static org.junit.Assert.assertThat;
38 | import static org.mockito.Matchers.anyString;
39 | import static org.mockito.Mockito.when;
40 | import static org.mockito.MockitoAnnotations.initMocks;
41 |
42 | public class TsDumpFileUtilsTest {
43 | private final static File ROOT = new File("/imaginary/root");
44 |
45 | @Mock
46 | private Context context;
47 |
48 | @Before
49 | public void setUp() {
50 | initMocks(this);
51 | when(context.getExternalFilesDir(anyString())).thenReturn(ROOT);
52 | }
53 |
54 | @Test
55 | public void testNameCreation() {
56 | File actual = TsDumpFileUtils.getFor(context, 506_000_000L, 8_000_000L, date(2017, 1, 10, 13, 4, 24));
57 | assertThat(actual, equalTo(new File(ROOT, "mux_506000000_8000000_20170110130424.ts")));
58 | }
59 |
60 | @SuppressWarnings("ConstantConditions") // yeah I know res could be know
61 | @Test
62 | public void testParsing() {
63 | TsDumpFileUtils.FreqBandwidth res =
64 | TsDumpFileUtils.getFreqAndBandwidth(new File(ROOT, "mux_506000000_8000000_20170110130424.ts"));
65 |
66 | assertThat(res.freq, is(506_000_000L));
67 | assertThat(res.bandwidth, is(8_000_000L));
68 | }
69 |
70 | @SuppressWarnings("ConstantConditions") // yeah I know res could be know
71 | @Test
72 | public void testParsing_withoutDate() {
73 | TsDumpFileUtils.FreqBandwidth res =
74 | TsDumpFileUtils.getFreqAndBandwidth(new File(ROOT, "mux_506000000_8000000_randomSuffix.ts"));
75 |
76 | assertThat(res.freq, is(506_000_000L));
77 | assertThat(res.bandwidth, is(8_000_000L));
78 | }
79 |
80 | @Test
81 | public void testUnparseable_RandomString() {
82 | TsDumpFileUtils.FreqBandwidth res =
83 | TsDumpFileUtils.getFreqAndBandwidth(new File(ROOT, "fsdjfmadjk3312"));
84 |
85 | assertThat(res, nullValue());
86 | }
87 |
88 | @Test
89 | public void testUnparseable_noExt() {
90 | TsDumpFileUtils.FreqBandwidth res =
91 | TsDumpFileUtils.getFreqAndBandwidth(new File(ROOT, "mux_506000000_8000000_20170110130424"));
92 |
93 | assertThat(res, nullValue());
94 | }
95 |
96 | @Test
97 | public void testUnparseable_noPrefix() {
98 | TsDumpFileUtils.FreqBandwidth res =
99 | TsDumpFileUtils.getFreqAndBandwidth(new File(ROOT, "506000000_8000000_20170110130424.ts"));
100 |
101 | assertThat(res, nullValue());
102 | }
103 |
104 | private static Date date(int year, int month, int day, int hour, int minute, int second) {
105 | Calendar c = new GregorianCalendar();
106 | c.set(Calendar.YEAR, year);
107 | c.set(Calendar.MONTH, month - 1);
108 | c.set(Calendar.DAY_OF_MONTH, day);
109 | c.set(Calendar.HOUR_OF_DAY, hour);
110 | c.set(Calendar.MINUTE, minute);
111 | c.set(Calendar.SECOND, second);
112 | return c.getTime();
113 | }
114 | }
--------------------------------------------------------------------------------
/feature_graphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/feature_graphic.png
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # This is an Android user space port of DVB-T Linux kernel modules.
3 | #
4 | # Copyright (C) 2022 by Signalware Ltd
5 | #
6 | # This program is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 2 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program; if not, write to the Free Software
18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | #
20 |
21 | # Project-wide Gradle settings.
22 | # IDE (e.g. Android Studio) users:
23 | # Gradle settings configured through the IDE *will override*
24 | # any settings specified in this file.
25 | # For more details on how to configure your build environment visit
26 | # http://www.gradle.org/docs/current/userguide/build_environment.html
27 | # Specifies the JVM arguments used for the daemon process.
28 | # The setting is particularly useful for tweaking memory settings.
29 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
30 | # When configured, Gradle will run in incubating parallel mode.
31 | # This option should only be used with decoupled projects. More details, visit
32 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
33 | # org.gradle.parallel=true
34 | # AndroidX package structure to make it clearer which packages are bundled with the
35 | # Android operating system, and which are packaged with your app's APK
36 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
37 | android.useAndroidX=true
38 | # Enables namespacing of each library's R class so that its R class includes only the
39 | # resources declared in the library itself and none from the library's dependencies,
40 | # thereby reducing the size of the R class for that library
41 | android.nonTransitiveRClass=true
42 | android.defaults.buildfeatures.buildconfig=true
43 | android.nonFinalResIds=false
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #
2 | # This is an Android user space port of DVB-T Linux kernel modules.
3 | #
4 | # Copyright (C) 2022 by Signalware Ltd
5 | #
6 | # This program is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 2 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with this program; if not, write to the Free Software
18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | #
20 |
21 | #Tue Oct 04 18:55:38 BST 2022
22 | distributionBase=GRADLE_USER_HOME
23 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
24 | distributionPath=wrapper/dists
25 | zipStorePath=wrapper/dists
26 | zipStoreBase=GRADLE_USER_HOME
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/icon_amazon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/icon_amazon.png
--------------------------------------------------------------------------------
/icon_web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/signalwareltd/AndroidDvbDriver/f68f5e28cc4c854c0e66cca80fe0d1418e53638e/icon_web.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | pluginManagement {
22 | repositories {
23 | gradlePluginPortal()
24 | google()
25 | mavenCentral()
26 | }
27 | }
28 | dependencyResolutionManagement {
29 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
30 | repositories {
31 | google()
32 | mavenCentral()
33 | }
34 | }
35 | rootProject.name = "DVBDriver"
36 | include ':app'
37 | include ':drivers'
38 | include ':usbxfer'
39 | include ':dvbservice'
40 |
--------------------------------------------------------------------------------
/usbxfer/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/usbxfer/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | plugins {
22 | id 'com.android.library'
23 | }
24 |
25 | android {
26 | namespace 'info.martinmarinov.usbxfer'
27 | compileSdk 34
28 |
29 | defaultConfig {
30 | minSdk 21
31 | targetSdk 34
32 |
33 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
34 | consumerProguardFiles "consumer-rules.pro"
35 | }
36 |
37 | buildTypes {
38 | release {
39 | minifyEnabled false
40 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
41 | }
42 | }
43 | compileOptions {
44 | sourceCompatibility JavaVersion.VERSION_1_8
45 | targetCompatibility JavaVersion.VERSION_1_8
46 | }
47 | externalNativeBuild {
48 | cmake {
49 | path file('src/main/cpp/CMakeLists.txt')
50 | }
51 | }
52 | }
53 |
54 | dependencies {
55 | implementation 'androidx.appcompat:appcompat:1.5.1'
56 | implementation 'com.google.android.material:material:1.7.0'
57 | testImplementation 'junit:junit:4.13.2'
58 | testImplementation 'org.mockito:mockito-all:1.10.19'
59 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
60 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
61 | }
--------------------------------------------------------------------------------
/usbxfer/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # You can edit the include path and order by changing the proguardFiles
4 | # directive in build.gradle.
5 | #
6 | # For more details, see
7 | # http://developer.android.com/guide/developing/tools/proguard.html
8 |
9 | # Add any project specific keep options here:
10 |
11 | # If your project uses WebView with JS, uncomment the following
12 | # and specify the fully qualified class name to the JavaScript interface
13 | # class:
14 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
15 | # public *;
16 | #}
17 |
--------------------------------------------------------------------------------
/usbxfer/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
26 |
27 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/usbxfer/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.3.1)
2 |
3 | PROJECT( "UsbXfer" C )
4 |
5 | FILE ( GLOB_RECURSE SOURCES_LIB "*.c" )
6 |
7 | SET ( CMAKE_C_FLAGS "-Wall" )
8 | SET ( CMAKE_C_FLAGS_DEBUG "-g -DDEBUG")
9 | SET ( CMAKE_C_FLAGS_RELEASE "-O1 -DNDEBUG" ) # Reduce optimization level due to suspected deadlocks on some Samsung devices
10 |
11 | FIND_LIBRARY( LOG_LIB log )
12 | FIND_LIBRARY( OPEN_SLES_LIB OpenSLES )
13 |
14 | ADD_LIBRARY( ${PROJECT_NAME} SHARED ${SOURCES_LIB} )
15 | TARGET_LINK_LIBRARIES( ${PROJECT_NAME} ${LOG_LIB} ${OPEN_SLES_LIB} )
--------------------------------------------------------------------------------
/usbxfer/src/main/cpp/usbhispdbulk.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #define TAG "JNI_HiSpeedBulk"
9 |
10 | JNIEXPORT jint JNICALL
11 | Java_info_martinmarinov_usbxfer_UsbHiSpeedBulk_jni_1setInterface(JNIEnv *env, jclass type, jint fd,
12 | jint interfaceId, jint alternateSettings) {
13 | struct usbdevfs_setinterface setint;
14 | setint.altsetting = (unsigned int) alternateSettings;
15 | setint.interface = (unsigned int) interfaceId;
16 |
17 | if (ioctl(fd, USBDEVFS_SETINTERFACE, &setint)) {
18 | __android_log_print(ANDROID_LOG_ERROR, TAG, "ioctl error %d text %s", errno, strerror(errno));
19 | return -errno;
20 | } else {
21 | return 0;
22 | }
23 | }
--------------------------------------------------------------------------------
/usbxfer/src/main/java/info/martinmarinov/usbxfer/AlternateUsbInterface.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.usbxfer;
22 |
23 | import android.hardware.usb.UsbDeviceConnection;
24 | import android.hardware.usb.UsbInterface;
25 |
26 | import androidx.annotation.VisibleForTesting;
27 |
28 | import java.util.ArrayList;
29 | import java.util.List;
30 |
31 | /**
32 | * Sometimes there could be multiple UsbInterfaces with same ID. Android API only allows
33 | * using the UsbInterface#getAlternateSettings after Android 5.0 so this is a compatibility layer
34 | */
35 | public class AlternateUsbInterface {
36 | public static List forUsbInterface(UsbDeviceConnection deviceConnection, UsbInterface usbInterface) {
37 | byte[] rawDescriptors = deviceConnection.getRawDescriptors();
38 |
39 | List alternateSettings = new ArrayList<>(2);
40 | int offset = 0;
41 | while(offset < rawDescriptors.length) {
42 | int bLength = rawDescriptors[offset] & 0xFF;
43 | int bDescriptorType = rawDescriptors[offset + 1] & 0xFF;
44 |
45 | if (bDescriptorType == 0x04) {
46 | // interface descriptor, we are not interested
47 | int bInterfaceNumber = rawDescriptors[offset + 2] & 0xFF;
48 | int bAlternateSetting = rawDescriptors[offset + 3] & 0xFF;
49 |
50 | if (bInterfaceNumber == usbInterface.getId()) {
51 | alternateSettings.add(new AlternateUsbInterface(usbInterface, bAlternateSetting));
52 | }
53 | }
54 |
55 | // go to next structure
56 | offset += bLength;
57 | }
58 |
59 | if (alternateSettings.size() < 1) throw new IllegalStateException();
60 | return alternateSettings;
61 | }
62 |
63 | private final UsbInterface usbInterface;
64 | private final int alternateSettings;
65 |
66 | @VisibleForTesting
67 | AlternateUsbInterface(UsbInterface usbInterface, int alternateSettings) {
68 | this.usbInterface = usbInterface;
69 | this.alternateSettings = alternateSettings;
70 | }
71 |
72 | public UsbInterface getUsbInterface() {
73 | return usbInterface;
74 | }
75 |
76 | int getAlternateSettings() {
77 | return alternateSettings;
78 | }
79 |
80 | @SuppressWarnings("SimplifiableIfStatement")
81 | @Override
82 | public boolean equals(Object o) {
83 | if (this == o) return true;
84 | if (o == null || getClass() != o.getClass()) return false;
85 |
86 | AlternateUsbInterface that = (AlternateUsbInterface) o;
87 |
88 | if (alternateSettings != that.alternateSettings) return false;
89 | return usbInterface != null ? usbInterface.equals(that.usbInterface) : that.usbInterface == null;
90 |
91 | }
92 |
93 | @Override
94 | public int hashCode() {
95 | int result = usbInterface != null ? usbInterface.hashCode() : 0;
96 | result = 31 * result + alternateSettings;
97 | return result;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/usbxfer/src/main/java/info/martinmarinov/usbxfer/ByteSink.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.usbxfer;
22 |
23 | import java.io.IOException;
24 |
25 | public interface ByteSink {
26 | void consume(byte[] data, int length) throws IOException;
27 | }
28 |
--------------------------------------------------------------------------------
/usbxfer/src/main/java/info/martinmarinov/usbxfer/ByteSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.usbxfer;
22 |
23 | import java.io.Closeable;
24 | import java.io.IOException;
25 |
26 | public interface ByteSource extends Closeable {
27 | void open() throws IOException;
28 | void readNext(ByteSink sink) throws IOException, InterruptedException;
29 | }
30 |
--------------------------------------------------------------------------------
/usbxfer/src/main/java/info/martinmarinov/usbxfer/IoctlUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.usbxfer;
22 |
23 | import java.io.IOException;
24 |
25 | class IoctlUtils {
26 | /**
27 | * Handles return value of an ioctl request and throws an exception if necessary
28 | * @param ioctlRes
29 | * @throws IOException if return value is negative
30 | */
31 | public static void res(int ioctlRes) throws IOException {
32 | if (ioctlRes < 0) throw new IOException("ioctl returned "+ioctlRes);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/usbxfer/src/main/java/info/martinmarinov/usbxfer/IsoRequest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.usbxfer;
22 |
23 | import android.hardware.usb.UsbDeviceConnection;
24 | import android.hardware.usb.UsbEndpoint;
25 |
26 | import java.io.IOException;
27 |
28 | class IsoRequest {
29 | private final long urbPtr;
30 | private final int fd;
31 |
32 | IsoRequest(UsbDeviceConnection usbDeviceConnection, UsbEndpoint usbEndpoint, int id, int maxPackets, int packetSize) {
33 | this.fd = usbDeviceConnection.getFileDescriptor();
34 | urbPtr = jni_allocate_urb(usbEndpoint.getAddress(), id, maxPackets, packetSize);
35 | jni_reset_urb(urbPtr);
36 | }
37 |
38 | void reset() {
39 | jni_reset_urb(urbPtr);
40 | }
41 |
42 | void submit() throws IOException {
43 | IoctlUtils.res(jni_submit(urbPtr, fd));
44 | }
45 |
46 | void cancel() throws IOException {
47 | IoctlUtils.res(jni_cancel(urbPtr, fd));
48 | }
49 |
50 | int read(byte[] data) {
51 | return jni_read(urbPtr, data);
52 | }
53 |
54 | static int getReadyRequestId(UsbDeviceConnection usbDeviceConnection, boolean wait) {
55 | return jni_get_ready_packet_id(usbDeviceConnection.getFileDescriptor(), wait);
56 | }
57 |
58 | @Override
59 | protected void finalize() throws Throwable {
60 | super.finalize();
61 | jni_free_urb(urbPtr);
62 | }
63 |
64 | private static native long jni_allocate_urb(int endpointAddr, int id, int maxPackets, int packetSize);
65 | private static native void jni_reset_urb(long ptr);
66 | private static native void jni_free_urb(long ptr);
67 | private static native int jni_submit(long ptr, int fd);
68 | private static native int jni_cancel(long ptr, int fd);
69 | private static native int jni_read(long ptr, byte[] data);
70 | private static native int jni_get_ready_packet_id(int fd, boolean wait);
71 | }
72 |
--------------------------------------------------------------------------------
/usbxfer/src/main/java/info/martinmarinov/usbxfer/UsbBulkSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.usbxfer;
22 |
23 | import android.hardware.usb.UsbDeviceConnection;
24 | import android.hardware.usb.UsbEndpoint;
25 |
26 | import java.io.IOException;
27 |
28 | public class UsbBulkSource implements ByteSource {
29 | private final static int INITIAL_DELAY_BEFORE_BACKOFF = 1_000;
30 | private final static int MAX_BACKOFF = 10;
31 |
32 | private final UsbDeviceConnection usbDeviceConnection;
33 | private final UsbEndpoint usbEndpoint;
34 | private final AlternateUsbInterface usbInterface;
35 | private final int numRequests;
36 | private final int numPacketsPerReq;
37 |
38 | private UsbHiSpeedBulk usbHiSpeedBulk;
39 | private int backoff = -INITIAL_DELAY_BEFORE_BACKOFF;
40 |
41 | public UsbBulkSource(UsbDeviceConnection usbDeviceConnection, UsbEndpoint usbEndpoint, AlternateUsbInterface usbInterface, int numRequests, int numPacketsPerReq) {
42 | this.usbDeviceConnection = usbDeviceConnection;
43 | this.usbEndpoint = usbEndpoint;
44 | this.usbInterface = usbInterface;
45 | this.numRequests = numRequests;
46 | this.numPacketsPerReq = numPacketsPerReq;
47 | }
48 |
49 | @Override
50 | public void open() throws IOException {
51 | usbHiSpeedBulk = new UsbHiSpeedBulk(usbDeviceConnection, usbEndpoint, numRequests, numPacketsPerReq);
52 |
53 | usbHiSpeedBulk.setInterface(usbInterface);
54 | usbDeviceConnection.claimInterface(usbInterface.getUsbInterface(), true);
55 | usbHiSpeedBulk.start();
56 | }
57 |
58 | @Override
59 | public void readNext(ByteSink sink) throws IOException, InterruptedException {
60 | UsbHiSpeedBulk.Buffer read = usbHiSpeedBulk.read(false);
61 | if (read == null) {
62 | backoff++;
63 | if (backoff > 0) {
64 | Thread.sleep(backoff);
65 | } else {
66 | if (backoff % 3 == 0) Thread.sleep(1);
67 | }
68 | if (backoff > MAX_BACKOFF) {
69 | backoff = MAX_BACKOFF;
70 | }
71 | } else {
72 | backoff = -INITIAL_DELAY_BEFORE_BACKOFF;
73 | sink.consume(read.getData(), read.getLength());
74 | }
75 | }
76 |
77 | @Override
78 | public void close() throws IOException {
79 | usbHiSpeedBulk.stop();
80 | usbHiSpeedBulk.unsetInterface(usbInterface);
81 | usbDeviceConnection.releaseInterface(usbInterface.getUsbInterface());
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/usbxfer/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 | UsbIso
23 |
24 |
--------------------------------------------------------------------------------
/usbxfer/src/test/java/info/martinmarinov/usbxfer/AlternateUsbInterfaceTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This is an Android user space port of DVB-T Linux kernel modules.
3 | *
4 | * Copyright (C) 2022 by Signalware Ltd
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | package info.martinmarinov.usbxfer;
22 |
23 | import android.hardware.usb.UsbDeviceConnection;
24 | import android.hardware.usb.UsbInterface;
25 |
26 | import org.junit.Test;
27 |
28 | import static java.util.Arrays.asList;
29 | import static java.util.Collections.singletonList;
30 | import static org.hamcrest.core.IsEqual.equalTo;
31 | import static org.junit.Assert.assertThat;
32 | import static org.mockito.Mockito.mock;
33 | import static org.mockito.Mockito.when;
34 |
35 | public class AlternateUsbInterfaceTest {
36 | @Test
37 | public void getAlternateSetting() throws Exception {
38 | UsbDeviceConnection usbDeviceConnection = mockConnectionWithRawDescriptors(new byte[] {
39 | 18, 1, 0, 2, 0, 0, 0, 64, -38, 11, 56, 40, 0, 1, 1, 2, 3, 1, // Device Descriptor
40 | 9, 2, 34, 0, 2, 1, 4, -128, -6, // Configuration Descriptor
41 | 9, 4, 0, 0, 1, -1, -1, -1, 5, // Interface Descriptor for interface 0 with alternate setting 0
42 | 9, 4, 0, 1, 1, -1, -1, -1, 5, // Interface Descriptor for interface 0 with alternate setting 1
43 | 7, 5, -127, 2, 0, 2, 0, // Endpoint Descriptor
44 | 9, 4, 1, 0, 0, -1, -1, -1, 5 // Interface Descriptor for interface 1 with alternate setting 0
45 | });
46 |
47 | // Interface 0 has alternate settings {0, 1}
48 | UsbInterface i0 = mockInterface(0);
49 | assertThat(AlternateUsbInterface.forUsbInterface(usbDeviceConnection, i0),
50 | equalTo(asList(new AlternateUsbInterface(i0, 0), new AlternateUsbInterface(i0, 1))));
51 |
52 | // Interface 1 has alternate settings {0}
53 | UsbInterface i1 = mockInterface(1);
54 | assertThat(AlternateUsbInterface.forUsbInterface(usbDeviceConnection, i1),
55 | equalTo(singletonList(new AlternateUsbInterface(i1, 0))));
56 | }
57 |
58 | private static UsbInterface mockInterface(int id) {
59 | UsbInterface usbInterface = mock(UsbInterface.class);
60 | when(usbInterface.getId()).thenReturn(id);
61 | return usbInterface;
62 | }
63 |
64 | private static UsbDeviceConnection mockConnectionWithRawDescriptors(byte[] rawDescriptors) {
65 | UsbDeviceConnection usbDeviceConnection = mock(UsbDeviceConnection.class);
66 | when(usbDeviceConnection.getRawDescriptors()).thenReturn(rawDescriptors);
67 | return usbDeviceConnection;
68 | }
69 | }
--------------------------------------------------------------------------------