首页 > 代码库 > linux内核debug的一种方式:procfs
linux内核debug的一种方式:procfs
1 #include <linux/module.h> 2 3 #include <linux/compat.h> 4 #include <linux/types.h> 5 #include <linux/errno.h> 6 #include <linux/kernel.h> 7 #include <linux/major.h> 8 #include <linux/slab.h> 9 #include <linux/mm.h> 10 #include <linux/mman.h> 11 #include <linux/vt.h> 12 #include <linux/init.h> 13 #include <linux/linux_logo.h> 14 #include <linux/proc_fs.h> 15 #include <linux/seq_file.h> 16 #include <linux/console.h> 17 #include <linux/kmod.h> 18 #include <linux/err.h> 19 #include <linux/device.h> 20 #include <linux/efi.h> 21 #include <linux/fb.h> 22 #include <linux/delay.h> 23 #include <linux/version.h> 24 #include <linux/kthread.h> 25 #include <linux/poll.h> 26 27 /*Proc based contron intertace*/ 28 #define AUDIO_DEBUG_PROC_DIR "audio" 29 #define AUDIO_DEBUG_PROC_INFO "debuginfo" 30 #define MAX_BUF_WT_LEN 200 //do not bigger than one page size 1024 bytes 31 #define MAX_BUF_RD_LEN 2048 32 33 static struct proc_dir_entry *audio_proc_dir = NULL; 34 static struct proc_dir_entry *audio_proc_dbginfo_file = NULL; 35 36 static struct deca_device *audio_deca_dev=NULL; 37 static struct snd_device *audio_snd_dev=NULL; 38 39 static char *audio_info_buffer = NULL; 40 static __u32 g_dbg_show_en = 0; 41 static __u32 g_dbg_show_interval = 1; 42 static struct mutex audio_dbg_mutex; 43 wait_queue_head_t audio_dbg_wq; 44 static struct task_struct *audio_dbg_show_thread_ptr; 45 46 static char *audio_state(unsigned long state) 47 { 48 char *ret = NULL; 49 switch(state) 50 { 51 case 0: 52 ret="DETACH"; 53 break; 54 case 1: 55 ret="ATTACH"; 56 break; 57 case 2: 58 ret="IDLE"; 59 break; 60 case 4: 61 ret="PLAY"; 62 break; 63 case 8: 64 ret="PAUSE"; 65 break; 66 default: 67 ret="UNKNOWN"; 68 break; 69 } 70 return ret; 71 } 72 static char *audio_sub_state(unsigned long state) 73 { 74 char *ret = NULL; 75 switch(state) 76 { 77 case 0: 78 ret="IDLE"; 79 break; 80 case 1: 81 ret="NORMAL"; 82 break; 83 case 2: 84 ret="NO DATA"; 85 break; 86 case 4: 87 ret="NO BUFF"; 88 break; 89 default: 90 ret="UNKNOWN"; 91 break; 92 } 93 return ret; 94 } 95 static int audio_read_debug_info(char * buffer) 96 { 97 int len = 0; 98 unsigned long len_max = MAX_BUF_RD_LEN - 100; 99 struct audio_dbg_info dbg_info;100 101 if(!audio_deca_dev || !audio_snd_dev)102 {103 return -EUNATCH;104 }105 106 if (RET_SUCCESS == deca_io_control(audio_deca_dev, DECA_GET_DBG_INFO, (UINT32)(&dbg_info)))107 {108 len += sprintf(&buffer[len],"\ndesc enable : %s\n", (1==dbg_info.snd.ad_en)?"yes":"no");109 if (len_max <= len)110 goto out;111 112 len += sprintf(&buffer[len],"deca state : %s(%d)\n", audio_state(dbg_info.deca.state), (int)dbg_info.deca.state);113 if (len_max <= len)114 goto out;115 116 len += sprintf(&buffer[len],"deca sub state : %s(%d)\n", audio_sub_state(dbg_info.deca.sub_state), (int)dbg_info.deca.sub_state);117 if (len_max <= len)118 goto out;119 120 len += sprintf(&buffer[len],"snd state : %s(%d)\n", audio_state(dbg_info.snd.state), (int)dbg_info.snd.state);121 if (len_max <= len)122 goto out;123 124 len += sprintf(&buffer[len],"snd sub state : %s(%d)\n", audio_sub_state(dbg_info.snd.sub_state), (int)dbg_info.snd.sub_state);125 if (len_max <= len)126 goto out;127 128 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");129 if (len_max <= len)130 goto out;131 len += sprintf(&buffer[len],"|BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) |\n");132 if (len_max <= len)133 goto out;134 135 /* deca buff info */136 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");137 if (len_max <= len)138 goto out;139 len += sprintf(&buffer[len],"|BS |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",140 (int)((dbg_info.deca.prog_bs_buff_rm*100)/(dbg_info.deca.prog_bs_buff_len)),141 (unsigned int)dbg_info.deca.prog_bs_buff_rm, (unsigned int)dbg_info.deca.prog_bs_buff_len,142 (int)((dbg_info.deca.desc_bs_buff_rm*100)/(dbg_info.deca.desc_bs_buff_len)),143 (unsigned int)dbg_info.deca.desc_bs_buff_rm, (unsigned int)dbg_info.deca.desc_bs_buff_len);144 if (len_max <= len)145 goto out;146 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");147 if (len_max <= len)148 goto out;149 len += sprintf(&buffer[len],"|CB |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",150 (int)((dbg_info.deca.prog_cb_buff_rm*100)/(dbg_info.deca.prog_cb_buff_len)),151 (unsigned int)dbg_info.deca.prog_cb_buff_rm, (unsigned int)dbg_info.deca.prog_cb_buff_len,152 (int)((dbg_info.deca.desc_cb_buff_rm*100)/(dbg_info.deca.desc_cb_buff_len)),153 (unsigned int)dbg_info.deca.desc_cb_buff_rm, (unsigned int)dbg_info.deca.desc_cb_buff_len);154 if (len_max <= len)155 goto out;156 157 /* snd buff info */158 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");159 if (len_max <= len)160 goto out;161 len += sprintf(&buffer[len],"|SYNC |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",162 (int)((dbg_info.snd.sync_buff_pcm_rm*100)/(dbg_info.snd.sync_buff_pcm_len)),163 (unsigned int)dbg_info.snd.sync_buff_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_pcm_len,164 (int)((dbg_info.snd.sync_buff_desc_pcm_rm*100)/(dbg_info.snd.sync_buff_desc_pcm_len)),165 (unsigned int)dbg_info.snd.sync_buff_desc_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_desc_pcm_len,166 (int)((dbg_info.snd.sync_buff_dd_rm*100)/(dbg_info.snd.sync_buff_dd_len)),167 (unsigned int)dbg_info.snd.sync_buff_dd_rm, (unsigned int)dbg_info.snd.sync_buff_dd_len,168 (int)((dbg_info.snd.sync_buff_ddp_rm*100)/(dbg_info.snd.sync_buff_ddp_len)),169 (unsigned int)dbg_info.snd.sync_buff_ddp_rm, (unsigned int)dbg_info.snd.sync_buff_ddp_len );170 if (len_max <= len)171 goto out;172 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");173 if (len_max <= len)174 goto out;175 len += sprintf(&buffer[len],"|DMA |%03d%%(%05x/%05x) | |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",176 (int)((dbg_info.snd.dma_buff_pcm_rm*100)/(dbg_info.snd.dma_buff_pcm_len)),177 (unsigned int)dbg_info.snd.dma_buff_pcm_rm, (unsigned int)dbg_info.snd.dma_buff_pcm_len,178 (int)((dbg_info.snd.dma_buff_dd_rm*100)/(dbg_info.snd.dma_buff_dd_len)),179 (unsigned int)dbg_info.snd.dma_buff_dd_rm, (unsigned int)dbg_info.snd.dma_buff_dd_len,180 (int)((dbg_info.snd.dma_buff_ddp_rm*100)/(dbg_info.snd.dma_buff_ddp_len)),181 (unsigned int)dbg_info.snd.dma_buff_ddp_rm, (unsigned int)dbg_info.snd.dma_buff_ddp_len );182 if (len_max <= len)183 goto out;184 185 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n\n");186 if (len_max <= len)187 goto out;188 }189 190 out:191 return len;192 }193 194 static int audio_show_debug_info(void)195 {196 struct audio_dbg_info dbg_info;197 198 if(!audio_deca_dev || !audio_snd_dev)199 {200 return -EUNATCH;201 }202 203 if (RET_SUCCESS == deca_io_control(audio_deca_dev, DECA_GET_DBG_INFO, (UINT32)(&dbg_info)))204 {205 printk( "\ndesc enable : %s\n", (1==dbg_info.snd.ad_en)?"yes":"no");206 printk( "deca state : %s(%d)\n", audio_state(dbg_info.deca.state), (int)dbg_info.deca.state);207 printk( "deca sub state : %s(%d)\n", audio_sub_state(dbg_info.deca.sub_state), (int)dbg_info.deca.sub_state);208 printk( "snd state : %s(%d)\n", audio_state(dbg_info.snd.state), (int)dbg_info.snd.state);209 printk( "snd sub state : %s(%d)\n", audio_sub_state(dbg_info.snd.sub_state), (int)dbg_info.snd.sub_state);210 211 printk( "+-----+------------------+------------------+------------------+------------------+\n");212 printk( "|BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) |\n");213 214 /* deca buff info */215 printk( "+-----+------------------+------------------+------------------+------------------+\n");216 printk( "|BS |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",217 (int)((dbg_info.deca.prog_bs_buff_rm*100)/(dbg_info.deca.prog_bs_buff_len)),218 (unsigned int)dbg_info.deca.prog_bs_buff_rm, (unsigned int)dbg_info.deca.prog_bs_buff_len,219 (int)((dbg_info.deca.desc_bs_buff_rm*100)/(dbg_info.deca.desc_bs_buff_len)),220 (unsigned int)dbg_info.deca.desc_bs_buff_rm, (unsigned int)dbg_info.deca.desc_bs_buff_len);221 printk( "+-----+------------------+------------------+------------------+------------------+\n");222 printk( "|CB |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",223 (int)((dbg_info.deca.prog_cb_buff_rm*100)/(dbg_info.deca.prog_cb_buff_len)),224 (unsigned int)dbg_info.deca.prog_cb_buff_rm, (unsigned int)dbg_info.deca.prog_cb_buff_len,225 (int)((dbg_info.deca.desc_cb_buff_rm*100)/(dbg_info.deca.desc_cb_buff_len)),226 (unsigned int)dbg_info.deca.desc_cb_buff_rm, (unsigned int)dbg_info.deca.desc_cb_buff_len);227 228 /* snd buff info */229 printk( "+-----+------------------+------------------+------------------+------------------+\n");230 printk( "|SYNC |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",231 (int)((dbg_info.snd.sync_buff_pcm_rm*100)/(dbg_info.snd.sync_buff_pcm_len)),232 (unsigned int)dbg_info.snd.sync_buff_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_pcm_len,233 (int)((dbg_info.snd.sync_buff_desc_pcm_rm*100)/(dbg_info.snd.sync_buff_desc_pcm_len)),234 (unsigned int)dbg_info.snd.sync_buff_desc_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_desc_pcm_len,235 (int)((dbg_info.snd.sync_buff_dd_rm*100)/(dbg_info.snd.sync_buff_dd_len)),236 (unsigned int)dbg_info.snd.sync_buff_dd_rm, (unsigned int)dbg_info.snd.sync_buff_dd_len,237 (int)((dbg_info.snd.sync_buff_ddp_rm*100)/(dbg_info.snd.sync_buff_ddp_len)),238 (unsigned int)dbg_info.snd.sync_buff_ddp_rm, (unsigned int)dbg_info.snd.sync_buff_ddp_len );239 printk( "+-----+------------------+------------------+------------------+------------------+\n");240 printk( "|DMA |%03d%%(%05x/%05x) | |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",241 (int)((dbg_info.snd.dma_buff_pcm_rm*100)/(dbg_info.snd.dma_buff_pcm_len)),242 (unsigned int)dbg_info.snd.dma_buff_pcm_rm, (unsigned int)dbg_info.snd.dma_buff_pcm_len,243 (int)((dbg_info.snd.dma_buff_dd_rm*100)/(dbg_info.snd.dma_buff_dd_len)),244 (unsigned int)dbg_info.snd.dma_buff_dd_rm, (unsigned int)dbg_info.snd.dma_buff_dd_len,245 (int)((dbg_info.snd.dma_buff_ddp_rm*100)/(dbg_info.snd.dma_buff_ddp_len)),246 (unsigned int)dbg_info.snd.dma_buff_ddp_rm, (unsigned int)dbg_info.snd.dma_buff_ddp_len );247 248 printk( "+-----+------------------+------------------+------------------+------------------+\n\n");249 }250 251 return 0;252 }253 254 /*Process debug info*/255 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))256 static ssize_t audio_dbginfo_procfile_read(struct file *file, char __user *ubuf, size_t size, loff_t *ppos)257 {258 int len = 0;259 ssize_t ret_len = 0;260 261 if(audio_info_buffer)262 {263 memset(audio_info_buffer, 0, MAX_BUF_RD_LEN);264 len = audio_read_debug_info(audio_info_buffer);265 ret_len = simple_read_from_buffer(ubuf, size, ppos, audio_info_buffer, len);266 }267 268 return ret_len;269 }270 271 272 static ssize_t audio_dbginfo_procfile_write(struct file *file, const char __user * buffer, size_t count, loff_t *ppos)273 {274 char buf[MAX_BUF_WT_LEN] = {0};275 char *eq_ch = NULL;276 char *endp = NULL;277 unsigned long value = http://www.mamicode.com/0;278 279 if ((0>=count) || (MAX_BUF_WT_LEN<count))280 return 0;281 282 if (copy_from_user(buf, buffer, count))283 return -EFAULT;284 285 eq_ch = strstr(buf, "=");286 if (NULL == eq_ch)287 {288 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);289 return -EINVAL;290 }291 292 value = http://www.mamicode.com/simple_strtoul((char *)(eq_ch+1), &endp, 0);293 if ((eq_ch+1) == endp || value >= INT_MAX)294 {295 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", (eq_ch+1));296 return -EINVAL;297 }298 299 switch(*buf)300 {301 case ‘a‘:302 {303 if (strstr(buf, "ad_en"))304 {305 if (0==value || 1==value)306 {307 if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (UINT32)value))308 {309 printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, (int)value);310 return -EFAULT;311 }312 }313 else314 {315 printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);316 return -EINVAL;317 }318 }319 else320 {321 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);322 return -EINVAL;323 }324 break;325 }326 case ‘m‘:327 {328 if (strstr(buf, "monitor"))329 {330 if (0==value || 1==value)331 {332 g_dbg_show_en = value;333 if (g_dbg_show_en)334 {335 if (mutex_lock_interruptible(&audio_dbg_mutex))336 {337 return(-ERESTARTSYS);338 }339 wake_up_interruptible(&audio_dbg_wq);340 mutex_unlock(&audio_dbg_mutex);341 }342 }343 else344 {345 printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);346 return -EINVAL;347 }348 }349 else350 {351 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);352 return -EINVAL;353 }354 break;355 }356 case ‘i‘:357 {358 if (strstr(buf, "interval"))359 {360 if (0<value && 100>value)361 {362 g_dbg_show_interval = value;363 }364 else365 {366 printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);367 return -EINVAL;368 }369 }370 else371 {372 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);373 return -EINVAL;374 }375 break;376 }377 default:378 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);379 return -EINVAL;380 }381 382 383 #if 0 /* Modified by William.Zeng on 2016-10-14 18:57 */384 if ((1 != sscanf(buf, "ad_en=%d", &ad_en)) && (0==ad_en || 1==ad_en))385 {386 return 0;387 }388 if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (enum adec_desc_channel_enable)ad_en))389 {390 printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);391 return 0;392 }393 printk("\033[40;31m%s->%s.%u, set ad_en(%d) success!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);394 #endif /* #if 0, End of Modified by William.Zeng on 2016-10-14 18:57 */395 396 return count;397 }398 #else399 static int audio_dbginfo_procfile_read(char*buffer, char**buffer_localation, off_t offset,int buffer_length,int* eof, void *data )400 {401 int len = 0;402 len = audio_read_debug_info(buffer);403 *eof = 1;404 return len;405 }406 407 static int audio_dbginfo_procfile_write(struct file *filp, const char *buffer,unsigned long count,void *data)408 {409 char buf[MAX_BUF_WT_LEN] = {0};410 char *eq_ch = NULL;411 char *endp = NULL;412 unsigned long value = http://www.mamicode.com/0;413 414 if ((0>=count) || (MAX_BUF_WT_LEN<count))415 return 0;416 417 if (copy_from_user(buf, buffer, count))418 return -EFAULT;419 420 eq_ch = strstr(buf, "=");421 if (NULL == eq_ch)422 {423 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);424 return -EINVAL;425 }426 427 value = http://www.mamicode.com/simple_strtoul((char *)(eq_ch+1), &endp, 0);428 if ((eq_ch+1) == endp || value >= INT_MAX)429 {430 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", (eq_ch+1));431 return -EINVAL;432 }433 434 switch(*buf)435 {436 case ‘a‘:437 if (strstr(buf, "ad_en"))438 {439 if (0==value || 1==value)440 {441 if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (UINT32)value))442 {443 printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, (int)value);444 return -EFAULT;445 }446 }447 else448 {449 printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);450 return -EINVAL;451 }452 }453 else454 {455 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);456 return -EINVAL;457 }458 break;459 case ‘m‘:460 if (strstr(buf, "monitor"))461 {462 if (0==value || 1==value)463 {464 g_dbg_show_en = value;465 if (g_dbg_show_en)466 {467 if (mutex_lock_interruptible(&audio_dbg_mutex))468 {469 return(-ERESTARTSYS);470 }471 wake_up_interruptible(&audio_dbg_wq);472 mutex_unlock(&audio_dbg_mutex);473 }474 }475 else476 {477 printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);478 return -EINVAL;479 }480 }481 else482 {483 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);484 return -EINVAL;485 }486 break;487 default:488 printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);489 return -EINVAL;490 }491 492 493 #if 0 /* Modified by William.Zeng on 2016-10-14 18:57 */494 if ((1 != sscanf(buf, "ad_en=%d", &ad_en)) && (0==ad_en || 1==ad_en))495 {496 return 0;497 }498 if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (enum adec_desc_channel_enable)ad_en))499 {500 printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);501 return 0;502 }503 printk("\033[40;31m%s->%s.%u, set ad_en(%d) success!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);504 #endif /* #if 0, End of Modified by William.Zeng on 2016-10-14 18:57 */505 506 return count;507 }508 509 510 #endif511 512 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))513 static const struct file_operations audio_debuginfo_fops = {514 .read = audio_dbginfo_procfile_read,515 .write = audio_dbginfo_procfile_write,516 .llseek = default_llseek,517 };518 #endif519 520 static int audio_dbg_show_thread(void *param)521 {522 __s32 ret;523 524 for(;;)525 {526 if (mutex_lock_interruptible(&audio_dbg_mutex))527 {528 return(-ERESTARTSYS);529 }530 531 /* Wait until we are allowed to show debug info.532 */533 while (g_dbg_show_en == 0)534 {535 mutex_unlock(&audio_dbg_mutex);536 if (wait_event_interruptible(audio_dbg_wq, (1==g_dbg_show_en)))537 {538 return(-ERESTARTSYS);539 }540 if (mutex_lock_interruptible(&audio_dbg_mutex))541 {542 return(-ERESTARTSYS);543 }544 }545 546 ret = audio_show_debug_info();547 548 if (ret < 0)549 {550 g_dbg_show_en = 0;551 printk("\033[40;31m%s->%s.%u, audio_show_debug_info failed!.\033[0m\n", __FILE__, __FUNCTION__, __LINE__);552 }553 mutex_unlock(&audio_dbg_mutex);554 555 msleep(g_dbg_show_interval*1000);556 }557 558 return(0);559 }560 561 int audio_debug_procfs_init(void)562 {563 audio_info_buffer = kmalloc(MAX_BUF_RD_LEN, GFP_KERNEL);564 if (NULL == audio_info_buffer)565 {566 printk("kmall audio_info_buffer %d failed!!\n", MAX_BUF_RD_LEN);567 return -1;568 }569 mutex_init(&audio_dbg_mutex);570 init_waitqueue_head(&audio_dbg_wq);571 572 audio_proc_dir = proc_mkdir(AUDIO_DEBUG_PROC_DIR, NULL);573 if (audio_proc_dir == NULL) {574 printk("audio_debug_procfs_init create dir audio failed!!\n");575 kfree(audio_info_buffer);576 return -1;577 }578 579 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 10, 0))580 /*For Debug info*/581 audio_proc_dbginfo_file = proc_create(AUDIO_DEBUG_PROC_INFO,0644,audio_proc_dir, &audio_debuginfo_fops);582 #else583 /*For Debug info*/584 audio_proc_dbginfo_file = create_proc_entry(AUDIO_DEBUG_PROC_INFO,0644,audio_proc_dir);585 #endif586 if(audio_proc_dbginfo_file == NULL)587 {588 remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);589 kfree(audio_info_buffer);590 printk("Error:could not initialize /proc/%s/%s\n", AUDIO_DEBUG_PROC_DIR, AUDIO_DEBUG_PROC_INFO);591 return -1;592 }593 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))594 audio_proc_dbginfo_file->read_proc = audio_dbginfo_procfile_read;595 audio_proc_dbginfo_file->write_proc = audio_dbginfo_procfile_write;596 #endif597 598 audio_deca_dev=(struct deca_device*)hld_dev_get_by_type(NULL, HLD_DEV_TYPE_DECA);599 audio_snd_dev=(struct snd_device*)hld_dev_get_by_type(NULL, HLD_DEV_TYPE_SND);600 601 audio_dbg_show_thread_ptr = kthread_create(audio_dbg_show_thread, NULL, "audio_dbg");602 603 if (IS_ERR(audio_dbg_show_thread_ptr))604 {605 printk("%s,%d\n", __FUNCTION__, __LINE__);606 remove_proc_entry(AUDIO_DEBUG_PROC_INFO, audio_proc_dir);607 remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);608 kfree(audio_info_buffer);609 return(PTR_ERR(audio_dbg_show_thread_ptr));610 }611 612 wake_up_process(audio_dbg_show_thread_ptr);613 614 return 0;615 }616 617 618 void audio_debug_procfs_exit(void)619 {620 remove_proc_entry(AUDIO_DEBUG_PROC_INFO, audio_proc_dir);621 remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);622 623 if (audio_info_buffer)624 kfree(audio_info_buffer);625 626 return ;627 }
今天刚好加了一个procfs的目录,用于调试自己的驱动,使用方法如下:
目前支持如下几个命令:
cat /proc/audio/debuginfo --》查看audio信息
echo "ad_en=1" > /proc/audio/debuginfo --》动态打开/关闭audio desc,ad_en参数只能为0或1
echo "monitor=1" > /proc/audio/debuginfo --》wake up内核线程audio_dbg,默认每秒打印一次audio信息,monitor参数只能为0或1
echo "interval=5" > /proc/audio/debuginfo --》设置monitor打印的时间间隔(单位:秒),interval参数范围为[1,100]
audio打印信息如下:(其中表格记录的是audio各个buff的使用情况:剩余数据量百分比(剩余数据量/buff总大小),主要用于debug buff堵住的情况)
# cat /proc/audio/debuginfodesc enable : nodeca state : IDLE(2)deca sub state : IDLE(0)snd state : IDLE(2)snd sub state : IDLE(0)+-----+------------------+------------------+------------------+------------------+|BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) |+-----+------------------+------------------+------------------+------------------+|BS |000%(00000/0c800) |000%(00000/0c800) | | |+-----+------------------+------------------+------------------+------------------+|CB |000%(00000/000c8) |000%(00000/000c8) | | |+-----+------------------+------------------+------------------+------------------+|SYNC |000%(00000/60300) |000%(00000/60300) |000%(00000/60300) |000%(00000/60300) |+-----+------------------+------------------+------------------+------------------+|DMA |000%(00000/20100) | |000%(00000/20100) |000%(00000/20100) |+-----+------------------+------------------+------------------+------------------+
linux内核debug的一种方式:procfs
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。