基於mini2440的MP3

button_device.c
#include <linux/device.h>
#include <linux/string.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/gpio.h>

static struct resource key_resource[]=
{
    [0] = {
        .start = IRQ_EINT8,
        .end = IRQ_EINT8,
        .flags = IORESOURCE_IRQ,
    },
    [1] = {
        .start = IRQ_EINT11,
        .end = IRQ_EINT11,
        .flags = IORESOURCE_IRQ,
    },
    [2]= {
        .start = IRQ_EINT13,
        .end = IRQ_EINT13,
        .flags = IORESOURCE_IRQ,
    },
    [3] = {
        .start = IRQ_EINT14,
        .end = IRQ_EINT14,
        .flags = IORESOURCE_IRQ,
    },
    [4] = {
        .start = IRQ_EINT15,
        .end = IRQ_EINT15,
        .flags = IORESOURCE_IRQ,
    },
    [5] = {
        .start = IRQ_EINT19,
        .end = IRQ_EINT19,
        .flags = IORESOURCE_IRQ,
    },
};

struct platform_device *my_buttons_dev;

static int __init platform_dev_init(void)
{
    int ret;

    my_buttons_dev = platform_device_alloc("my_buttons", -1);/*分配設備*/

    platform_device_add_resources(my_buttons_dev,key_resource,6);/*添加資源一定要用該函數,不能使用對platform_device->resource賦值
                                                                                             否則會導致platform_device_unregister調用失敗,內核異常。*/

    ret = platform_device_add(my_buttons_dev);/*平臺設備的註冊*/

    if(ret)
        platform_device_put(my_buttons_dev);

    return ret;
}

static void __exit platform_dev_exit(void)
{
    platform_device_unregister(my_buttons_dev);/*平臺設備的卸載*/
}

module_init(platform_dev_init);
module_exit(platform_dev_exit);

MODULE_AUTHOR("Chen chunjian");
MODULE_LICENSE("GPL");



button_driver.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/gpio.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/unistd.h>
#include <linux/device.h>
#include <linux/cdev.h>

#include <linux/fcntl.h>
#include <asm/system.h>		/* cli(), *_flags */
#include <asm/uaccess.h>	/* copy_*_user */
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/timer.h>
#define DEVICE_NAME     "buttons"
#define BUTTON_NUM       6			/* button numbers */
static int buttons_irq[BUTTON_NUM];

struct irq_des
{
    int *buttons_irq;
    char *name[BUTTON_NUM];
};


struct irq_des button_irqs = {
    .buttons_irq = buttons_irq,
    .name = {"KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5"},
};

static volatile int key_values[] = {0,0,0,0,0,0};
struct timer_list button_timers[BUTTON_NUM]; /* buttons delay timer */

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);


static volatile int ev_press = 0;


static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
    int i;
    for(i=0; i<BUTTON_NUM; i++)
	{
        if(irq == buttons_irq[i])
		{
			key_values[i] = !key_values[i];
            ev_press = 1;
            wake_up_interruptible(&button_waitq);
			
			mdelay(100);
        }
    }
    return IRQ_RETVAL(IRQ_HANDLED);
}


static int s3c24xx_buttons_open(struct inode *inode, struct file *file)
{
    int i;
    int err = 0;

    for (i = 0; i < BUTTON_NUM; i++) {
        err = request_irq(button_irqs.buttons_irq[i], buttons_interrupt, IRQ_TYPE_EDGE_BOTH,
                          button_irqs.name[i], (void *)&button_irqs.buttons_irq[i]);
        if (err)
            break;
    }

    if (err) {
        i--;
        for (; i >= 0; i--) {
        if (button_irqs.buttons_irq[i] < 0) {
        continue;
        }
        disable_irq(button_irqs.buttons_irq[i]);
            free_irq(button_irqs.buttons_irq[i], (void *)&button_irqs.buttons_irq[i]);
        }
        return -EBUSY;
    }

    return 0;
}


static int s3c24xx_buttons_close(struct inode *inode, struct file *file)
{
    int i;

    for (i = 0; i < BUTTON_NUM; i++) {
    free_irq(button_irqs.buttons_irq[i], (void *)&button_irqs.buttons_irq[i]);
    }

    return 0;
}


static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
    unsigned long err;

    if (!ev_press) {
    if (filp->f_flags & O_NONBLOCK)
        return -EAGAIN;
    else
        wait_event_interruptible(button_waitq, ev_press);
    }

    ev_press = 0;

    err = copy_to_user(buff, (const void *)&key_values, min(sizeof(key_values), count));

    return err ? -EFAULT : min(sizeof(key_values), count);
}

static unsigned int s3c24xx_buttons_poll( struct file *file, struct poll_table_struct *wait)
{
    unsigned int mask = 0;
    poll_wait(file, &button_waitq, wait);
    if (ev_press)
        mask |= POLLIN | POLLRDNORM;
    return mask;
}


static struct file_operations dev_fops = {
    .owner   =   THIS_MODULE,
    .open    =   s3c24xx_buttons_open,
    .release =   s3c24xx_buttons_close,
    .read    =   s3c24xx_buttons_read,
    .poll    =   s3c24xx_buttons_poll,
};

static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "my_buttons",
    .fops = &dev_fops,
};


static int my_plat_probe(struct platform_device *dev)
{
    int ret,i;
    struct resource *plat_resource;
    struct platform_device *pdev = dev;

    printk("my platform dirver find my platfrom device.\n");

    for(i=0; i<BUTTON_NUM; i++){
        plat_resource = platform_get_resource(pdev,IORESOURCE_IRQ,i);/*獲取資源*/
        if(plat_resource == NULL)
            return -ENOENT;
        buttons_irq[i] = plat_resource->start;
    }

    ret = misc_register(&misc);//娣鋒潅璁懼鍙鋒敞鍐?
    if(ret)
        return ret;


    return 0;
}

static int my_plat_remove(struct platform_device *dev)
{
    printk("my platfrom device has removed.\n");
    misc_deregister(&misc);
    return 0;
}

struct platform_driver my_buttons_drv = {
    .probe = my_plat_probe,
    .remove = my_plat_remove,
    .driver = {
        .owner = THIS_MODULE,
        .name = "my_buttons",
    },
};

static int __init platform_drv_init(void)
{
    int ret;

    ret = platform_driver_register(&my_buttons_drv);/*平臺設備驅動的註冊*/

    return ret;
}

static void __exit platform_drv_exit(void)
{
    platform_driver_unregister(&my_buttons_drv);/*平臺設備驅動卸載*/
}

module_init(platform_drv_init);
module_exit(platform_drv_exit);

MODULE_AUTHOR("Chen chunjian");
MODULE_LICENSE("GPL");


mp3_play.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <signal.h>
#include <linux/soundcard.h>
#include <time.h>

#define SINGLE 1
#define LOOP 2
#define RANDOM 3
#define SCAN 4
#define VOL_INIT 60

struct DuLNode
{
    char num[100];
    struct DuLNode *prior,*next;
};
struct DuLNode *head=NULL;
struct DuLNode *current_head=NULL;
pid_t ppid = 0;
pid_t pid = 0;
int play_mod = 0;

mp3_play.c
#include "../../include/mp3_play.h"

/***************************************************
函數名:handler
功能:信號處理程序
傳入參數:int signo
返回值:void
***************************************************/
void handler(int signo)
{
    if(signo == SIGUSR1)
    {
		current_head = current_head->next;
		printf("signo == SIGUSR1\n");
    }
	return ;
}

/***************************************************
函數名:interface
功能:邋MP3按鍵提示界面
傳入參數: void
返回值:void
***************************************************/
void interface()
{
	printf("=======================MP3======================\n");
	printf("  1.play/stop               2.suspend/continue	\n");
	printf("  3.previous song           4.next song 		\n");
	printf("  5.volume up               6.volume down		\n");
	printf("================================================\n");
}

/***************************************************
函數名:vol_init
功能:音量初始化
傳入參數: void
返回值:void
***************************************************/
void vol_init()
{
	int MIX_FD;
	int iLevel;
	MIX_FD = open("/dev/mixer", O_WRONLY);
	if (MIX_FD == -1) 
	{
		perror("Error:open /dev/mixer error");
		exit(1);
	}
	iLevel = (VOL_INIT << 8) + VOL_INIT;	
	ioctl(MIX_FD, MIXER_WRITE(SOUND_MIXER_VOLUME), &iLevel);  
	close(MIX_FD);
}

/***************************************************
函數名:vol_up
功能:音量增大
傳入參數: void
返回值:void
***************************************************/
void vol_up()
{
	int MIX_FD;
    int iLevel;
	int vol;
    MIX_FD= open("/dev/mixer", O_WRONLY);
    if (MIX_FD == -1) 
	{
        perror("Error:open /dev/mixer error");
        exit(1);
    }
	ioctl(MIX_FD, MIXER_READ(SOUND_MIXER_VOLUME), &iLevel);  
	vol = iLevel & 0xff;  
	vol += 5;
	if(vol > 100)
	{
		vol = 100;
	}
	iLevel = (vol << 8) + vol;	
	printf("vol is at %d %%\n", vol);
	ioctl(MIX_FD, MIXER_WRITE(SOUND_MIXER_VOLUME), &iLevel);  
	close(MIX_FD);
	interface();
}

/***************************************************
函數名:vol_down
功能:音量減小
傳入參數: void
返回值:void
***************************************************/
void vol_down()
{
	int MIX_FD;
    int iLevel;
	int vol;
    MIX_FD= open("/dev/mixer", O_WRONLY);
    if (MIX_FD == -1) 
	{
        perror("Error:open /dev/mixer error");
        exit(1);
    }
	ioctl(MIX_FD, MIXER_READ(SOUND_MIXER_VOLUME), &iLevel);  
	vol = iLevel & 0xff; 
	vol -= 5;
	if(vol < 0)
	{
		vol = 0;
	}
	iLevel = (vol << 8) + vol;	
	printf("vol is at %d %%\n", vol);
	ioctl(MIX_FD, MIXER_WRITE(SOUND_MIXER_VOLUME), &iLevel);  
	close(MIX_FD);
	interface();    
}

/***************************************************
函數名:main
功能:主函數
傳入參數: void
返回值:int
***************************************************/
int main(void)
{
	int buttons_fd;
	int buttons[] = {0,0,0,0,0,0};
	int play_flag = 0;
	int stop_flag = 1;
	time_t time_up,time_dowm;
	
	buttons_fd = open("/dev/my_buttons", 0);
	if (buttons_fd < 0) 
	{
		perror("open device my_buttons");
		exit(1);
	}
	DuLinkList_init();
	vol_init();
	if(signal(SIGUSR1,handler) == SIG_ERR) /*爲信號設置信號處理程序*/
	{
	    perror("can not handler for SIGUSR1");
		exit(1);
	}
	ppid = getpid();/*得到父進程的進程ID號*/
	for (;;) 
	{
		int i;
		int current_buttons[6];
	    if( 0 == play_mod )
		{
			system("clear");
			printf("=============play_mod=============\n");
			printf("  1.single 2.loop 3.random 4.scan\n");
			printf("==================================\n");
		}
		if (read(buttons_fd, ¤t_buttons, sizeof current_buttons ) != sizeof current_buttons ) 
		{
			perror("read my_buttons:");
			exit(1);
		}
        for (i = 0; i < sizeof (buttons) / sizeof (buttons[0]); i++)
		{
		    if (buttons[i] != current_buttons[i])
			{
			    buttons[i] = current_buttons[i];
			    if(buttons[i] == 1)
			    {
			        if((time_dowm = time(NULL)) == -1)
			        {
			            perror("time");
						exit(1);
			        }
					if( 0 == play_mod )/*設置播放模式*/
					{
						switch(i)
						{
						    case 0:
							{
								play_mod = SINGLE;/*單曲循環*/
								break;
							}
						    case 1:
							{
								play_mod = LOOP;/*順序播放*/
								break;
							}
						    case 2:
							{
								play_mod = RANDOM;/*隨機播放*/
								break;
							}
							case 3:
							{
								play_mod = SCAN;/*瀏覽播放*/
								break;
							}
						    default:
							{
								break;
							}
						}
						i = 0;
					}
					play_show();
					switch(i)
					{
					    case 0:/*開始、停止*/
						{
							if((++play_flag)%2 == 0)
							{
							    play_flag = 0;
								if(kill(pid,SIGKILL) == -1)/*殺死子進程*/
								{
									perror("fail to send signal");
									exit(1);
								}
								system("killall -9 madplay");/*停止播放*/
								printf("stop!\n");
								interface();
								break;
							}
							pid = fork();/*創建子進程*/
							if(pid<0)
							{
							   perror("fork error!\n");
							   exit(1);
							}
							if(pid == 0)/*子進程*/
		                    { 
 							    start_play(ppid);
								exit(0);
                            }
							else/*父進程*/
							{
								if(waitpid(pid,NULL,WNOHANG) == -1)
								{
									perror("fail to wait!\n");
									exit(1);
								}		
							}
							break;
						}
					    case 1:/*暫停、繼續*/
						{
							if((++stop_flag)%2 == 0)
							{
							    stop_flag= 0;
								system("killall -STOP madplay");/*暫停播放*/
								printf("suspend...\n");
								interface();
							}
							else
							{
								system("killall -CONT  madplay");/*繼續播放*/
								printf("continue...\n");
								interface();
							}
							break;
						}
					    case 2:/*播放上一首*/
						{
							if(kill(pid,SIGKILL) == -1)/*殺死進程*/
							{
								perror("fail to send signal");
								exit(1);
							}
							system("killall -9 madplay");/*停止播放*/
							current_head = current_head->prior;/*當前指針指向上一首*/
							pid = fork();/*創建子進程*/
							if(pid<0)
							{
							   perror("fork error!\n");
							   exit(1);
							}
							if(pid == 0)/*子進程*/
		                    { 
 							    start_play(ppid);
								stop_flag = 1;
								exit(0);
                            }
							break;
						}
					    case 3:/*播放下一首*/
						{
							if(kill(pid,SIGKILL) == -1)/*殺死進程*/
							{
								perror("fail to send signal");
								exit(1);
							}
							system("killall -9 madplay");/*停止播放*/
							current_head = current_head->next;/*當前指針指向下一首*/
							pid = fork();/*創建子進程*/
							if(pid<0)
							{
							   perror("fork error!\n");
							   exit(1);
							}
							if(pid == 0)/*子進程*/
		                    { 
 							    start_play(ppid);
								stop_flag = 1;
								exit(0);
                            }
							break;
						}
					    case 4:/*音量增大*/
						{
							vol_up();
							break;
						}
						case 5:/*音量減小*/
						{
							vol_down();
							break;
						}
						default:
						{
							break;
						}
					}
			    }
				else
				{
			        if((time_up = time(NULL)) == -1)
			        {
			            perror("time");
						exit(1);
			        }
					if((time_up - time_dowm) >3)
					{
					    play_mod = 0;
					}
				}
		    }
	    }
	}
	close(buttons_fd);
	return 0;
}


handle.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/wait.h>
#include <signal.h>
#define SINGLE 1
#define LOOP 2
#define RANDOM 3
#define SCAN 4

extern struct DuLNode
{
    char num[100];
    struct DuLNode *prior,*next;
};
extern struct DuLNode *head;
extern struct DuLNode *current_head;
extern int play_mod;

handle.c
#include "../../include/handle.h"

/***************************************************
函數名:play
功能:播放mp3
傳入參數:struct DuLNode*current_head
返回值:int
***************************************************/
int play(struct DuLNode*current_head)
{  
   char str[100];
   char this_song[100]="/mp3/song/";
   int len;
   strcat(this_song,current_head->num);
   len = strlen(this_song);
   this_song[len]='\0';
   execl("/mp3/madplay","madplay",this_song,NULL);
   return 0;
}

/***************************************************
函數名:play_show
功能:顯示播放信息
傳入參數:void
返回值:void
***************************************************/
void play_show()
{
    int count;
    count = count_DuLNode();/*獲得歌曲數目*/
	system("clear");
	printf("song amount:%d\n",count);
	switch(play_mod)/*顯示播放模式*/
	{
	    case SINGLE:
	    {
		    printf("play mod:SINGLE\n");
			break;
		}
	    case LOOP:
		{
			printf("play mod:LOOP\n");
			break;
		}
		case RANDOM:
		{
					
		    printf("play mod:RANDOM\n");
			break;
		}
		case SCAN:
		{
					
		    printf("play mod:SCAN\n");
			break;
		}
		default:
		{
			break;
		}
	}
	printf("[previous song]:%s\n",(current_head->prior)->num);/*顯示上一首*/
	printf("[next song]:%s\n",(current_head->next)->num);/*顯示下一首*/
	printf("[this song]:%s\n",current_head->num);/*顯示當前歌曲*/
}

/***************************************************
函數名:start_play
功能:開始播放
傳入參數:pid_t ppid
返回值:int
***************************************************/
int start_play(pid_t ppid)
{
    int fd;
	char buf[100];
	pid_t pid;

    while(1)
	{
		pid = fork();/*創建子進程*/
		if(pid<0)
		{
		   perror("fork error!\n");
		   exit(1);
		}
		else if(pid==0)/*子進程*/
		{ 
			play_show();
		    interface();
			play(current_head);
		    exit(0);
		}
		else/*父進程*/
		{
		    if( play_mod == SCAN)
		    {
		        int i = 0;
				for(i = 0;i < 10;i++)
				{
				    sleep(1);
				}
				system("killall -9 madplay");/*停止播放*/
		    }
			if(wait(NULL) == -1)/*等待子進程退出*/
			{
				perror("fail to wait!\n");
				exit(1);
			}
			switch(play_mod)/*根據播放模式,選擇下一首*/
			{
			    case SINGLE:/*單曲循環*/
				{
					break;
				}
			    case LOOP:/*順序播放*/
				{
					current_head = current_head->next;
					if(kill(ppid,SIGUSR1) == -1)/*向父進程發送信號SIGUSR1*/
					{
						perror("fail to send signal");
						exit(1);
					}
					break;
				}
			    case RANDOM:/*隨機播放*/
				{
					int i;
					int step;
					srand((int)time(0));
					step = 1+(int)(100.0*rand()/(RAND_MAX+1.0));
					for(i=0;i<step;i++)
					{
						current_head = current_head->next;
						if(kill(ppid,SIGUSR1) == -1)/*向父進程發送信號SIGUSR1*/
						{
							perror("fail to send signal");
							exit(1);
						}
					}
					break;
				}
				case SCAN:
				{
					current_head = current_head->next;
					if(kill(ppid,SIGUSR1) == -1)/*向父進程發送信號SIGUSR1*/
					{
						perror("fail to send signal");
						exit(1);
					}
					break;
				}
				default:
				{
					break;
				}
			}
			
		}
	}
   return 0;
}

   


DuLinkList_file.h

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"unistd.h"
#include"sys/types.h"
#include"fcntl.h"
#include"dirent.h"

extern struct DuLNode
{
    char num[100];
    struct DuLNode *prior,*next;
};
extern struct DuLNode *head;
extern struct DuLNode *current_head;

DuLinkList_file.c
#include "../../include/DuLinkList_file.h"

/***************************************************
函數名:DuLinkList_init
功能:初始化
傳入參數:void
返回值:void
***************************************************/
void DuLinkList_init()
{
    head = (struct DuLNode *)malloc(sizeof(struct DuLNode));
    head->prior = head;
    head->next = head;
	current_head = head;
	head->num[0] = '\0';
	DIR *dp;
	struct dirent *dirp;
	//打開指定的目錄
	if ((dp = opendir("./song")) == NULL)
	{
		printf("can't open \n");
		exit(1);
	}	
	//遍歷目錄
	while ((dirp = readdir(dp)) != NULL)
	{
	    if(strcmp(dirp->d_name,".")==0 || strcmp(dirp->d_name,"..")==0)
	    {			
	        continue;
	    }
		add_DuLNode(dirp->d_name);
	}
	//關閉目錄
	closedir(dp);
}

/***************************************************
函數名:add_DuLNode
功能:插入結點
傳入參數:char *num
返回值:void
***************************************************/
void add_DuLNode(char *num) 
{
    if(head->num[0] == '\0')
    {
		strcpy(head->num,num);
    }
	else
	{	
		struct DuLNode *ptr = (struct DuLNode *)malloc(sizeof(struct DuLNode));
		strcpy(ptr->num,num);
	    ptr->next=head->next;
        head->next=ptr;
	    ptr->prior=head;
	    ptr->next->prior=ptr;
	}
}

/***************************************************
函數名:display_DuLNode
功能:遍歷鏈表
傳入參數:void
返回值:void
***************************************************/
void display_DuLNode()
{
    struct DuLNode *p = head;
    do
    {
        printf("%s\n",p->num);
        p = p->next;
    }while(p!=head);
}

/***************************************************
函數名:display_next_DuLNode
功能:顯示下一首歌曲
傳入參數:void
返回值:void
***************************************************/
void display_next_DuLNode() 
{
	current_head = current_head->next;
    printf("%s\n",current_head->num);
}

/***************************************************
函數名:display_prior_DuLNode
功能:顯示上一首歌曲
傳入參數:void
返回值:void
***************************************************/
void display_prior_DuLNode() 
{
	current_head = current_head->prior;
    printf("%s\n",current_head->num);
}

/***************************************************
函數名:count_DuLNode
功能:計算鏈表結點數目
傳入參數:void
返回值:int count
***************************************************/
int count_DuLNode()
{
    struct DuLNode *p = head;
	int count = 0;
    do
    {
        count++;
        p = p->next;
    }while(p!=head);
	return count;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章