基于mini2440开发板和MADPLAY,用声卡,按键实现MP3功能,通过mini2440的6个按键实现开始,暂停,上一首,下一首,音量+,音量-的功能,而且可以顺序播放和随机播放。
按键平台驱动
device
#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 button_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_button;
static int __init platform_dev_init(void)
{
int ret;
my_button = platform_device_alloc("my_button", -1);
platform_device_add_resources(my_button,button_resource,6);
ret = platform_device_add(my_button);
if(ret)
{
platform_device_put(my_button);
}
return ret;
}
static void __exit platform_dev_exit(void)
{
platform_device_unregister(my_button);
}
module_init(platform_dev_init);
module_exit(platform_dev_exit);
MODULE_AUTHOR("zxf");
MODULE_LICENSE("GPL");
driver
#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>
#define DEVICE_NAME "buttons"
struct button_irq_desc {
int irq;
int pin;
int pin_setting;
int number;
char *name;
};
static struct button_irq_desc button_irqs [] = {
{IRQ_EINT8 , S3C2410_GPG(0) , S3C2410_GPG0_EINT8 , 0, "KEY0"},
{IRQ_EINT11, S3C2410_GPG(3) , S3C2410_GPG3_EINT11 , 1, "KEY1"},
{IRQ_EINT13, S3C2410_GPG(5) , S3C2410_GPG5_EINT13 , 2, "KEY2"},
{IRQ_EINT14, S3C2410_GPG(6) , S3C2410_GPG6_EINT14 , 3, "KEY3"},
{IRQ_EINT15, S3C2410_GPG(7) , S3C2410_GPG7_EINT15 , 4, "KEY4"},
{IRQ_EINT19, S3C2410_GPG(11), S3C2410_GPG11_EINT19, 5, "KEY5"},
};
static volatile char key_values [] = {'0', '0', '0', '0', '0', '0'};
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
static volatile int ev_press = 0;
static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;
int down;
// udelay(0);
down = !s3c2410_gpio_getpin(button_irqs->pin);
if (down != (key_values[button_irqs->number] & 1)) { // Changed
key_values[button_irqs->number] = '0' + down;
ev_press = 1;
wake_up_interruptible(&button_waitq);
}
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 < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
if (button_irqs[i].irq < 0) {
continue;
}
err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH,
button_irqs[i].name, (void *)&button_irqs[i]);
if (err)
break;
}
if (err) {
i--;
for (; i >= 0; i--) {
if (button_irqs[i].irq < 0) {
continue;
}
disable_irq(button_irqs[i].irq);
free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
}
return -EBUSY;
}
ev_press = 1;
return 0;
}
static int s3c24xx_buttons_close(struct inode *inode, struct file *file)
{
int i;
for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
if (button_irqs[i].irq < 0) {
continue;
}
free_irq(button_irqs[i].irq, (void *)&button_irqs[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 = DEVICE_NAME,
.fops = &dev_fops,
};
static int my_plat_probe(struct platform_device *dev)
{
int ret,i;
struct resource *button_resource;
struct platform_device *pdev = dev;
printk("platform dirver mach platfrom device.\n");
for( i=0; i < 6; i++ )
{
button_resource = platform_get_resource(pdev,IORESOURCE_IRQ,i);
if( button_resource == NULL )
{
return -ENOENT;
}
button_irqs[i].irq = button_resource->start;
}
ret = misc_register(&misc);
if(ret)
{
return ret;
}
return 0;
}
static int my_plat_remove(struct platform_device *dev)
{
printk("my platfrom button has removed.\n");
misc_deregister(&misc);
return 0;
}
struct platform_driver my_button =
{
.probe = my_plat_probe,
.remove = my_plat_remove,
.driver =
{
.owner = THIS_MODULE,
.name = "my_button",
},
};
static int __init platform_drv_init(void)
{
int ret;
ret = platform_driver_register(&my_button);
printk (DEVICE_NAME"\tinitialized\n");
return ret;
}
static void __exit platform_drv_exit(void)
{
platform_driver_unregister(&my_button);
}
module_init(platform_drv_init);
module_exit(platform_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("FriendlyARM Inc.");
source
modulechoose.c
#include"../include/mp3.h"
int module_choose( int buttons_fd,char *buttons)
{
int i = 0;
int flag = 1;
int choose = 7;
enum module { ran, list, quit };
while(flag)
{
char current_buttons[6];
printf("\n\n\n\n\n\n\n\n\t\t\t play moudle choose\n\n\n");
// printf("\t\t\t K1:singal\n");
printf("\t\t\t k1:random\n");
printf("\t\t\t k2:list\n");
printf("\t\t\t k3:poweroff\n\n\n\n\n\n\n");
printf("please input:\n");
if ( read(buttons_fd, current_buttons, sizeof ( current_buttons ) ) != sizeof ( current_buttons) )
{
perror("read buttons:");
exit(1);
}
for ( i = 0; i < 6; i++)
{
if ( buttons[i] != current_buttons[i] )
{
buttons[i] = current_buttons[i];
if( buttons[i] == '1')
{
goto over;
}
choose = i;
}
}
if( choose == 7)
{
system("clear");
continue;
}
switch( choose )
{
case ran:
{
system("clear");
printf("\n\n\n\n\n\n\n\n\n\n\n\t\t\tyou choose random moudle\n\n\n\n\n\n\n\n\n\n\n\n");
flag = 0;
sleep(1);
break;
}
case list:
{
system("clear");
printf("\n\n\n\n\n\n\n\n\n\n\n\t\t\tyou chooose list moudle\n\n\n\n\n\n\n\n\n\n\n\n");
flag = 0;
sleep(1);
break;
}
#if 0
case ran :
{
system("clear");
printf("\n\n\n\n\n\n\n\n\n\n\n\t\t\tyou chooose random moudle\n\n\n\n\n\n\n\n\n\n\n\n");
flag = 0;
sleep(1);
break;
}
#endif
case quit:
{
system("clear");
printf("\n\n\n\n\n\n\n\n\n\n\n\t\t\t\tsee you!\n\n\n\n\n\n\n\n\n\n\n\n");
sleep(1);
close( buttons_fd );
exit(0);
}
default :
{
printf("press key error!\n");
sleep(1);
}
}
over:
system("clear");
}
return choose;
}
songdir.c
#include "../include/mp3.h"
dl * dircreate()
{
DIR *mydir;
dl *head = NULL;
dl *last = NULL;
struct dirent *myitem;
mydir = opendir("./song/");
while( ( myitem = readdir(mydir) ) != NULL )
{
if( ( strcmp(myitem->d_name,".") == 0 ) || ( strcmp(myitem->d_name,"..") == 0) )
{
continue;
}
dl *p = (dl *)malloc(sizeof(dl));
if( head == NULL)
{
strcpy(p->name,myitem->d_name);
head = p;
head->front = NULL;
head->frev = head;
last = p;
}
else
{
strcpy(p->name,myitem->d_name);
last->frev = p;
p->front = last;
last = p;
last->frev = head;
}
}
head->front = last;
closedir(mydir);
return head;
}
void print( dl *head )
{
dl *p = head;
printf("mp3 has the song list: ");
while( p->frev != head )
{
printf( "%s ", p->name );
p = p->frev;
}
printf("%s\n",p->name);
}
disp.c
#include "../include/mp3.h"
void disp( dl *p, char *state, dl *head, int moudle)
{
system("clear");
printf("\n\n\n\t\t******************* MP3 Player *******************\n");
printf("\n\t\t\tk1 start\t\tk5 stop\n\n");
printf("\n\t\t\tk3 next \t\tk6 front\n\n");
printf("\n\t\t\tk2 up \t\tk4 down \n\n");
printf("the current state is: %s\n\n",state);
print(head);
if( moudle == 1 )
{
printf("\nthe current play moudle is: list\n");
}
else
{
printf("\nthe current play moudle is: random\n");
}
printf("\nthe current song is: %s \n",p->name);
if( moudle == 1 )
{
printf("\nthe next song is: %s\n",p->frev->name);
}
printf("\n\nwait the choose:\n");
}
function.c
#include"../include/mp3.h"
void function( int buttons_fd, dl *p, char *buttons, int moudle)
{
char state[5];
char current_buttons[6];
int MIX_FD = open("/dev/mixer", O_WRONLY);
int value = 50;
int iLevel;
int iLeft = 0;
int iRight = 0;
iLeft = iRight = value;
iLevel = (iRight << 8) + iLeft;
ioctl(MIX_FD, MIXER_WRITE(SOUND_MIXER_VOLUME), &iLevel);
int i = 0;
int choose = 7;
strcpy( state,"stop");
char cmd[30];
int flag = 0;
enum fun { start, up, next, down, stop, front };
pid_t pid = 0;
dl *head = p;
int shmid;
if( ( shmid = shmget( IPC_PRIVATE, sizeof(dl), 0777 ) ) < 0 )
{
perror("fail to shmget");
exit(-1);
}
dl *shmaddr;
shmaddr = (dl *)shmat( shmid,NULL,0);
memcpy(shmaddr,head,sizeof(dl));
shmaddr->flag = 0;
while(1)
{
disp( p, state, head, moudle);
over:
if ( read(buttons_fd, current_buttons, sizeof ( current_buttons ) ) != sizeof ( current_buttons) )
{
perror("read buttons:");
exit(-1);
}
if( shmaddr->flag == 1)
{
p = shmaddr;
shmaddr->flag = 0;
}
for ( i = 0; i < 6; i++)
{
if ( buttons[i] != current_buttons[i] )
{
buttons[i] = current_buttons[i];
if( buttons[i] == '1')
{
goto over;
}
choose = i;
}
}
switch( choose )
{
case start:
{
if( strcmp( state,"stop") == 0)
{
strcpy( state,"play");
if( flag == 1)
{
system("killall -CONT my_madplay &");
}
else
{
flag = 1;
pid = fork();
if(pid == 0)
{
while(1)
{
disp( p,state,head,moudle);
sprintf(cmd,"my_madplay ./song/%s", p->name);
system(cmd);
sleep(1);
if( moudle == 1 )
{
p = p->frev;
p->flag = 1;
memcpy( shmaddr, p,sizeof(dl));
}
else
{
int n = rand()%3 + 1;
while( n-- )
{
p = p->frev;
}
p->flag = 1;
memcpy( shmaddr, p,sizeof(dl));
}
}
}
}
}
else
{
printf("the mp3 is already play!\n");
sleep(1);
}
system("clear");
break;
}
case stop:
{
if( strcmp( state, "stop" ) == 0)
{
printf("the mp3 current is stop!\n");
sleep(1);
}
else
{
strcpy( state,"stop");
system("killall -STOP my_madplay &");
}
break;
}
case front:
{
int n = rand()%3 + 1;
if( strcmp( state,"play") == 0 )
{
system("killall -9 my_madplay");
kill(pid,9);
if( moudle == 1)
{
p = p->front;
}
else
{
while(n--)
{
p = p->front;
}
}
pid = fork();
if( pid < 0 )
{
printf("fork error\n");
}
if( pid == 0 )
{
while(1)
{
disp( p,state,head, moudle);
memset( cmd, 0, 30);
sprintf(cmd,"my_madplay ./song/%s ", p->name);
system(cmd);
sleep(1);
if( moudle == 1 )
{
p = p->front;
}
else
{
int n = rand()%3 + 1;
while(n--)
{
p = p->front;
}
}
p->flag = 1;
memcpy( shmaddr, p, sizeof(dl) );
}
}
}
else
{
if( flag == 1)
{
system("killall -9 my_madplay");
kill( pid, 9);
flag = 0;
}
if( moudle == 1)
{
p = p->front;
}
else
{
while(n--)
{
p = p->front;
}
}
}
break;
}
case next:
{
int n = rand()%3 + 1;
if( strcmp( state,"play") == 0)
{
system("killall -9 my_madplay");
kill( pid, 9);
if( moudle == 1)
{
p = p->frev;
}
else
{
while(n--)
{
p = p->frev;
}
}
pid = fork();
if( pid < 0 )
{
printf("press error!\n");
exit(-1);
}
if( pid == 0 )
{
while(1)
{
disp( p, state, head, moudle);
memset( cmd, 0, 30 );
sprintf(cmd,"my_madplay ./song/%s ", p->name);
system(cmd);
sleep(1);
if( moudle == 1 )
{
p = p->frev;
}
else
{
int n = rand()%3 + 1;
while(n--)
{
p = p->frev;
}
}
p->flag = 1;
memcpy( shmaddr, p, sizeof(dl) );
}
}
}
else
{
if( flag == 1)
{
system("killall -9 my_madplay");
kill( pid, 9);
flag = 0;
}
if( moudle == 1)
{
p = p->frev;
}
else
{
while(n--)
{
p = p->frev;
}
}
}
break;
}
case up:
{
if( value < 100 )
{
value = value + 5;
}
iLeft = iRight = value;
iLevel = (iRight << 8) + iLeft;
ioctl(MIX_FD, MIXER_WRITE(SOUND_MIXER_VOLUME),
&iLevel);
printf("voice up done\n"); sleep(1);
break;
}
case down:
{
if( value > 0)
{
value = value - 5;
}
iLeft = iRight = value;
iLevel = (iRight << 8) + iLeft;
ioctl(MIX_FD, MIXER_WRITE(SOUND_MIXER_VOLUME), &iLevel);
printf("voice down done\n");
sleep(1);
break;
}
default :
{
printf("press error\n");
sleep(1);
}
}
}
}
main.c
#include "../include/mp3.h"
int main()
{
int module = 0;
dl *head;
system("clear");
int buttons_fd;
buttons_fd = open("/dev/buttons", 0);
if ( buttons_fd < 0 )
{
perror("open device buttons");
exit(-1);
}
char buttons[6] = { '0', '0', '0', '0', '0', '0' };
printf("\n\n\n\n\n\n\n\n\n\n\n\t\t\t\tenjoy music\n\n\n\n\n\n\n\n\n\n\n\n");
sleep(1);
system("clear");
module = module_choose( buttons_fd,buttons );
head = dircreate();
function( buttons_fd, head, buttons, module);
return 0;
}