This source file includes following definitions.
- smsdvb_print_dvb_stats
- smsdvb_print_isdb_stats
- smsdvb_print_isdb_stats_ex
- smsdvb_stats_open
- smsdvb_debugfs_data_release
- smsdvb_stats_wait_read
- smsdvb_stats_poll
- smsdvb_stats_read
- smsdvb_stats_release
- smsdvb_debugfs_create
- smsdvb_debugfs_release
- smsdvb_debugfs_register
- smsdvb_debugfs_unregister
1
2
3
4
5 #include "smscoreapi.h"
6
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>
13
14 #include <media/dmxdev.h>
15 #include <media/dvbdev.h>
16 #include <media/dvb_demux.h>
17 #include <media/dvb_frontend.h>
18
19 #include "smsdvb.h"
20
21 static struct dentry *smsdvb_debugfs_usb_root;
22
23 struct smsdvb_debugfs {
24 struct kref refcount;
25 spinlock_t lock;
26
27 char stats_data[PAGE_SIZE];
28 unsigned stats_count;
29 bool stats_was_read;
30
31 wait_queue_head_t stats_queue;
32 };
33
34 static void smsdvb_print_dvb_stats(struct smsdvb_debugfs *debug_data,
35 struct sms_stats *p)
36 {
37 int n = 0;
38 char *buf;
39
40 spin_lock(&debug_data->lock);
41 if (debug_data->stats_count) {
42 spin_unlock(&debug_data->lock);
43 return;
44 }
45
46 buf = debug_data->stats_data;
47
48 n += snprintf(&buf[n], PAGE_SIZE - n,
49 "is_rf_locked = %d\n", p->is_rf_locked);
50 n += snprintf(&buf[n], PAGE_SIZE - n,
51 "is_demod_locked = %d\n", p->is_demod_locked);
52 n += snprintf(&buf[n], PAGE_SIZE - n,
53 "is_external_lna_on = %d\n", p->is_external_lna_on);
54 n += snprintf(&buf[n], PAGE_SIZE - n,
55 "SNR = %d\n", p->SNR);
56 n += snprintf(&buf[n], PAGE_SIZE - n,
57 "ber = %d\n", p->ber);
58 n += snprintf(&buf[n], PAGE_SIZE - n,
59 "FIB_CRC = %d\n", p->FIB_CRC);
60 n += snprintf(&buf[n], PAGE_SIZE - n,
61 "ts_per = %d\n", p->ts_per);
62 n += snprintf(&buf[n], PAGE_SIZE - n,
63 "MFER = %d\n", p->MFER);
64 n += snprintf(&buf[n], PAGE_SIZE - n,
65 "RSSI = %d\n", p->RSSI);
66 n += snprintf(&buf[n], PAGE_SIZE - n,
67 "in_band_pwr = %d\n", p->in_band_pwr);
68 n += snprintf(&buf[n], PAGE_SIZE - n,
69 "carrier_offset = %d\n", p->carrier_offset);
70 n += snprintf(&buf[n], PAGE_SIZE - n,
71 "modem_state = %d\n", p->modem_state);
72 n += snprintf(&buf[n], PAGE_SIZE - n,
73 "frequency = %d\n", p->frequency);
74 n += snprintf(&buf[n], PAGE_SIZE - n,
75 "bandwidth = %d\n", p->bandwidth);
76 n += snprintf(&buf[n], PAGE_SIZE - n,
77 "transmission_mode = %d\n", p->transmission_mode);
78 n += snprintf(&buf[n], PAGE_SIZE - n,
79 "modem_state = %d\n", p->modem_state);
80 n += snprintf(&buf[n], PAGE_SIZE - n,
81 "guard_interval = %d\n", p->guard_interval);
82 n += snprintf(&buf[n], PAGE_SIZE - n,
83 "code_rate = %d\n", p->code_rate);
84 n += snprintf(&buf[n], PAGE_SIZE - n,
85 "lp_code_rate = %d\n", p->lp_code_rate);
86 n += snprintf(&buf[n], PAGE_SIZE - n,
87 "hierarchy = %d\n", p->hierarchy);
88 n += snprintf(&buf[n], PAGE_SIZE - n,
89 "constellation = %d\n", p->constellation);
90 n += snprintf(&buf[n], PAGE_SIZE - n,
91 "burst_size = %d\n", p->burst_size);
92 n += snprintf(&buf[n], PAGE_SIZE - n,
93 "burst_duration = %d\n", p->burst_duration);
94 n += snprintf(&buf[n], PAGE_SIZE - n,
95 "burst_cycle_time = %d\n", p->burst_cycle_time);
96 n += snprintf(&buf[n], PAGE_SIZE - n,
97 "calc_burst_cycle_time = %d\n",
98 p->calc_burst_cycle_time);
99 n += snprintf(&buf[n], PAGE_SIZE - n,
100 "num_of_rows = %d\n", p->num_of_rows);
101 n += snprintf(&buf[n], PAGE_SIZE - n,
102 "num_of_padd_cols = %d\n", p->num_of_padd_cols);
103 n += snprintf(&buf[n], PAGE_SIZE - n,
104 "num_of_punct_cols = %d\n", p->num_of_punct_cols);
105 n += snprintf(&buf[n], PAGE_SIZE - n,
106 "error_ts_packets = %d\n", p->error_ts_packets);
107 n += snprintf(&buf[n], PAGE_SIZE - n,
108 "total_ts_packets = %d\n", p->total_ts_packets);
109 n += snprintf(&buf[n], PAGE_SIZE - n,
110 "num_of_valid_mpe_tlbs = %d\n", p->num_of_valid_mpe_tlbs);
111 n += snprintf(&buf[n], PAGE_SIZE - n,
112 "num_of_invalid_mpe_tlbs = %d\n", p->num_of_invalid_mpe_tlbs);
113 n += snprintf(&buf[n], PAGE_SIZE - n,
114 "num_of_corrected_mpe_tlbs = %d\n", p->num_of_corrected_mpe_tlbs);
115 n += snprintf(&buf[n], PAGE_SIZE - n,
116 "ber_error_count = %d\n", p->ber_error_count);
117 n += snprintf(&buf[n], PAGE_SIZE - n,
118 "ber_bit_count = %d\n", p->ber_bit_count);
119 n += snprintf(&buf[n], PAGE_SIZE - n,
120 "sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
121 n += snprintf(&buf[n], PAGE_SIZE - n,
122 "pre_ber = %d\n", p->pre_ber);
123 n += snprintf(&buf[n], PAGE_SIZE - n,
124 "cell_id = %d\n", p->cell_id);
125 n += snprintf(&buf[n], PAGE_SIZE - n,
126 "dvbh_srv_ind_hp = %d\n", p->dvbh_srv_ind_hp);
127 n += snprintf(&buf[n], PAGE_SIZE - n,
128 "dvbh_srv_ind_lp = %d\n", p->dvbh_srv_ind_lp);
129 n += snprintf(&buf[n], PAGE_SIZE - n,
130 "num_mpe_received = %d\n", p->num_mpe_received);
131
132 debug_data->stats_count = n;
133 spin_unlock(&debug_data->lock);
134 wake_up(&debug_data->stats_queue);
135 }
136
137 static void smsdvb_print_isdb_stats(struct smsdvb_debugfs *debug_data,
138 struct sms_isdbt_stats *p)
139 {
140 int i, n = 0;
141 char *buf;
142
143 spin_lock(&debug_data->lock);
144 if (debug_data->stats_count) {
145 spin_unlock(&debug_data->lock);
146 return;
147 }
148
149 buf = debug_data->stats_data;
150
151 n += snprintf(&buf[n], PAGE_SIZE - n,
152 "statistics_type = %d\t", p->statistics_type);
153 n += snprintf(&buf[n], PAGE_SIZE - n,
154 "full_size = %d\n", p->full_size);
155
156 n += snprintf(&buf[n], PAGE_SIZE - n,
157 "is_rf_locked = %d\t\t", p->is_rf_locked);
158 n += snprintf(&buf[n], PAGE_SIZE - n,
159 "is_demod_locked = %d\t", p->is_demod_locked);
160 n += snprintf(&buf[n], PAGE_SIZE - n,
161 "is_external_lna_on = %d\n", p->is_external_lna_on);
162 n += snprintf(&buf[n], PAGE_SIZE - n,
163 "SNR = %d dB\t\t", p->SNR);
164 n += snprintf(&buf[n], PAGE_SIZE - n,
165 "RSSI = %d dBm\t\t", p->RSSI);
166 n += snprintf(&buf[n], PAGE_SIZE - n,
167 "in_band_pwr = %d dBm\n", p->in_band_pwr);
168 n += snprintf(&buf[n], PAGE_SIZE - n,
169 "carrier_offset = %d\t", p->carrier_offset);
170 n += snprintf(&buf[n], PAGE_SIZE - n,
171 "bandwidth = %d\t\t", p->bandwidth);
172 n += snprintf(&buf[n], PAGE_SIZE - n,
173 "frequency = %d Hz\n", p->frequency);
174 n += snprintf(&buf[n], PAGE_SIZE - n,
175 "transmission_mode = %d\t", p->transmission_mode);
176 n += snprintf(&buf[n], PAGE_SIZE - n,
177 "modem_state = %d\t\t", p->modem_state);
178 n += snprintf(&buf[n], PAGE_SIZE - n,
179 "guard_interval = %d\n", p->guard_interval);
180 n += snprintf(&buf[n], PAGE_SIZE - n,
181 "system_type = %d\t\t", p->system_type);
182 n += snprintf(&buf[n], PAGE_SIZE - n,
183 "partial_reception = %d\t", p->partial_reception);
184 n += snprintf(&buf[n], PAGE_SIZE - n,
185 "num_of_layers = %d\n", p->num_of_layers);
186 n += snprintf(&buf[n], PAGE_SIZE - n,
187 "sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
188
189 for (i = 0; i < 3; i++) {
190 if (p->layer_info[i].number_of_segments < 1 ||
191 p->layer_info[i].number_of_segments > 13)
192 continue;
193
194 n += snprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
195 n += snprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
196 p->layer_info[i].code_rate);
197 n += snprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
198 p->layer_info[i].constellation);
199 n += snprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
200 p->layer_info[i].ber);
201 n += snprintf(&buf[n], PAGE_SIZE - n, "\tber_error_count = %-5d\t",
202 p->layer_info[i].ber_error_count);
203 n += snprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
204 p->layer_info[i].ber_bit_count);
205 n += snprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
206 p->layer_info[i].pre_ber);
207 n += snprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
208 p->layer_info[i].ts_per);
209 n += snprintf(&buf[n], PAGE_SIZE - n, "\terror_ts_packets = %-5d\t",
210 p->layer_info[i].error_ts_packets);
211 n += snprintf(&buf[n], PAGE_SIZE - n, "total_ts_packets = %-5d\t",
212 p->layer_info[i].total_ts_packets);
213 n += snprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
214 p->layer_info[i].ti_ldepth_i);
215 n += snprintf(&buf[n], PAGE_SIZE - n,
216 "\tnumber_of_segments = %d\t",
217 p->layer_info[i].number_of_segments);
218 n += snprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
219 p->layer_info[i].tmcc_errors);
220 }
221
222 debug_data->stats_count = n;
223 spin_unlock(&debug_data->lock);
224 wake_up(&debug_data->stats_queue);
225 }
226
227 static void smsdvb_print_isdb_stats_ex(struct smsdvb_debugfs *debug_data,
228 struct sms_isdbt_stats_ex *p)
229 {
230 int i, n = 0;
231 char *buf;
232
233 spin_lock(&debug_data->lock);
234 if (debug_data->stats_count) {
235 spin_unlock(&debug_data->lock);
236 return;
237 }
238
239 buf = debug_data->stats_data;
240
241 n += snprintf(&buf[n], PAGE_SIZE - n,
242 "statistics_type = %d\t", p->statistics_type);
243 n += snprintf(&buf[n], PAGE_SIZE - n,
244 "full_size = %d\n", p->full_size);
245
246 n += snprintf(&buf[n], PAGE_SIZE - n,
247 "is_rf_locked = %d\t\t", p->is_rf_locked);
248 n += snprintf(&buf[n], PAGE_SIZE - n,
249 "is_demod_locked = %d\t", p->is_demod_locked);
250 n += snprintf(&buf[n], PAGE_SIZE - n,
251 "is_external_lna_on = %d\n", p->is_external_lna_on);
252 n += snprintf(&buf[n], PAGE_SIZE - n,
253 "SNR = %d dB\t\t", p->SNR);
254 n += snprintf(&buf[n], PAGE_SIZE - n,
255 "RSSI = %d dBm\t\t", p->RSSI);
256 n += snprintf(&buf[n], PAGE_SIZE - n,
257 "in_band_pwr = %d dBm\n", p->in_band_pwr);
258 n += snprintf(&buf[n], PAGE_SIZE - n,
259 "carrier_offset = %d\t", p->carrier_offset);
260 n += snprintf(&buf[n], PAGE_SIZE - n,
261 "bandwidth = %d\t\t", p->bandwidth);
262 n += snprintf(&buf[n], PAGE_SIZE - n,
263 "frequency = %d Hz\n", p->frequency);
264 n += snprintf(&buf[n], PAGE_SIZE - n,
265 "transmission_mode = %d\t", p->transmission_mode);
266 n += snprintf(&buf[n], PAGE_SIZE - n,
267 "modem_state = %d\t\t", p->modem_state);
268 n += snprintf(&buf[n], PAGE_SIZE - n,
269 "guard_interval = %d\n", p->guard_interval);
270 n += snprintf(&buf[n], PAGE_SIZE - n,
271 "system_type = %d\t\t", p->system_type);
272 n += snprintf(&buf[n], PAGE_SIZE - n,
273 "partial_reception = %d\t", p->partial_reception);
274 n += snprintf(&buf[n], PAGE_SIZE - n,
275 "num_of_layers = %d\n", p->num_of_layers);
276 n += snprintf(&buf[n], PAGE_SIZE - n, "segment_number = %d\t",
277 p->segment_number);
278 n += snprintf(&buf[n], PAGE_SIZE - n, "tune_bw = %d\n",
279 p->tune_bw);
280
281 for (i = 0; i < 3; i++) {
282 if (p->layer_info[i].number_of_segments < 1 ||
283 p->layer_info[i].number_of_segments > 13)
284 continue;
285
286 n += snprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
287 n += snprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
288 p->layer_info[i].code_rate);
289 n += snprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
290 p->layer_info[i].constellation);
291 n += snprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
292 p->layer_info[i].ber);
293 n += snprintf(&buf[n], PAGE_SIZE - n, "\tber_error_count = %-5d\t",
294 p->layer_info[i].ber_error_count);
295 n += snprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
296 p->layer_info[i].ber_bit_count);
297 n += snprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
298 p->layer_info[i].pre_ber);
299 n += snprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
300 p->layer_info[i].ts_per);
301 n += snprintf(&buf[n], PAGE_SIZE - n, "\terror_ts_packets = %-5d\t",
302 p->layer_info[i].error_ts_packets);
303 n += snprintf(&buf[n], PAGE_SIZE - n, "total_ts_packets = %-5d\t",
304 p->layer_info[i].total_ts_packets);
305 n += snprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
306 p->layer_info[i].ti_ldepth_i);
307 n += snprintf(&buf[n], PAGE_SIZE - n,
308 "\tnumber_of_segments = %d\t",
309 p->layer_info[i].number_of_segments);
310 n += snprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
311 p->layer_info[i].tmcc_errors);
312 }
313
314
315 debug_data->stats_count = n;
316 spin_unlock(&debug_data->lock);
317
318 wake_up(&debug_data->stats_queue);
319 }
320
321 static int smsdvb_stats_open(struct inode *inode, struct file *file)
322 {
323 struct smsdvb_client_t *client = inode->i_private;
324 struct smsdvb_debugfs *debug_data = client->debug_data;
325
326 kref_get(&debug_data->refcount);
327
328 spin_lock(&debug_data->lock);
329 debug_data->stats_count = 0;
330 debug_data->stats_was_read = false;
331 spin_unlock(&debug_data->lock);
332
333 file->private_data = debug_data;
334
335 return 0;
336 }
337
338 static void smsdvb_debugfs_data_release(struct kref *ref)
339 {
340 struct smsdvb_debugfs *debug_data;
341
342 debug_data = container_of(ref, struct smsdvb_debugfs, refcount);
343 kfree(debug_data);
344 }
345
346 static int smsdvb_stats_wait_read(struct smsdvb_debugfs *debug_data)
347 {
348 int rc = 1;
349
350 spin_lock(&debug_data->lock);
351
352 if (debug_data->stats_was_read)
353 goto exit;
354
355 rc = debug_data->stats_count;
356
357 exit:
358 spin_unlock(&debug_data->lock);
359 return rc;
360 }
361
362 static __poll_t smsdvb_stats_poll(struct file *file, poll_table *wait)
363 {
364 struct smsdvb_debugfs *debug_data = file->private_data;
365 int rc;
366
367 kref_get(&debug_data->refcount);
368
369 poll_wait(file, &debug_data->stats_queue, wait);
370
371 rc = smsdvb_stats_wait_read(debug_data);
372 kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
373
374 return rc > 0 ? EPOLLIN | EPOLLRDNORM : 0;
375 }
376
377 static ssize_t smsdvb_stats_read(struct file *file, char __user *user_buf,
378 size_t nbytes, loff_t *ppos)
379 {
380 int rc = 0, len;
381 struct smsdvb_debugfs *debug_data = file->private_data;
382
383 kref_get(&debug_data->refcount);
384
385 if (file->f_flags & O_NONBLOCK) {
386 rc = smsdvb_stats_wait_read(debug_data);
387 if (!rc) {
388 rc = -EWOULDBLOCK;
389 goto ret;
390 }
391 } else {
392 rc = wait_event_interruptible(debug_data->stats_queue,
393 smsdvb_stats_wait_read(debug_data));
394 if (rc < 0)
395 goto ret;
396 }
397
398 if (debug_data->stats_was_read) {
399 rc = 0;
400 goto ret;
401 }
402
403 len = debug_data->stats_count - *ppos;
404 if (len >= 0)
405 rc = simple_read_from_buffer(user_buf, nbytes, ppos,
406 debug_data->stats_data, len);
407 else
408 rc = 0;
409
410 if (*ppos >= debug_data->stats_count) {
411 spin_lock(&debug_data->lock);
412 debug_data->stats_was_read = true;
413 spin_unlock(&debug_data->lock);
414 }
415 ret:
416 kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
417 return rc;
418 }
419
420 static int smsdvb_stats_release(struct inode *inode, struct file *file)
421 {
422 struct smsdvb_debugfs *debug_data = file->private_data;
423
424 spin_lock(&debug_data->lock);
425 debug_data->stats_was_read = true;
426 spin_unlock(&debug_data->lock);
427 wake_up_interruptible_sync(&debug_data->stats_queue);
428
429 kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
430 file->private_data = NULL;
431
432 return 0;
433 }
434
435 static const struct file_operations debugfs_stats_ops = {
436 .open = smsdvb_stats_open,
437 .poll = smsdvb_stats_poll,
438 .read = smsdvb_stats_read,
439 .release = smsdvb_stats_release,
440 .llseek = generic_file_llseek,
441 };
442
443
444
445
446
447 int smsdvb_debugfs_create(struct smsdvb_client_t *client)
448 {
449 struct smscore_device_t *coredev = client->coredev;
450 struct dentry *d;
451 struct smsdvb_debugfs *debug_data;
452
453 if (!smsdvb_debugfs_usb_root || !coredev->is_usb_device)
454 return -ENODEV;
455
456 client->debugfs = debugfs_create_dir(coredev->devpath,
457 smsdvb_debugfs_usb_root);
458 if (IS_ERR_OR_NULL(client->debugfs)) {
459 pr_info("Unable to create debugfs %s directory.\n",
460 coredev->devpath);
461 return -ENODEV;
462 }
463
464 d = debugfs_create_file("stats", S_IRUGO | S_IWUSR, client->debugfs,
465 client, &debugfs_stats_ops);
466 if (!d) {
467 debugfs_remove(client->debugfs);
468 return -ENOMEM;
469 }
470
471 debug_data = kzalloc(sizeof(*client->debug_data), GFP_KERNEL);
472 if (!debug_data)
473 return -ENOMEM;
474
475 client->debug_data = debug_data;
476 client->prt_dvb_stats = smsdvb_print_dvb_stats;
477 client->prt_isdb_stats = smsdvb_print_isdb_stats;
478 client->prt_isdb_stats_ex = smsdvb_print_isdb_stats_ex;
479
480 init_waitqueue_head(&debug_data->stats_queue);
481 spin_lock_init(&debug_data->lock);
482 kref_init(&debug_data->refcount);
483
484 return 0;
485 }
486
487 void smsdvb_debugfs_release(struct smsdvb_client_t *client)
488 {
489 if (!client->debugfs)
490 return;
491
492 client->prt_dvb_stats = NULL;
493 client->prt_isdb_stats = NULL;
494 client->prt_isdb_stats_ex = NULL;
495
496 debugfs_remove_recursive(client->debugfs);
497 kref_put(&client->debug_data->refcount, smsdvb_debugfs_data_release);
498
499 client->debug_data = NULL;
500 client->debugfs = NULL;
501 }
502
503 void smsdvb_debugfs_register(void)
504 {
505 struct dentry *d;
506
507
508
509
510
511
512
513
514
515
516
517 d = debugfs_create_dir("smsdvb", usb_debug_root);
518 if (IS_ERR_OR_NULL(d)) {
519 pr_err("Couldn't create sysfs node for smsdvb\n");
520 return;
521 }
522 smsdvb_debugfs_usb_root = d;
523 }
524
525 void smsdvb_debugfs_unregister(void)
526 {
527 if (!smsdvb_debugfs_usb_root)
528 return;
529 debugfs_remove_recursive(smsdvb_debugfs_usb_root);
530 smsdvb_debugfs_usb_root = NULL;
531 }