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 = ;
  41. static __u32 g_dbg_show_interval = ;
  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 :
  52. ret="DETACH";
  53. break;
  54. case :
  55. ret="ATTACH";
  56. break;
  57. case :
  58. ret="IDLE";
  59. break;
  60. case :
  61. ret="PLAY";
  62. break;
  63. case :
  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 :
  78. ret="IDLE";
  79. break;
  80. case :
  81. ret="NORMAL";
  82. break;
  83. case :
  84. ret="NO DATA";
  85. break;
  86. case :
  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 = ;
  98. unsigned long len_max = MAX_BUF_RD_LEN - ;
  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", (==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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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", (==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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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*)/(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 ;
  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 = ;
  259. ssize_t ret_len = ;
  260.  
  261. if(audio_info_buffer)
  262. {
  263. memset(audio_info_buffer, , 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. static ssize_t audio_dbginfo_procfile_write(struct file *file, const char __user * buffer, size_t count, loff_t *ppos)
  272. {
  273. char buf[MAX_BUF_WT_LEN] = {};
  274. char *eq_ch = NULL;
  275. char *endp = NULL;
  276. unsigned long value = ;
  277.  
  278. if ((>=count) || (MAX_BUF_WT_LEN<count))
  279. return ;
  280.  
  281. if (copy_from_user(buf, buffer, count))
  282. return -EFAULT;
  283.  
  284. eq_ch = strstr(buf, "=");
  285. if (NULL == eq_ch)
  286. {
  287. printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
  288. return -EINVAL;
  289. }
  290.  
  291. value = simple_strtoul((char *)(eq_ch+), &endp, );
  292. if ((eq_ch+) == endp || value >= INT_MAX)
  293. {
  294. printk(KERN_ERR "param error: incorrect value: \"%s\"\n", (eq_ch+));
  295. return -EINVAL;
  296. }
  297.  
  298. switch(*buf)
  299. {
  300. case 'a':
  301. {
  302. if (strstr(buf, "ad_en"))
  303. {
  304. if (==value || ==value)
  305. {
  306. if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (UINT32)value))
  307. {
  308. printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, (int)value);
  309. return -EFAULT;
  310. }
  311. }
  312. else
  313. {
  314. printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
  315. return -EINVAL;
  316. }
  317. }
  318. else
  319. {
  320. printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
  321. return -EINVAL;
  322. }
  323. break;
  324. }
  325. case 'm':
  326. {
  327. if (strstr(buf, "monitor"))
  328. {
  329. if (==value || ==value)
  330. {
  331. g_dbg_show_en = value;
  332. if (g_dbg_show_en)
  333. {
  334. if (mutex_lock_interruptible(&audio_dbg_mutex))
  335. {
  336. return(-ERESTARTSYS);
  337. }
  338. wake_up_interruptible(&audio_dbg_wq);
  339. mutex_unlock(&audio_dbg_mutex);
  340. }
  341. }
  342. else
  343. {
  344. printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
  345. return -EINVAL;
  346. }
  347. }
  348. else
  349. {
  350. printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
  351. return -EINVAL;
  352. }
  353. break;
  354. }
  355. case 'i':
  356. {
  357. if (strstr(buf, "interval"))
  358. {
  359. if (<value && >value)
  360. {
  361. g_dbg_show_interval = value;
  362. }
  363. else
  364. {
  365. printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
  366. return -EINVAL;
  367. }
  368. }
  369. else
  370. {
  371. printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
  372. return -EINVAL;
  373. }
  374. break;
  375. }
  376. default:
  377. printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
  378. return -EINVAL;
  379. }
  380.  
  381. #if 0 /* Modified by William.Zeng on 2016-10-14 18:57 */
  382. if (( != sscanf(buf, "ad_en=%d", &ad_en)) && (==ad_en || ==ad_en))
  383. {
  384. return ;
  385. }
  386. if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (enum adec_desc_channel_enable)ad_en))
  387. {
  388. printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
  389. return ;
  390. }
  391. printk("\033[40;31m%s->%s.%u, set ad_en(%d) success!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
  392. #endif /* #if 0, End of Modified by William.Zeng on 2016-10-14 18:57 */
  393.  
  394. return count;
  395. }
  396. #else
  397. static int audio_dbginfo_procfile_read(char*buffer, char**buffer_localation, off_t offset,int buffer_length,int* eof, void *data )
  398. {
  399. int len = ;
  400. len = audio_read_debug_info(buffer);
  401. *eof = ;
  402. return len;
  403. }
  404.  
  405. static int audio_dbginfo_procfile_write(struct file *filp, const char *buffer,unsigned long count,void *data)
  406. {
  407. char buf[MAX_BUF_WT_LEN] = {};
  408. char *eq_ch = NULL;
  409. char *endp = NULL;
  410. unsigned long value = ;
  411.  
  412. if ((>=count) || (MAX_BUF_WT_LEN<count))
  413. return ;
  414.  
  415. if (copy_from_user(buf, buffer, count))
  416. return -EFAULT;
  417.  
  418. eq_ch = strstr(buf, "=");
  419. if (NULL == eq_ch)
  420. {
  421. printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
  422. return -EINVAL;
  423. }
  424.  
  425. value = simple_strtoul((char *)(eq_ch+), &endp, );
  426. if ((eq_ch+) == endp || value >= INT_MAX)
  427. {
  428. printk(KERN_ERR "param error: incorrect value: \"%s\"\n", (eq_ch+));
  429. return -EINVAL;
  430. }
  431.  
  432. switch(*buf)
  433. {
  434. case 'a':
  435. if (strstr(buf, "ad_en"))
  436. {
  437. if (==value || ==value)
  438. {
  439. if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (UINT32)value))
  440. {
  441. printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, (int)value);
  442. return -EFAULT;
  443. }
  444. }
  445. else
  446. {
  447. printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
  448. return -EINVAL;
  449. }
  450. }
  451. else
  452. {
  453. printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
  454. return -EINVAL;
  455. }
  456. break;
  457. case 'm':
  458. if (strstr(buf, "monitor"))
  459. {
  460. if (==value || ==value)
  461. {
  462. g_dbg_show_en = value;
  463. if (g_dbg_show_en)
  464. {
  465. if (mutex_lock_interruptible(&audio_dbg_mutex))
  466. {
  467. return(-ERESTARTSYS);
  468. }
  469. wake_up_interruptible(&audio_dbg_wq);
  470. mutex_unlock(&audio_dbg_mutex);
  471. }
  472. }
  473. else
  474. {
  475. printk(KERN_ERR "param error: incorrect value: \"%d\"\n", (int)value);
  476. return -EINVAL;
  477. }
  478. }
  479. else
  480. {
  481. printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
  482. return -EINVAL;
  483. }
  484. break;
  485. default:
  486. printk(KERN_ERR "param error: incorrect value: \"%s\"\n", buf);
  487. return -EINVAL;
  488. }
  489.  
  490. #if 0 /* Modified by William.Zeng on 2016-10-14 18:57 */
  491. if (( != sscanf(buf, "ad_en=%d", &ad_en)) && (==ad_en || ==ad_en))
  492. {
  493. return ;
  494. }
  495. if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (enum adec_desc_channel_enable)ad_en))
  496. {
  497. printk("\033[40;31m%s->%s.%u, set ad_en(%d) fail!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
  498. return ;
  499. }
  500. printk("\033[40;31m%s->%s.%u, set ad_en(%d) success!\033[0m\n", __FILE__, __FUNCTION__, __LINE__, ad_en);
  501. #endif /* #if 0, End of Modified by William.Zeng on 2016-10-14 18:57 */
  502.  
  503. return count;
  504. }
  505.  
  506. #endif
  507.  
  508. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
  509. static const struct file_operations audio_debuginfo_fops = {
  510. .read = audio_dbginfo_procfile_read,
  511. .write = audio_dbginfo_procfile_write,
  512. .llseek = default_llseek,
  513. };
  514. #endif
  515.  
  516. static int audio_dbg_show_thread(void *param)
  517. {
  518. __s32 ret;
  519.  
  520. for(;;)
  521. {
  522. if (mutex_lock_interruptible(&audio_dbg_mutex))
  523. {
  524. return(-ERESTARTSYS);
  525. }
  526.  
  527. /* Wait until we are allowed to show debug info.
  528. */
  529. while (g_dbg_show_en == )
  530. {
  531. mutex_unlock(&audio_dbg_mutex);
  532. if (wait_event_interruptible(audio_dbg_wq, (==g_dbg_show_en)))
  533. {
  534. return(-ERESTARTSYS);
  535. }
  536. if (mutex_lock_interruptible(&audio_dbg_mutex))
  537. {
  538. return(-ERESTARTSYS);
  539. }
  540. }
  541.  
  542. ret = audio_show_debug_info();
  543.  
  544. if (ret < )
  545. {
  546. g_dbg_show_en = ;
  547. printk("\033[40;31m%s->%s.%u, audio_show_debug_info failed!.\033[0m\n", __FILE__, __FUNCTION__, __LINE__);
  548. }
  549. mutex_unlock(&audio_dbg_mutex);
  550.  
  551. msleep(g_dbg_show_interval*);
  552. }
  553.  
  554. return();
  555. }
  556.  
  557. int audio_debug_procfs_init(void)
  558. {
  559. audio_info_buffer = kmalloc(MAX_BUF_RD_LEN, GFP_KERNEL);
  560. if (NULL == audio_info_buffer)
  561. {
  562. printk("kmall audio_info_buffer %d failed!!\n", MAX_BUF_RD_LEN);
  563. return -;
  564. }
  565. mutex_init(&audio_dbg_mutex);
  566. init_waitqueue_head(&audio_dbg_wq);
  567.  
  568. audio_proc_dir = proc_mkdir(AUDIO_DEBUG_PROC_DIR, NULL);
  569. if (audio_proc_dir == NULL) {
  570. printk("audio_debug_procfs_init create dir audio failed!!\n");
  571. kfree(audio_info_buffer);
  572. return -;
  573. }
  574.  
  575. #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 10, 0))
  576. /*For Debug info*/
  577. audio_proc_dbginfo_file = proc_create(AUDIO_DEBUG_PROC_INFO,,audio_proc_dir, &audio_debuginfo_fops);
  578. #else
  579. /*For Debug info*/
  580. audio_proc_dbginfo_file = create_proc_entry(AUDIO_DEBUG_PROC_INFO,,audio_proc_dir);
  581. #endif
  582. if(audio_proc_dbginfo_file == NULL)
  583. {
  584. remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);
  585. kfree(audio_info_buffer);
  586. printk("Error:could not initialize /proc/%s/%s\n", AUDIO_DEBUG_PROC_DIR, AUDIO_DEBUG_PROC_INFO);
  587. return -;
  588. }
  589. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
  590. audio_proc_dbginfo_file->read_proc = audio_dbginfo_procfile_read;
  591. audio_proc_dbginfo_file->write_proc = audio_dbginfo_procfile_write;
  592. #endif
  593.  
  594. audio_deca_dev=(struct deca_device*)hld_dev_get_by_type(NULL, HLD_DEV_TYPE_DECA);
  595. audio_snd_dev=(struct snd_device*)hld_dev_get_by_type(NULL, HLD_DEV_TYPE_SND);
  596.  
  597. audio_dbg_show_thread_ptr = kthread_create(audio_dbg_show_thread, NULL, "audio_dbg");
  598.  
  599. if (IS_ERR(audio_dbg_show_thread_ptr))
  600. {
  601. printk("%s,%d\n", __FUNCTION__, __LINE__);
  602. remove_proc_entry(AUDIO_DEBUG_PROC_INFO, audio_proc_dir);
  603. remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);
  604. kfree(audio_info_buffer);
  605. return(PTR_ERR(audio_dbg_show_thread_ptr));
  606. }
  607.  
  608. wake_up_process(audio_dbg_show_thread_ptr);
  609.  
  610. return ;
  611. }
  612.  
  613. void audio_debug_procfs_exit(void)
  614. {
  615. remove_proc_entry(AUDIO_DEBUG_PROC_INFO, audio_proc_dir);
  616. remove_proc_entry(AUDIO_DEBUG_PROC_DIR, NULL);
  617.  
  618. if (audio_info_buffer)
  619. kfree(audio_info_buffer);
  620.  
  621. return ;
  622. }

今天刚好加了一个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堵住的情况)

  1. # cat /proc/audio/debuginfo
  2.  
  3. desc enable : no
  4. deca state : IDLE()
  5. deca sub state : IDLE()
  6. snd state : IDLE()
  7. snd sub state : IDLE()
  8. +-----+------------------+------------------+------------------+------------------+
  9. |BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) |
  10. +-----+------------------+------------------+------------------+------------------+
  11. |BS |%(/0c800) |%(/0c800) | | |
  12. +-----+------------------+------------------+------------------+------------------+
  13. |CB |%(/000c8) |%(/000c8) | | |
  14. +-----+------------------+------------------+------------------+------------------+
  15. |SYNC |%(/) |%(/) |%(/) |%(/) |
  16. +-----+------------------+------------------+------------------+------------------+
  17. |DMA |%(/) | |%(/) |%(/) |
  18. +-----+------------------+------------------+------------------+------------------+

linux内核debug的一种方式:procfs的更多相关文章

  1. Linux 内核睡眠的几种方式

    译至:http://geeki.wordpress.com/2010/10/30/ways-of-sleeping-in-linux-kernel/ 在Linux中睡眠有2-3种不同的方法. 睡眠的第 ...

  2. 设置 Linux 下打印机的几种方式

    设置 Linux 下打印机的几种方式 一.使用 cups 进行设置 如若遇到 cups 也没有驱动的话可以前往 openprinting.org 找寻对应驱动. 二.前往 official 下载驱动 ...

  3. linux创建文件的四种方式(其实是两种,强行4种)

    linux创建文件的四种方式: 1.vi newfilename->i->编辑文件->ESC->:wq! 2.touch newfilename 3.cp sourcePath ...

  4. Linux 软件安装的三种方式

    Linux 软件安装的三种方式 1.yum ​ 语法格式: ​ yum -y install package.name ​ -y yes # 遇到提示自动输入yes ​ 案例: 安装ifconfig命 ...

  5. Linux 安装 Nodejs 的两种方式

    Linux 安装 Nodejs 的两种方式 目录 Linux 安装 Nodejs 的两种方式 一.压缩包安装 Nodejs 二.源码编译安装 Nodejs 一.压缩包安装 Nodejs 下载 Node ...

  6. Linux下定时执行任务的几种方式

    如果说我说如果,你的某一个目录下会经常的生成一些垃圾文件,比如访问日志.错误日志.core文件,而你又不想过几分钟就去手动检查一下,那么可以使用定时执行任务的方式来解决.目前我所知道的可以执行定时任务 ...

  7. linux异步IO的两种方式【转】

    转自:https://blog.csdn.net/shixin_0125/article/details/78898146 知道异步IO已经很久了,但是直到最近,才真正用它来解决一下实际问题(在一个C ...

  8. Linux内核替换的一种简单方法

    前言 使用现有centos的镜像,在海光机器上出现了无法运行的情况,grub引导后就只剩下光标一直在闪,无任何字符输出.这种情况大概率是因为Linux的内核无法运行在海光的CPU上所导致的. 已得知L ...

  9. Linux进程通信的几种方式总结

    进程通信的目的 数据传输 一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间 共享数据 多个进程想要操作共享数据,一个进程对共享数据 通知事 一个进程需要向另一个或一组进程发 ...

随机推荐

  1. Git以及GitHub的一些基本使用

    1:注册GitHub账号: https://github.com/ 2:Git bash工具下载地址 https://gitforwindows.org/ 3:怎么在GitHub 新增 SSH Key ...

  2. Java面向对象——类的成员

    Java面向对象——类的成员 摘要:本文主要介绍了类的常见成员. 属性 属性称为成员变量,一般来讲不用赋值,因为有默认值,另外显式赋值没有意义会导致所有由此类创建对象都是此值. 默认值 Boolean ...

  3. Mysql、Oracle、SQLServer等数据库参考文档免费分享下载

    场景 MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统 ...

  4. Ribbon架构剖析

    在学习Ribbon之前,先看一下这张图,这张图完美的把Ribbon的基础架构给描述出来了 这张图的核心是负载均衡管理器,围绕着它的是外面的这5大功能点,咱们就从核心开始看然后再带出来其他的功能 首先看 ...

  5. 使用jq操作脚本生成元素的事件

    其实这个很简单,是jq里面的一个delegate操作,具体如下: $("div").delegate("button","click",fu ...

  6. 【Web安全入门】三个技巧教你玩转XSS漏洞

    XSS漏洞是Web应用程序中最常见的漏洞之一,想要入门Web安全的小伙伴,这个知识点是必学的. i春秋官网中有很多关于XSS漏洞的课程,新手小白可以去官网看课学习. 学习地址:https://www. ...

  7. SPC软控件提供商NWA的产品在各行业的应用(生命科学行业)

    在上一篇文章中,我们提到了NWA软件产品在各行业都有广泛的应用,并且就化工行业的应用展开了详细介绍.而在本文中,您将看到NWA产品在生命科学行业也扮演着不可替代的角色. Northwest Analy ...

  8. Win2003下配置iis+php+mysql+zend

    所需软件: ActivePerl.PHP.MYSQL.Zend (一.安装IIS6.0;二.配置PHP环境;三.安装mysql;四.安装 Zend Optimizer;五.配置PHPMYADMIN) ...

  9. 关于使用repo时repo init和repo sync失败的一个解决方案

    由于我国的网络的原因,在访问谷歌等一些国外网络资源时经常会遇到被拦截的情况,导致repo等一些代码管理工具拉取代码网络受限受阻,下面提供一个可以参考的简单解决方案. 1.repo init时的遇到fa ...

  10. c# 第15节 StringBuilder

    本节内容: 1:StringBuilder 2:内容总结 1:StringBuilder 实例: 2:内容总结 项目: