首页 > 代码库 > 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 }
View Code

 

今天刚好加了一个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