基于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; }