linux内核debug的一种方式:procfs
- #include <linux/module.h>
- #include <linux/compat.h>
- #include <linux/types.h>
- #include <linux/errno.h>
- #include <linux/kernel.h>
- #include <linux/major.h>
- #include <linux/slab.h>
- #include <linux/mm.h>
- #include <linux/mman.h>
- #include <linux/vt.h>
- #include <linux/init.h>
- #include <linux/linux_logo.h>
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/console.h>
- #include <linux/kmod.h>
- #include <linux/err.h>
- #include <linux/device.h>
- #include <linux/efi.h>
- #include <linux/fb.h>
- #include <linux/delay.h>
- #include <linux/version.h>
- #include <linux/kthread.h>
- #include <linux/poll.h>
- /*Proc based contron intertace*/
- #define AUDIO_DEBUG_PROC_DIR "audio"
- #define AUDIO_DEBUG_PROC_INFO "debuginfo"
- #define MAX_BUF_WT_LEN 200 //do not bigger than one page size 1024 bytes
- #define MAX_BUF_RD_LEN 2048
- static struct proc_dir_entry *audio_proc_dir = NULL;
- static struct proc_dir_entry *audio_proc_dbginfo_file = NULL;
- static struct deca_device *audio_deca_dev=NULL;
- static struct snd_device *audio_snd_dev=NULL;
- static char *audio_info_buffer = NULL;
- static __u32 g_dbg_show_en = ;
- static __u32 g_dbg_show_interval = ;
- static struct mutex audio_dbg_mutex;
- wait_queue_head_t audio_dbg_wq;
- static struct task_struct *audio_dbg_show_thread_ptr;
- static char *audio_state(unsigned long state)
- {
- char *ret = NULL;
- switch(state)
- {
- case :
- ret="DETACH";
- break;
- case :
- ret="ATTACH";
- break;
- case :
- ret="IDLE";
- break;
- case :
- ret="PLAY";
- break;
- case :
- ret="PAUSE";
- break;
- default:
- ret="UNKNOWN";
- break;
- }
- return ret;
- }
- static char *audio_sub_state(unsigned long state)
- {
- char *ret = NULL;
- switch(state)
- {
- case :
- ret="IDLE";
- break;
- case :
- ret="NORMAL";
- break;
- case :
- ret="NO DATA";
- break;
- case :
- ret="NO BUFF";
- break;
- default:
- ret="UNKNOWN";
- break;
- }
- return ret;
- }
- static int audio_read_debug_info(char * buffer)
- {
- int len = ;
- unsigned long len_max = MAX_BUF_RD_LEN - ;
- struct audio_dbg_info dbg_info;
- if(!audio_deca_dev || !audio_snd_dev)
- {
- return -EUNATCH;
- }
- if (RET_SUCCESS == deca_io_control(audio_deca_dev, DECA_GET_DBG_INFO, (UINT32)(&dbg_info)))
- {
- len += sprintf(&buffer[len],"\ndesc enable : %s\n", (==dbg_info.snd.ad_en)?"yes":"no");
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"deca state : %s(%d)\n", audio_state(dbg_info.deca.state), (int)dbg_info.deca.state);
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"deca sub state : %s(%d)\n", audio_sub_state(dbg_info.deca.sub_state), (int)dbg_info.deca.sub_state);
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"snd state : %s(%d)\n", audio_state(dbg_info.snd.state), (int)dbg_info.snd.state);
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"snd sub state : %s(%d)\n", audio_sub_state(dbg_info.snd.sub_state), (int)dbg_info.snd.sub_state);
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"|BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) |\n");
- if (len_max <= len)
- goto out;
- /* deca buff info */
- len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"|BS |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",
- (int)((dbg_info.deca.prog_bs_buff_rm*)/(dbg_info.deca.prog_bs_buff_len)),
- (unsigned int)dbg_info.deca.prog_bs_buff_rm, (unsigned int)dbg_info.deca.prog_bs_buff_len,
- (int)((dbg_info.deca.desc_bs_buff_rm*)/(dbg_info.deca.desc_bs_buff_len)),
- (unsigned int)dbg_info.deca.desc_bs_buff_rm, (unsigned int)dbg_info.deca.desc_bs_buff_len);
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"|CB |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",
- (int)((dbg_info.deca.prog_cb_buff_rm*)/(dbg_info.deca.prog_cb_buff_len)),
- (unsigned int)dbg_info.deca.prog_cb_buff_rm, (unsigned int)dbg_info.deca.prog_cb_buff_len,
- (int)((dbg_info.deca.desc_cb_buff_rm*)/(dbg_info.deca.desc_cb_buff_len)),
- (unsigned int)dbg_info.deca.desc_cb_buff_rm, (unsigned int)dbg_info.deca.desc_cb_buff_len);
- if (len_max <= len)
- goto out;
- /* snd buff info */
- len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"|SYNC |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
- (int)((dbg_info.snd.sync_buff_pcm_rm*)/(dbg_info.snd.sync_buff_pcm_len)),
- (unsigned int)dbg_info.snd.sync_buff_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_pcm_len,
- (int)((dbg_info.snd.sync_buff_desc_pcm_rm*)/(dbg_info.snd.sync_buff_desc_pcm_len)),
- (unsigned int)dbg_info.snd.sync_buff_desc_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_desc_pcm_len,
- (int)((dbg_info.snd.sync_buff_dd_rm*)/(dbg_info.snd.sync_buff_dd_len)),
- (unsigned int)dbg_info.snd.sync_buff_dd_rm, (unsigned int)dbg_info.snd.sync_buff_dd_len,
- (int)((dbg_info.snd.sync_buff_ddp_rm*)/(dbg_info.snd.sync_buff_ddp_len)),
- (unsigned int)dbg_info.snd.sync_buff_ddp_rm, (unsigned int)dbg_info.snd.sync_buff_ddp_len );
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n");
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"|DMA |%03d%%(%05x/%05x) | |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
- (int)((dbg_info.snd.dma_buff_pcm_rm*)/(dbg_info.snd.dma_buff_pcm_len)),
- (unsigned int)dbg_info.snd.dma_buff_pcm_rm, (unsigned int)dbg_info.snd.dma_buff_pcm_len,
- (int)((dbg_info.snd.dma_buff_dd_rm*)/(dbg_info.snd.dma_buff_dd_len)),
- (unsigned int)dbg_info.snd.dma_buff_dd_rm, (unsigned int)dbg_info.snd.dma_buff_dd_len,
- (int)((dbg_info.snd.dma_buff_ddp_rm*)/(dbg_info.snd.dma_buff_ddp_len)),
- (unsigned int)dbg_info.snd.dma_buff_ddp_rm, (unsigned int)dbg_info.snd.dma_buff_ddp_len );
- if (len_max <= len)
- goto out;
- len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+\n\n");
- if (len_max <= len)
- goto out;
- }
- out:
- return len;
- }
- static int audio_show_debug_info(void)
- {
- struct audio_dbg_info dbg_info;
- if(!audio_deca_dev || !audio_snd_dev)
- {
- return -EUNATCH;
- }
- if (RET_SUCCESS == deca_io_control(audio_deca_dev, DECA_GET_DBG_INFO, (UINT32)(&dbg_info)))
- {
- printk( "\ndesc enable : %s\n", (==dbg_info.snd.ad_en)?"yes":"no");
- printk( "deca state : %s(%d)\n", audio_state(dbg_info.deca.state), (int)dbg_info.deca.state);
- printk( "deca sub state : %s(%d)\n", audio_sub_state(dbg_info.deca.sub_state), (int)dbg_info.deca.sub_state);
- printk( "snd state : %s(%d)\n", audio_state(dbg_info.snd.state), (int)dbg_info.snd.state);
- printk( "snd sub state : %s(%d)\n", audio_sub_state(dbg_info.snd.sub_state), (int)dbg_info.snd.sub_state);
- printk( "+-----+------------------+------------------+------------------+------------------+\n");
- printk( "|BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) |\n");
- /* deca buff info */
- printk( "+-----+------------------+------------------+------------------+------------------+\n");
- printk( "|BS |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",
- (int)((dbg_info.deca.prog_bs_buff_rm*)/(dbg_info.deca.prog_bs_buff_len)),
- (unsigned int)dbg_info.deca.prog_bs_buff_rm, (unsigned int)dbg_info.deca.prog_bs_buff_len,
- (int)((dbg_info.deca.desc_bs_buff_rm*)/(dbg_info.deca.desc_bs_buff_len)),
- (unsigned int)dbg_info.deca.desc_bs_buff_rm, (unsigned int)dbg_info.deca.desc_bs_buff_len);
- printk( "+-----+------------------+------------------+------------------+------------------+\n");
- printk( "|CB |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | |\n",
- (int)((dbg_info.deca.prog_cb_buff_rm*)/(dbg_info.deca.prog_cb_buff_len)),
- (unsigned int)dbg_info.deca.prog_cb_buff_rm, (unsigned int)dbg_info.deca.prog_cb_buff_len,
- (int)((dbg_info.deca.desc_cb_buff_rm*)/(dbg_info.deca.desc_cb_buff_len)),
- (unsigned int)dbg_info.deca.desc_cb_buff_rm, (unsigned int)dbg_info.deca.desc_cb_buff_len);
- /* snd buff info */
- printk( "+-----+------------------+------------------+------------------+------------------+\n");
- printk( "|SYNC |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
- (int)((dbg_info.snd.sync_buff_pcm_rm*)/(dbg_info.snd.sync_buff_pcm_len)),
- (unsigned int)dbg_info.snd.sync_buff_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_pcm_len,
- (int)((dbg_info.snd.sync_buff_desc_pcm_rm*)/(dbg_info.snd.sync_buff_desc_pcm_len)),
- (unsigned int)dbg_info.snd.sync_buff_desc_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_desc_pcm_len,
- (int)((dbg_info.snd.sync_buff_dd_rm*)/(dbg_info.snd.sync_buff_dd_len)),
- (unsigned int)dbg_info.snd.sync_buff_dd_rm, (unsigned int)dbg_info.snd.sync_buff_dd_len,
- (int)((dbg_info.snd.sync_buff_ddp_rm*)/(dbg_info.snd.sync_buff_ddp_len)),
- (unsigned int)dbg_info.snd.sync_buff_ddp_rm, (unsigned int)dbg_info.snd.sync_buff_ddp_len );
- printk( "+-----+------------------+------------------+------------------+------------------+\n");
- printk( "|DMA |%03d%%(%05x/%05x) | |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |\n",
- (int)((dbg_info.snd.dma_buff_pcm_rm*)/(dbg_info.snd.dma_buff_pcm_len)),
- (unsigned int)dbg_info.snd.dma_buff_pcm_rm, (unsigned int)dbg_info.snd.dma_buff_pcm_len,
- (int)((dbg_info.snd.dma_buff_dd_rm*)/(dbg_info.snd.dma_buff_dd_len)),
- (unsigned int)dbg_info.snd.dma_buff_dd_rm, (unsigned int)dbg_info.snd.dma_buff_dd_len,
- (int)((dbg_info.snd.dma_buff_ddp_rm*)/(dbg_info.snd.dma_buff_ddp_len)),
- (unsigned int)dbg_info.snd.dma_buff_ddp_rm, (unsigned int)dbg_info.snd.dma_buff_ddp_len );
- printk( "+-----+------------------+------------------+------------------+------------------+\n\n");
- }
- return ;
- }
- /*Process debug info*/
- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- static ssize_t audio_dbginfo_procfile_read(struct file *file, char __user *ubuf, size_t size, loff_t *ppos)
- {
- int len = ;
- ssize_t ret_len = ;
- if(audio_info_buffer)
- {
- memset(audio_info_buffer, , MAX_BUF_RD_LEN);
- len = audio_read_debug_info(audio_info_buffer);
- ret_len = simple_read_from_buffer(ubuf, size, ppos, audio_info_buffer, len);
- }
- return ret_len;
- }
- static ssize_t audio_dbginfo_procfile_write(struct file *file, const char __user * buffer, size_t count, loff_t *ppos)
- {
- char buf[MAX_BUF_WT_LEN] = {};
- char *eq_ch = NULL;
- char *endp = NULL;
- unsigned long value = ;
- if ((>=count) || (MAX_BUF_WT_LEN<count))
- return ;
- if (copy_from_user(buf, buffer, count))
- return -EFAULT;
- eq_ch = strstr(buf, "=");
- if (NULL == eq_ch)
- {
- printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
- return -EINVAL;
- }
- value = simple_strtoul((char *)(eq_ch+), &endp, );
- if ((eq_ch+) == endp || value >= INT_MAX)
- {
- printk(KERN_ERR "param error: incorrect value: \"%s\"\n", (eq_ch+));
- return -EINVAL;
- }
- switch(*buf)
- {
- case 'a':
- {
- if (strstr(buf, "ad_en"))
- {
- if (==value || ==value)
- {
- if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (UINT32)value))
- {
- printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, (int)value);
- return -EFAULT;
- }
- }
- else
- {
- printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
- return -EINVAL;
- }
- }
- else
- {
- printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
- return -EINVAL;
- }
- break;
- }
- case 'm':
- {
- if (strstr(buf, "monitor"))
- {
- if (==value || ==value)
- {
- g_dbg_show_en = value;
- if (g_dbg_show_en)
- {
- if (mutex_lock_interruptible(&audio_dbg_mutex))
- {
- return(-ERESTARTSYS);
- }
- wake_up_interruptible(&audio_dbg_wq);
- mutex_unlock(&audio_dbg_mutex);
- }
- }
- else
- {
- printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
- return -EINVAL;
- }
- }
- else
- {
- printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
- return -EINVAL;
- }
- break;
- }
- case 'i':
- {
- if (strstr(buf, "interval"))
- {
- if (<value && >value)
- {
- g_dbg_show_interval = value;
- }
- else
- {
- printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
- return -EINVAL;
- }
- }
- else
- {
- printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
- return -EINVAL;
- }
- break;
- }
- default:
- printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
- return -EINVAL;
- }
- #if 0 /* Modified by William.Zeng on 2016-10-14 18:57 */
- if (( != sscanf(buf, "ad_en=%d", &ad_en)) && (==ad_en || ==ad_en))
- {
- return ;
- }
- if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (enum adec_desc_channel_enable)ad_en))
- {
- printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
- return ;
- }
- printk("\033[40;31m%s->%s.%u, set ad_en(%d) success!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
- #endif /* #if 0, End of Modified by William.Zeng on 2016-10-14 18:57 */
- return count;
- }
- #else
- static int audio_dbginfo_procfile_read(char*buffer, char**buffer_localation, off_t offset,int buffer_length,int* eof, void *data )
- {
- int len = ;
- len = audio_read_debug_info(buffer);
- *eof = ;
- return len;
- }
- static int audio_dbginfo_procfile_write(struct file *filp, const char *buffer,unsigned long count,void *data)
- {
- char buf[MAX_BUF_WT_LEN] = {};
- char *eq_ch = NULL;
- char *endp = NULL;
- unsigned long value = ;
- if ((>=count) || (MAX_BUF_WT_LEN<count))
- return ;
- if (copy_from_user(buf, buffer, count))
- return -EFAULT;
- eq_ch = strstr(buf, "=");
- if (NULL == eq_ch)
- {
- printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
- return -EINVAL;
- }
- value = simple_strtoul((char *)(eq_ch+), &endp, );
- if ((eq_ch+) == endp || value >= INT_MAX)
- {
- printk(KERN_ERR "param error: incorrect value: \"%s\"\n", (eq_ch+));
- return -EINVAL;
- }
- switch(*buf)
- {
- case 'a':
- if (strstr(buf, "ad_en"))
- {
- if (==value || ==value)
- {
- if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (UINT32)value))
- {
- printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, (int)value);
- return -EFAULT;
- }
- }
- else
- {
- printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
- return -EINVAL;
- }
- }
- else
- {
- printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
- return -EINVAL;
- }
- break;
- case 'm':
- if (strstr(buf, "monitor"))
- {
- if (==value || ==value)
- {
- g_dbg_show_en = value;
- if (g_dbg_show_en)
- {
- if (mutex_lock_interruptible(&audio_dbg_mutex))
- {
- return(-ERESTARTSYS);
- }
- wake_up_interruptible(&audio_dbg_wq);
- mutex_unlock(&audio_dbg_mutex);
- }
- }
- else
- {
- printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
- return -EINVAL;
- }
- }
- else
- {
- printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
- return -EINVAL;
- }
- break;
- default:
- printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
- return -EINVAL;
- }
- #if 0 /* Modified by William.Zeng on 2016-10-14 18:57 */
- if (( != sscanf(buf, "ad_en=%d", &ad_en)) && (==ad_en || ==ad_en))
- {
- return ;
- }
- if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (enum adec_desc_channel_enable)ad_en))
- {
- printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
- return ;
- }
- printk("\033[40;31m%s->%s.%u, set ad_en(%d) success!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
- #endif /* #if 0, End of Modified by William.Zeng on 2016-10-14 18:57 */
- return count;
- }
- #endif
- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- static const struct file_operations audio_debuginfo_fops = {
- .read = audio_dbginfo_procfile_read,
- .write = audio_dbginfo_procfile_write,
- .llseek = default_llseek,
- };
- #endif
- static int audio_dbg_show_thread(void *param)
- {
- __s32 ret;
- for(;;)
- {
- if (mutex_lock_interruptible(&audio_dbg_mutex))
- {
- return(-ERESTARTSYS);
- }
- /* Wait until we are allowed to show debug info.
- */
- while (g_dbg_show_en == )
- {
- mutex_unlock(&audio_dbg_mutex);
- if (wait_event_interruptible(audio_dbg_wq, (==g_dbg_show_en)))
- {
- return(-ERESTARTSYS);
- }
- if (mutex_lock_interruptible(&audio_dbg_mutex))
- {
- return(-ERESTARTSYS);
- }
- }
- ret = audio_show_debug_info();
- if (ret < )
- {
- g_dbg_show_en = ;
- printk("\033[40;31m%s->%s.%u, audio_show_debug_info failed!.\033[0m\n", __FILE__, __FUNCTION__, __LINE__);
- }
- mutex_unlock(&audio_dbg_mutex);
- msleep(g_dbg_show_interval*);
- }
- return();
- }
- int audio_debug_procfs_init(void)
- {
- audio_info_buffer = kmalloc(MAX_BUF_RD_LEN, GFP_KERNEL);
- if (NULL == audio_info_buffer)
- {
- printk("kmall audio_info_buffer %d failed!!\n", MAX_BUF_RD_LEN);
- return -;
- }
- mutex_init(&audio_dbg_mutex);
- init_waitqueue_head(&audio_dbg_wq);
- audio_proc_dir = proc_mkdir(AUDIO_DEBUG_PROC_DIR, NULL);
- if (audio_proc_dir == NULL) {
- printk("audio_debug_procfs_init create dir audio failed!!\n");
- kfree(audio_info_buffer);
- return -;
- }
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 10, 0))
- /*For Debug info*/
- audio_proc_dbginfo_file = proc_create(AUDIO_DEBUG_PROC_INFO,,audio_proc_dir, &audio_debuginfo_fops);
- #else
- /*For Debug info*/
- audio_proc_dbginfo_file = create_proc_entry(AUDIO_DEBUG_PROC_INFO,,audio_proc_dir);
- #endif
- if(audio_proc_dbginfo_file == NULL)
- {
- remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);
- kfree(audio_info_buffer);
- printk("Error:could not initialize /proc/%s/%s\n", AUDIO_DEBUG_PROC_DIR, AUDIO_DEBUG_PROC_INFO);
- return -;
- }
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
- audio_proc_dbginfo_file->read_proc = audio_dbginfo_procfile_read;
- audio_proc_dbginfo_file->write_proc = audio_dbginfo_procfile_write;
- #endif
- audio_deca_dev=(struct deca_device*)hld_dev_get_by_type(NULL, HLD_DEV_TYPE_DECA);
- audio_snd_dev=(struct snd_device*)hld_dev_get_by_type(NULL, HLD_DEV_TYPE_SND);
- audio_dbg_show_thread_ptr = kthread_create(audio_dbg_show_thread, NULL, "audio_dbg");
- if (IS_ERR(audio_dbg_show_thread_ptr))
- {
- printk("%s,%d\n", __FUNCTION__, __LINE__);
- remove_proc_entry(AUDIO_DEBUG_PROC_INFO, audio_proc_dir);
- remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);
- kfree(audio_info_buffer);
- return(PTR_ERR(audio_dbg_show_thread_ptr));
- }
- wake_up_process(audio_dbg_show_thread_ptr);
- return ;
- }
- void audio_debug_procfs_exit(void)
- {
- remove_proc_entry(AUDIO_DEBUG_PROC_INFO, audio_proc_dir);
- remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);
- if (audio_info_buffer)
- kfree(audio_info_buffer);
- return ;
- }
今天刚好加了一个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/debuginfo
- desc enable : no
- deca state : IDLE()
- deca sub state : IDLE()
- snd state : IDLE()
- snd sub state : IDLE()
- +-----+------------------+------------------+------------------+------------------+
- |BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) |
- +-----+------------------+------------------+------------------+------------------+
- |BS |%(/0c800) |%(/0c800) | | |
- +-----+------------------+------------------+------------------+------------------+
- |CB |%(/000c8) |%(/000c8) | | |
- +-----+------------------+------------------+------------------+------------------+
- |SYNC |%(/) |%(/) |%(/) |%(/) |
- +-----+------------------+------------------+------------------+------------------+
- |DMA |%(/) | |%(/) |%(/) |
- +-----+------------------+------------------+------------------+------------------+
linux内核debug的一种方式:procfs的更多相关文章
- Linux 内核睡眠的几种方式
译至:http://geeki.wordpress.com/2010/10/30/ways-of-sleeping-in-linux-kernel/ 在Linux中睡眠有2-3种不同的方法. 睡眠的第 ...
- 设置 Linux 下打印机的几种方式
设置 Linux 下打印机的几种方式 一.使用 cups 进行设置 如若遇到 cups 也没有驱动的话可以前往 openprinting.org 找寻对应驱动. 二.前往 official 下载驱动 ...
- linux创建文件的四种方式(其实是两种,强行4种)
linux创建文件的四种方式: 1.vi newfilename->i->编辑文件->ESC->:wq! 2.touch newfilename 3.cp sourcePath ...
- Linux 软件安装的三种方式
Linux 软件安装的三种方式 1.yum 语法格式: yum -y install package.name -y yes # 遇到提示自动输入yes 案例: 安装ifconfig命 ...
- Linux 安装 Nodejs 的两种方式
Linux 安装 Nodejs 的两种方式 目录 Linux 安装 Nodejs 的两种方式 一.压缩包安装 Nodejs 二.源码编译安装 Nodejs 一.压缩包安装 Nodejs 下载 Node ...
- Linux下定时执行任务的几种方式
如果说我说如果,你的某一个目录下会经常的生成一些垃圾文件,比如访问日志.错误日志.core文件,而你又不想过几分钟就去手动检查一下,那么可以使用定时执行任务的方式来解决.目前我所知道的可以执行定时任务 ...
- linux异步IO的两种方式【转】
转自:https://blog.csdn.net/shixin_0125/article/details/78898146 知道异步IO已经很久了,但是直到最近,才真正用它来解决一下实际问题(在一个C ...
- Linux内核替换的一种简单方法
前言 使用现有centos的镜像,在海光机器上出现了无法运行的情况,grub引导后就只剩下光标一直在闪,无任何字符输出.这种情况大概率是因为Linux的内核无法运行在海光的CPU上所导致的. 已得知L ...
- Linux进程通信的几种方式总结
进程通信的目的 数据传输 一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间 共享数据 多个进程想要操作共享数据,一个进程对共享数据 通知事 一个进程需要向另一个或一组进程发 ...
随机推荐
- Git以及GitHub的一些基本使用
1:注册GitHub账号: https://github.com/ 2:Git bash工具下载地址 https://gitforwindows.org/ 3:怎么在GitHub 新增 SSH Key ...
- Java面向对象——类的成员
Java面向对象——类的成员 摘要:本文主要介绍了类的常见成员. 属性 属性称为成员变量,一般来讲不用赋值,因为有默认值,另外显式赋值没有意义会导致所有由此类创建对象都是此值. 默认值 Boolean ...
- Mysql、Oracle、SQLServer等数据库参考文档免费分享下载
场景 MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统 ...
- Ribbon架构剖析
在学习Ribbon之前,先看一下这张图,这张图完美的把Ribbon的基础架构给描述出来了 这张图的核心是负载均衡管理器,围绕着它的是外面的这5大功能点,咱们就从核心开始看然后再带出来其他的功能 首先看 ...
- 使用jq操作脚本生成元素的事件
其实这个很简单,是jq里面的一个delegate操作,具体如下: $("div").delegate("button","click",fu ...
- 【Web安全入门】三个技巧教你玩转XSS漏洞
XSS漏洞是Web应用程序中最常见的漏洞之一,想要入门Web安全的小伙伴,这个知识点是必学的. i春秋官网中有很多关于XSS漏洞的课程,新手小白可以去官网看课学习. 学习地址:https://www. ...
- SPC软控件提供商NWA的产品在各行业的应用(生命科学行业)
在上一篇文章中,我们提到了NWA软件产品在各行业都有广泛的应用,并且就化工行业的应用展开了详细介绍.而在本文中,您将看到NWA产品在生命科学行业也扮演着不可替代的角色. Northwest Analy ...
- Win2003下配置iis+php+mysql+zend
所需软件: ActivePerl.PHP.MYSQL.Zend (一.安装IIS6.0;二.配置PHP环境;三.安装mysql;四.安装 Zend Optimizer;五.配置PHPMYADMIN) ...
- 关于使用repo时repo init和repo sync失败的一个解决方案
由于我国的网络的原因,在访问谷歌等一些国外网络资源时经常会遇到被拦截的情况,导致repo等一些代码管理工具拉取代码网络受限受阻,下面提供一个可以参考的简单解决方案. 1.repo init时的遇到fa ...
- c# 第15节 StringBuilder
本节内容: 1:StringBuilder 2:内容总结 1:StringBuilder 实例: 2:内容总结 项目: