1 // SPDX-License-Identifier: GPL-2.0+
3 // Copyright(c) 2013 Mauro Carvalho Chehab
5 #include "smscoreapi.h"
7 #include <linux/module.h>
8 #include <linux/slab.h>
9 #include <linux/init.h>
10 #include <linux/debugfs.h>
11 #include <linux/spinlock.h>
12 #include <linux/usb.h>
14 #include <media/dmxdev.h>
15 #include <media/dvbdev.h>
16 #include <media/dvb_demux.h>
17 #include <media/dvb_frontend.h>
21 static struct dentry
*smsdvb_debugfs_usb_root
;
23 struct smsdvb_debugfs
{
27 char stats_data
[PAGE_SIZE
];
31 wait_queue_head_t stats_queue
;
34 static void smsdvb_print_dvb_stats(struct smsdvb_debugfs
*debug_data
,
40 spin_lock(&debug_data
->lock
);
41 if (debug_data
->stats_count
) {
42 spin_unlock(&debug_data
->lock
);
46 buf
= debug_data
->stats_data
;
48 n
+= sysfs_emit_at(buf
, n
, "is_rf_locked = %d\n", p
->is_rf_locked
);
49 n
+= sysfs_emit_at(buf
, n
, "is_demod_locked = %d\n", p
->is_demod_locked
);
50 n
+= sysfs_emit_at(buf
, n
, "is_external_lna_on = %d\n", p
->is_external_lna_on
);
51 n
+= sysfs_emit_at(buf
, n
, "SNR = %d\n", p
->SNR
);
52 n
+= sysfs_emit_at(buf
, n
, "ber = %d\n", p
->ber
);
53 n
+= sysfs_emit_at(buf
, n
, "FIB_CRC = %d\n", p
->FIB_CRC
);
54 n
+= sysfs_emit_at(buf
, n
, "ts_per = %d\n", p
->ts_per
);
55 n
+= sysfs_emit_at(buf
, n
, "MFER = %d\n", p
->MFER
);
56 n
+= sysfs_emit_at(buf
, n
, "RSSI = %d\n", p
->RSSI
);
57 n
+= sysfs_emit_at(buf
, n
, "in_band_pwr = %d\n", p
->in_band_pwr
);
58 n
+= sysfs_emit_at(buf
, n
, "carrier_offset = %d\n", p
->carrier_offset
);
59 n
+= sysfs_emit_at(buf
, n
, "modem_state = %d\n", p
->modem_state
);
60 n
+= sysfs_emit_at(buf
, n
, "frequency = %d\n", p
->frequency
);
61 n
+= sysfs_emit_at(buf
, n
, "bandwidth = %d\n", p
->bandwidth
);
62 n
+= sysfs_emit_at(buf
, n
, "transmission_mode = %d\n", p
->transmission_mode
);
63 n
+= sysfs_emit_at(buf
, n
, "modem_state = %d\n", p
->modem_state
);
64 n
+= sysfs_emit_at(buf
, n
, "guard_interval = %d\n", p
->guard_interval
);
65 n
+= sysfs_emit_at(buf
, n
, "code_rate = %d\n", p
->code_rate
);
66 n
+= sysfs_emit_at(buf
, n
, "lp_code_rate = %d\n", p
->lp_code_rate
);
67 n
+= sysfs_emit_at(buf
, n
, "hierarchy = %d\n", p
->hierarchy
);
68 n
+= sysfs_emit_at(buf
, n
, "constellation = %d\n", p
->constellation
);
69 n
+= sysfs_emit_at(buf
, n
, "burst_size = %d\n", p
->burst_size
);
70 n
+= sysfs_emit_at(buf
, n
, "burst_duration = %d\n", p
->burst_duration
);
71 n
+= sysfs_emit_at(buf
, n
, "burst_cycle_time = %d\n", p
->burst_cycle_time
);
72 n
+= sysfs_emit_at(buf
, n
, "calc_burst_cycle_time = %d\n", p
->calc_burst_cycle_time
);
73 n
+= sysfs_emit_at(buf
, n
, "num_of_rows = %d\n", p
->num_of_rows
);
74 n
+= sysfs_emit_at(buf
, n
, "num_of_padd_cols = %d\n", p
->num_of_padd_cols
);
75 n
+= sysfs_emit_at(buf
, n
, "num_of_punct_cols = %d\n", p
->num_of_punct_cols
);
76 n
+= sysfs_emit_at(buf
, n
, "error_ts_packets = %d\n", p
->error_ts_packets
);
77 n
+= sysfs_emit_at(buf
, n
, "total_ts_packets = %d\n", p
->total_ts_packets
);
78 n
+= sysfs_emit_at(buf
, n
, "num_of_valid_mpe_tlbs = %d\n", p
->num_of_valid_mpe_tlbs
);
79 n
+= sysfs_emit_at(buf
, n
, "num_of_invalid_mpe_tlbs = %d\n", p
->num_of_invalid_mpe_tlbs
);
80 n
+= sysfs_emit_at(buf
, n
, "num_of_corrected_mpe_tlbs = %d\n",
81 p
->num_of_corrected_mpe_tlbs
);
82 n
+= sysfs_emit_at(buf
, n
, "ber_error_count = %d\n", p
->ber_error_count
);
83 n
+= sysfs_emit_at(buf
, n
, "ber_bit_count = %d\n", p
->ber_bit_count
);
84 n
+= sysfs_emit_at(buf
, n
, "sms_to_host_tx_errors = %d\n", p
->sms_to_host_tx_errors
);
85 n
+= sysfs_emit_at(buf
, n
, "pre_ber = %d\n", p
->pre_ber
);
86 n
+= sysfs_emit_at(buf
, n
, "cell_id = %d\n", p
->cell_id
);
87 n
+= sysfs_emit_at(buf
, n
, "dvbh_srv_ind_hp = %d\n", p
->dvbh_srv_ind_hp
);
88 n
+= sysfs_emit_at(buf
, n
, "dvbh_srv_ind_lp = %d\n", p
->dvbh_srv_ind_lp
);
89 n
+= sysfs_emit_at(buf
, n
, "num_mpe_received = %d\n", p
->num_mpe_received
);
91 debug_data
->stats_count
= n
;
92 spin_unlock(&debug_data
->lock
);
93 wake_up(&debug_data
->stats_queue
);
96 static void smsdvb_print_isdb_stats(struct smsdvb_debugfs
*debug_data
,
97 struct sms_isdbt_stats
*p
)
102 spin_lock(&debug_data
->lock
);
103 if (debug_data
->stats_count
) {
104 spin_unlock(&debug_data
->lock
);
108 buf
= debug_data
->stats_data
;
110 n
+= sysfs_emit_at(buf
, n
, "statistics_type = %d\t", p
->statistics_type
);
111 n
+= sysfs_emit_at(buf
, n
, "full_size = %d\n", p
->full_size
);
113 n
+= sysfs_emit_at(buf
, n
, "is_rf_locked = %d\t\t", p
->is_rf_locked
);
114 n
+= sysfs_emit_at(buf
, n
, "is_demod_locked = %d\t", p
->is_demod_locked
);
115 n
+= sysfs_emit_at(buf
, n
, "is_external_lna_on = %d\n", p
->is_external_lna_on
);
116 n
+= sysfs_emit_at(buf
, n
, "SNR = %d dB\t\t", p
->SNR
);
117 n
+= sysfs_emit_at(buf
, n
, "RSSI = %d dBm\t\t", p
->RSSI
);
118 n
+= sysfs_emit_at(buf
, n
, "in_band_pwr = %d dBm\n", p
->in_band_pwr
);
119 n
+= sysfs_emit_at(buf
, n
, "carrier_offset = %d\t", p
->carrier_offset
);
120 n
+= sysfs_emit_at(buf
, n
, "bandwidth = %d\t\t", p
->bandwidth
);
121 n
+= sysfs_emit_at(buf
, n
, "frequency = %d Hz\n", p
->frequency
);
122 n
+= sysfs_emit_at(buf
, n
, "transmission_mode = %d\t", p
->transmission_mode
);
123 n
+= sysfs_emit_at(buf
, n
, "modem_state = %d\t\t", p
->modem_state
);
124 n
+= sysfs_emit_at(buf
, n
, "guard_interval = %d\n", p
->guard_interval
);
125 n
+= sysfs_emit_at(buf
, n
, "system_type = %d\t\t", p
->system_type
);
126 n
+= sysfs_emit_at(buf
, n
, "partial_reception = %d\t", p
->partial_reception
);
127 n
+= sysfs_emit_at(buf
, n
, "num_of_layers = %d\n", p
->num_of_layers
);
128 n
+= sysfs_emit_at(buf
, n
, "sms_to_host_tx_errors = %d\n", p
->sms_to_host_tx_errors
);
130 for (i
= 0; i
< 3; i
++) {
131 if (p
->layer_info
[i
].number_of_segments
< 1 ||
132 p
->layer_info
[i
].number_of_segments
> 13)
135 n
+= sysfs_emit_at(buf
, n
, "\nLayer %d\n", i
);
136 n
+= sysfs_emit_at(buf
, n
, "\tcode_rate = %d\t", p
->layer_info
[i
].code_rate
);
137 n
+= sysfs_emit_at(buf
, n
, "constellation = %d\n", p
->layer_info
[i
].constellation
);
138 n
+= sysfs_emit_at(buf
, n
, "\tber = %-5d\t", p
->layer_info
[i
].ber
);
139 n
+= sysfs_emit_at(buf
, n
, "\tber_error_count = %-5d\t",
140 p
->layer_info
[i
].ber_error_count
);
141 n
+= sysfs_emit_at(buf
, n
, "ber_bit_count = %-5d\n",
142 p
->layer_info
[i
].ber_bit_count
);
143 n
+= sysfs_emit_at(buf
, n
, "\tpre_ber = %-5d\t", p
->layer_info
[i
].pre_ber
);
144 n
+= sysfs_emit_at(buf
, n
, "\tts_per = %-5d\n", p
->layer_info
[i
].ts_per
);
145 n
+= sysfs_emit_at(buf
, n
, "\terror_ts_packets = %-5d\t",
146 p
->layer_info
[i
].error_ts_packets
);
147 n
+= sysfs_emit_at(buf
, n
, "total_ts_packets = %-5d\t",
148 p
->layer_info
[i
].total_ts_packets
);
149 n
+= sysfs_emit_at(buf
, n
, "ti_ldepth_i = %d\n", p
->layer_info
[i
].ti_ldepth_i
);
150 n
+= sysfs_emit_at(buf
, n
, "\tnumber_of_segments = %d\t",
151 p
->layer_info
[i
].number_of_segments
);
152 n
+= sysfs_emit_at(buf
, n
, "tmcc_errors = %d\n", p
->layer_info
[i
].tmcc_errors
);
155 debug_data
->stats_count
= n
;
156 spin_unlock(&debug_data
->lock
);
157 wake_up(&debug_data
->stats_queue
);
160 static void smsdvb_print_isdb_stats_ex(struct smsdvb_debugfs
*debug_data
,
161 struct sms_isdbt_stats_ex
*p
)
166 spin_lock(&debug_data
->lock
);
167 if (debug_data
->stats_count
) {
168 spin_unlock(&debug_data
->lock
);
172 buf
= debug_data
->stats_data
;
174 n
+= sysfs_emit_at(buf
, n
, "statistics_type = %d\t", p
->statistics_type
);
175 n
+= sysfs_emit_at(buf
, n
, "full_size = %d\n", p
->full_size
);
177 n
+= sysfs_emit_at(buf
, n
, "is_rf_locked = %d\t\t", p
->is_rf_locked
);
178 n
+= sysfs_emit_at(buf
, n
, "is_demod_locked = %d\t", p
->is_demod_locked
);
179 n
+= sysfs_emit_at(buf
, n
, "is_external_lna_on = %d\n", p
->is_external_lna_on
);
180 n
+= sysfs_emit_at(buf
, n
, "SNR = %d dB\t\t", p
->SNR
);
181 n
+= sysfs_emit_at(buf
, n
, "RSSI = %d dBm\t\t", p
->RSSI
);
182 n
+= sysfs_emit_at(buf
, n
, "in_band_pwr = %d dBm\n", p
->in_band_pwr
);
183 n
+= sysfs_emit_at(buf
, n
, "carrier_offset = %d\t", p
->carrier_offset
);
184 n
+= sysfs_emit_at(buf
, n
, "bandwidth = %d\t\t", p
->bandwidth
);
185 n
+= sysfs_emit_at(buf
, n
, "frequency = %d Hz\n", p
->frequency
);
186 n
+= sysfs_emit_at(buf
, n
, "transmission_mode = %d\t", p
->transmission_mode
);
187 n
+= sysfs_emit_at(buf
, n
, "modem_state = %d\t\t", p
->modem_state
);
188 n
+= sysfs_emit_at(buf
, n
, "guard_interval = %d\n", p
->guard_interval
);
189 n
+= sysfs_emit_at(buf
, n
, "system_type = %d\t\t", p
->system_type
);
190 n
+= sysfs_emit_at(buf
, n
, "partial_reception = %d\t", p
->partial_reception
);
191 n
+= sysfs_emit_at(buf
, n
, "num_of_layers = %d\n", p
->num_of_layers
);
192 n
+= sysfs_emit_at(buf
, n
, "segment_number = %d\t", p
->segment_number
);
193 n
+= sysfs_emit_at(buf
, n
, "tune_bw = %d\n", p
->tune_bw
);
195 for (i
= 0; i
< 3; i
++) {
196 if (p
->layer_info
[i
].number_of_segments
< 1 ||
197 p
->layer_info
[i
].number_of_segments
> 13)
200 n
+= sysfs_emit_at(buf
, n
, "\nLayer %d\n", i
);
201 n
+= sysfs_emit_at(buf
, n
, "\tcode_rate = %d\t", p
->layer_info
[i
].code_rate
);
202 n
+= sysfs_emit_at(buf
, n
, "constellation = %d\n", p
->layer_info
[i
].constellation
);
203 n
+= sysfs_emit_at(buf
, n
, "\tber = %-5d\t", p
->layer_info
[i
].ber
);
204 n
+= sysfs_emit_at(buf
, n
, "\tber_error_count = %-5d\t",
205 p
->layer_info
[i
].ber_error_count
);
206 n
+= sysfs_emit_at(buf
, n
, "ber_bit_count = %-5d\n",
207 p
->layer_info
[i
].ber_bit_count
);
208 n
+= sysfs_emit_at(buf
, n
, "\tpre_ber = %-5d\t", p
->layer_info
[i
].pre_ber
);
209 n
+= sysfs_emit_at(buf
, n
, "\tts_per = %-5d\n", p
->layer_info
[i
].ts_per
);
210 n
+= sysfs_emit_at(buf
, n
, "\terror_ts_packets = %-5d\t",
211 p
->layer_info
[i
].error_ts_packets
);
212 n
+= sysfs_emit_at(buf
, n
, "total_ts_packets = %-5d\t",
213 p
->layer_info
[i
].total_ts_packets
);
214 n
+= sysfs_emit_at(buf
, n
, "ti_ldepth_i = %d\n", p
->layer_info
[i
].ti_ldepth_i
);
215 n
+= sysfs_emit_at(buf
, n
, "\tnumber_of_segments = %d\t",
216 p
->layer_info
[i
].number_of_segments
);
217 n
+= sysfs_emit_at(buf
, n
, "tmcc_errors = %d\n", p
->layer_info
[i
].tmcc_errors
);
221 debug_data
->stats_count
= n
;
222 spin_unlock(&debug_data
->lock
);
224 wake_up(&debug_data
->stats_queue
);
227 static int smsdvb_stats_open(struct inode
*inode
, struct file
*file
)
229 struct smsdvb_client_t
*client
= inode
->i_private
;
230 struct smsdvb_debugfs
*debug_data
= client
->debug_data
;
232 kref_get(&debug_data
->refcount
);
234 spin_lock(&debug_data
->lock
);
235 debug_data
->stats_count
= 0;
236 debug_data
->stats_was_read
= false;
237 spin_unlock(&debug_data
->lock
);
239 file
->private_data
= debug_data
;
244 static void smsdvb_debugfs_data_release(struct kref
*ref
)
246 struct smsdvb_debugfs
*debug_data
;
248 debug_data
= container_of(ref
, struct smsdvb_debugfs
, refcount
);
252 static int smsdvb_stats_wait_read(struct smsdvb_debugfs
*debug_data
)
256 spin_lock(&debug_data
->lock
);
258 if (debug_data
->stats_was_read
)
261 rc
= debug_data
->stats_count
;
264 spin_unlock(&debug_data
->lock
);
268 static __poll_t
smsdvb_stats_poll(struct file
*file
, poll_table
*wait
)
270 struct smsdvb_debugfs
*debug_data
= file
->private_data
;
273 kref_get(&debug_data
->refcount
);
275 poll_wait(file
, &debug_data
->stats_queue
, wait
);
277 rc
= smsdvb_stats_wait_read(debug_data
);
278 kref_put(&debug_data
->refcount
, smsdvb_debugfs_data_release
);
280 return rc
> 0 ? EPOLLIN
| EPOLLRDNORM
: 0;
283 static ssize_t
smsdvb_stats_read(struct file
*file
, char __user
*user_buf
,
284 size_t nbytes
, loff_t
*ppos
)
287 struct smsdvb_debugfs
*debug_data
= file
->private_data
;
289 kref_get(&debug_data
->refcount
);
291 if (file
->f_flags
& O_NONBLOCK
) {
292 rc
= smsdvb_stats_wait_read(debug_data
);
298 rc
= wait_event_interruptible(debug_data
->stats_queue
,
299 smsdvb_stats_wait_read(debug_data
));
304 if (debug_data
->stats_was_read
) {
309 len
= debug_data
->stats_count
- *ppos
;
311 rc
= simple_read_from_buffer(user_buf
, nbytes
, ppos
,
312 debug_data
->stats_data
, len
);
316 if (*ppos
>= debug_data
->stats_count
) {
317 spin_lock(&debug_data
->lock
);
318 debug_data
->stats_was_read
= true;
319 spin_unlock(&debug_data
->lock
);
322 kref_put(&debug_data
->refcount
, smsdvb_debugfs_data_release
);
326 static int smsdvb_stats_release(struct inode
*inode
, struct file
*file
)
328 struct smsdvb_debugfs
*debug_data
= file
->private_data
;
330 spin_lock(&debug_data
->lock
);
331 debug_data
->stats_was_read
= true; /* return EOF to read() */
332 spin_unlock(&debug_data
->lock
);
333 wake_up_interruptible_sync(&debug_data
->stats_queue
);
335 kref_put(&debug_data
->refcount
, smsdvb_debugfs_data_release
);
336 file
->private_data
= NULL
;
341 static const struct file_operations debugfs_stats_ops
= {
342 .open
= smsdvb_stats_open
,
343 .poll
= smsdvb_stats_poll
,
344 .read
= smsdvb_stats_read
,
345 .release
= smsdvb_stats_release
,
346 .llseek
= generic_file_llseek
,
350 * Functions used by smsdvb, in order to create the interfaces
353 int smsdvb_debugfs_create(struct smsdvb_client_t
*client
)
355 struct smscore_device_t
*coredev
= client
->coredev
;
356 struct smsdvb_debugfs
*debug_data
;
358 if (!smsdvb_debugfs_usb_root
|| !coredev
->is_usb_device
)
361 debug_data
= kzalloc(sizeof(*client
->debug_data
), GFP_KERNEL
);
365 client
->debugfs
= debugfs_create_dir(coredev
->devpath
,
366 smsdvb_debugfs_usb_root
);
368 debugfs_create_file("stats", S_IRUGO
| S_IWUSR
, client
->debugfs
,
369 client
, &debugfs_stats_ops
);
371 client
->debug_data
= debug_data
;
372 client
->prt_dvb_stats
= smsdvb_print_dvb_stats
;
373 client
->prt_isdb_stats
= smsdvb_print_isdb_stats
;
374 client
->prt_isdb_stats_ex
= smsdvb_print_isdb_stats_ex
;
376 init_waitqueue_head(&debug_data
->stats_queue
);
377 spin_lock_init(&debug_data
->lock
);
378 kref_init(&debug_data
->refcount
);
383 void smsdvb_debugfs_release(struct smsdvb_client_t
*client
)
385 if (!client
->debugfs
)
388 client
->prt_dvb_stats
= NULL
;
389 client
->prt_isdb_stats
= NULL
;
390 client
->prt_isdb_stats_ex
= NULL
;
392 debugfs_remove_recursive(client
->debugfs
);
393 kref_put(&client
->debug_data
->refcount
, smsdvb_debugfs_data_release
);
395 client
->debug_data
= NULL
;
396 client
->debugfs
= NULL
;
399 void smsdvb_debugfs_register(void)
402 * FIXME: This was written to debug Siano USB devices. So, it creates
403 * the debugfs node under <debugfs>/usb.
404 * A similar logic would be needed for Siano sdio devices, but, in that
405 * case, usb_debug_root is not a good choice.
407 * Perhaps the right fix here would be to create another sysfs root
408 * node for sdio-based boards, but this may need some logic at sdio
411 smsdvb_debugfs_usb_root
= debugfs_create_dir("smsdvb", usb_debug_root
);
414 void smsdvb_debugfs_unregister(void)
416 if (!smsdvb_debugfs_usb_root
)
418 debugfs_remove_recursive(smsdvb_debugfs_usb_root
);
419 smsdvb_debugfs_usb_root
= NULL
;