1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Driver for Dummy Frontend |
4 | * |
5 | * Written by Emard <emard@softhome.net> |
6 | */ |
7 | |
8 | #include <linux/module.h> |
9 | #include <linux/init.h> |
10 | #include <linux/string.h> |
11 | #include <linux/slab.h> |
12 | |
13 | #include <media/dvb_frontend.h> |
14 | #include "dvb_dummy_fe.h" |
15 | |
16 | |
17 | struct dvb_dummy_fe_state { |
18 | struct dvb_frontend frontend; |
19 | }; |
20 | |
21 | |
22 | static int dvb_dummy_fe_read_status(struct dvb_frontend *fe, |
23 | enum fe_status *status) |
24 | { |
25 | *status = FE_HAS_SIGNAL |
26 | | FE_HAS_CARRIER |
27 | | FE_HAS_VITERBI |
28 | | FE_HAS_SYNC |
29 | | FE_HAS_LOCK; |
30 | |
31 | return 0; |
32 | } |
33 | |
34 | static int dvb_dummy_fe_read_ber(struct dvb_frontend *fe, u32 *ber) |
35 | { |
36 | *ber = 0; |
37 | return 0; |
38 | } |
39 | |
40 | static int dvb_dummy_fe_read_signal_strength(struct dvb_frontend *fe, |
41 | u16 *strength) |
42 | { |
43 | *strength = 0; |
44 | return 0; |
45 | } |
46 | |
47 | static int dvb_dummy_fe_read_snr(struct dvb_frontend *fe, u16 *snr) |
48 | { |
49 | *snr = 0; |
50 | return 0; |
51 | } |
52 | |
53 | static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) |
54 | { |
55 | *ucblocks = 0; |
56 | return 0; |
57 | } |
58 | |
59 | /* |
60 | * Should only be implemented if it actually reads something from the hardware. |
61 | * Also, it should check for the locks, in order to avoid report wrong data |
62 | * to userspace. |
63 | */ |
64 | static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe, |
65 | struct dtv_frontend_properties *p) |
66 | { |
67 | return 0; |
68 | } |
69 | |
70 | static int dvb_dummy_fe_set_frontend(struct dvb_frontend *fe) |
71 | { |
72 | if (fe->ops.tuner_ops.set_params) { |
73 | fe->ops.tuner_ops.set_params(fe); |
74 | if (fe->ops.i2c_gate_ctrl) |
75 | fe->ops.i2c_gate_ctrl(fe, 0); |
76 | } |
77 | |
78 | return 0; |
79 | } |
80 | |
81 | static int dvb_dummy_fe_sleep(struct dvb_frontend *fe) |
82 | { |
83 | return 0; |
84 | } |
85 | |
86 | static int dvb_dummy_fe_init(struct dvb_frontend *fe) |
87 | { |
88 | return 0; |
89 | } |
90 | |
91 | static int dvb_dummy_fe_set_tone(struct dvb_frontend *fe, |
92 | enum fe_sec_tone_mode tone) |
93 | { |
94 | return 0; |
95 | } |
96 | |
97 | static int dvb_dummy_fe_set_voltage(struct dvb_frontend *fe, |
98 | enum fe_sec_voltage voltage) |
99 | { |
100 | return 0; |
101 | } |
102 | |
103 | static void dvb_dummy_fe_release(struct dvb_frontend *fe) |
104 | { |
105 | struct dvb_dummy_fe_state *state = fe->demodulator_priv; |
106 | |
107 | kfree(objp: state); |
108 | } |
109 | |
110 | static const struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops; |
111 | |
112 | struct dvb_frontend *dvb_dummy_fe_ofdm_attach(void) |
113 | { |
114 | struct dvb_dummy_fe_state *state = NULL; |
115 | |
116 | /* allocate memory for the internal state */ |
117 | state = kzalloc(size: sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); |
118 | if (!state) |
119 | return NULL; |
120 | |
121 | /* create dvb_frontend */ |
122 | memcpy(&state->frontend.ops, |
123 | &dvb_dummy_fe_ofdm_ops, |
124 | sizeof(struct dvb_frontend_ops)); |
125 | |
126 | state->frontend.demodulator_priv = state; |
127 | return &state->frontend; |
128 | } |
129 | EXPORT_SYMBOL(dvb_dummy_fe_ofdm_attach); |
130 | |
131 | static const struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops; |
132 | |
133 | struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void) |
134 | { |
135 | struct dvb_dummy_fe_state *state = NULL; |
136 | |
137 | /* allocate memory for the internal state */ |
138 | state = kzalloc(size: sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); |
139 | if (!state) |
140 | return NULL; |
141 | |
142 | /* create dvb_frontend */ |
143 | memcpy(&state->frontend.ops, |
144 | &dvb_dummy_fe_qpsk_ops, |
145 | sizeof(struct dvb_frontend_ops)); |
146 | |
147 | state->frontend.demodulator_priv = state; |
148 | return &state->frontend; |
149 | } |
150 | EXPORT_SYMBOL(dvb_dummy_fe_qpsk_attach); |
151 | |
152 | static const struct dvb_frontend_ops dvb_dummy_fe_qam_ops; |
153 | |
154 | struct dvb_frontend *dvb_dummy_fe_qam_attach(void) |
155 | { |
156 | struct dvb_dummy_fe_state *state = NULL; |
157 | |
158 | /* allocate memory for the internal state */ |
159 | state = kzalloc(size: sizeof(struct dvb_dummy_fe_state), GFP_KERNEL); |
160 | if (!state) |
161 | return NULL; |
162 | |
163 | /* create dvb_frontend */ |
164 | memcpy(&state->frontend.ops, |
165 | &dvb_dummy_fe_qam_ops, |
166 | sizeof(struct dvb_frontend_ops)); |
167 | |
168 | state->frontend.demodulator_priv = state; |
169 | return &state->frontend; |
170 | } |
171 | EXPORT_SYMBOL(dvb_dummy_fe_qam_attach); |
172 | |
173 | static const struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = { |
174 | .delsys = { SYS_DVBT }, |
175 | .info = { |
176 | .name = "Dummy DVB-T" , |
177 | .frequency_min_hz = 0, |
178 | .frequency_max_hz = 863250 * kHz, |
179 | .frequency_stepsize_hz = 62500, |
180 | .caps = FE_CAN_FEC_1_2 | |
181 | FE_CAN_FEC_2_3 | |
182 | FE_CAN_FEC_3_4 | |
183 | FE_CAN_FEC_4_5 | |
184 | FE_CAN_FEC_5_6 | |
185 | FE_CAN_FEC_6_7 | |
186 | FE_CAN_FEC_7_8 | |
187 | FE_CAN_FEC_8_9 | |
188 | FE_CAN_FEC_AUTO | |
189 | FE_CAN_QAM_16 | |
190 | FE_CAN_QAM_64 | |
191 | FE_CAN_QAM_AUTO | |
192 | FE_CAN_TRANSMISSION_MODE_AUTO | |
193 | FE_CAN_GUARD_INTERVAL_AUTO | |
194 | FE_CAN_HIERARCHY_AUTO, |
195 | }, |
196 | |
197 | .release = dvb_dummy_fe_release, |
198 | |
199 | .init = dvb_dummy_fe_init, |
200 | .sleep = dvb_dummy_fe_sleep, |
201 | |
202 | .set_frontend = dvb_dummy_fe_set_frontend, |
203 | .get_frontend = dvb_dummy_fe_get_frontend, |
204 | |
205 | .read_status = dvb_dummy_fe_read_status, |
206 | .read_ber = dvb_dummy_fe_read_ber, |
207 | .read_signal_strength = dvb_dummy_fe_read_signal_strength, |
208 | .read_snr = dvb_dummy_fe_read_snr, |
209 | .read_ucblocks = dvb_dummy_fe_read_ucblocks, |
210 | }; |
211 | |
212 | static const struct dvb_frontend_ops dvb_dummy_fe_qam_ops = { |
213 | .delsys = { SYS_DVBC_ANNEX_A }, |
214 | .info = { |
215 | .name = "Dummy DVB-C" , |
216 | .frequency_min_hz = 51 * MHz, |
217 | .frequency_max_hz = 858 * MHz, |
218 | .frequency_stepsize_hz = 62500, |
219 | /* symbol_rate_min: SACLK/64 == (XIN/2)/64 */ |
220 | .symbol_rate_min = (57840000 / 2) / 64, |
221 | .symbol_rate_max = (57840000 / 2) / 4, /* SACLK/4 */ |
222 | .caps = FE_CAN_QAM_16 | |
223 | FE_CAN_QAM_32 | |
224 | FE_CAN_QAM_64 | |
225 | FE_CAN_QAM_128 | |
226 | FE_CAN_QAM_256 | |
227 | FE_CAN_FEC_AUTO | |
228 | FE_CAN_INVERSION_AUTO |
229 | }, |
230 | |
231 | .release = dvb_dummy_fe_release, |
232 | |
233 | .init = dvb_dummy_fe_init, |
234 | .sleep = dvb_dummy_fe_sleep, |
235 | |
236 | .set_frontend = dvb_dummy_fe_set_frontend, |
237 | .get_frontend = dvb_dummy_fe_get_frontend, |
238 | |
239 | .read_status = dvb_dummy_fe_read_status, |
240 | .read_ber = dvb_dummy_fe_read_ber, |
241 | .read_signal_strength = dvb_dummy_fe_read_signal_strength, |
242 | .read_snr = dvb_dummy_fe_read_snr, |
243 | .read_ucblocks = dvb_dummy_fe_read_ucblocks, |
244 | }; |
245 | |
246 | static const struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = { |
247 | .delsys = { SYS_DVBS }, |
248 | .info = { |
249 | .name = "Dummy DVB-S" , |
250 | .frequency_min_hz = 950 * MHz, |
251 | .frequency_max_hz = 2150 * MHz, |
252 | .frequency_stepsize_hz = 250 * kHz, |
253 | .frequency_tolerance_hz = 29500 * kHz, |
254 | .symbol_rate_min = 1000000, |
255 | .symbol_rate_max = 45000000, |
256 | .caps = FE_CAN_INVERSION_AUTO | |
257 | FE_CAN_FEC_1_2 | |
258 | FE_CAN_FEC_2_3 | |
259 | FE_CAN_FEC_3_4 | |
260 | FE_CAN_FEC_5_6 | |
261 | FE_CAN_FEC_7_8 | |
262 | FE_CAN_FEC_AUTO | |
263 | FE_CAN_QPSK |
264 | }, |
265 | |
266 | .release = dvb_dummy_fe_release, |
267 | |
268 | .init = dvb_dummy_fe_init, |
269 | .sleep = dvb_dummy_fe_sleep, |
270 | |
271 | .set_frontend = dvb_dummy_fe_set_frontend, |
272 | .get_frontend = dvb_dummy_fe_get_frontend, |
273 | |
274 | .read_status = dvb_dummy_fe_read_status, |
275 | .read_ber = dvb_dummy_fe_read_ber, |
276 | .read_signal_strength = dvb_dummy_fe_read_signal_strength, |
277 | .read_snr = dvb_dummy_fe_read_snr, |
278 | .read_ucblocks = dvb_dummy_fe_read_ucblocks, |
279 | |
280 | .set_voltage = dvb_dummy_fe_set_voltage, |
281 | .set_tone = dvb_dummy_fe_set_tone, |
282 | }; |
283 | |
284 | MODULE_DESCRIPTION("DVB DUMMY Frontend" ); |
285 | MODULE_AUTHOR("Emard" ); |
286 | MODULE_LICENSE("GPL" ); |
287 | |