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