按键平台驱动:
platfrom_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("Z-YP"); MODULE_LICENSE("GPL");
platfrom_derver.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> #define DEVICE_NAME "my_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 = "my_buttons", .fops = &dev_fops, }; #if 1 static int my_plat_probe(struct platform_device *dev) { int ret,i; struct resource *plat_resource; struct platform_device *pdev = dev; //printk("----"); for(i = 0;i < 6;i++) { plat_resource = platform_get_resource(pdev,IORESOURCE_IRQ,i); if(plat_resource == NULL) { return -ENOENT; } button_irqs[i].irq = plat_resource->start; } ret = misc_register(&misc); if(ret) { return ret; } return 0; } #endif static int my_plat_remove(struct platform_device *dev) { printk("my platfrom device has removed."); 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); printk (DEVICE_NAME"\tinitialized\n"); 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_LICENSE("GPL"); MODULE_AUTHOR("Z-YP");
应用程序:
mymp3.h:
typedef struct node { char data[100]; struct node *left; struct node *right; }NODE; enum modules{mod1,mod2}; enum mp3buttons{pre,start,next,pau,up,down}; NODE *mycreatedoublelist(void); extern void mp3_display(NODE *,int,int *,int *,int); extern int module(void);
mp3.c:
#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/types.h> #include <sys/wait.h> #include <linux/soundcard.h> #include <sys/ipc.h> #include <sys/shm.h> #include "mymp3.h" int main(void) { int buttons_fd,mix_fd; int iLeft = 0; int iRight = 0; int iLevel; int volume = 75; iLeft = iRight = volume; iLevel = (iRight << 8) + iLeft; int mod; int ret; int sta = 0; int isstart = 0; int rand; int flg = 0; int num = 0; int stop = 0; char play[60]; NODE *shmptr = NULL; int shmid; NODE *head = mycreatedoublelist(); NODE *p = head; mod = module(); mp3_display(head,10,&volume,&flg,mod); char buttons[6] = {'0', '0', '0', '0', '0', '0'}; buttons_fd = open("/dev/my_buttons",0); if (buttons_fd < 0) { perror("open device buttons\n"); exit(1); } mix_fd = open("/dev/mixer",O_WRONLY); if(mix_fd < 0) { perror("open device mixer\n"); exit(1); } ioctl(mix_fd,MIXER_WRITE(SOUND_MIXER_VOLUME),&iLevel); shmid = shmget(IPC_PRIVATE,sizeof(NODE),0777); shmptr = (NODE *)shmat(shmid,0,0); memcpy(shmptr,p,sizeof(NODE)); for (;;) { char current_buttons[6]; int count_of_changed_key; int i; int changeflg = 0; pid_t pid,playpid; if (read(buttons_fd, current_buttons, sizeof current_buttons) != sizeof current_buttons) { perror("read buttons:"); exit(1); } for (i = 0, count_of_changed_key = 0; i < sizeof buttons / sizeof buttons[0]; i++) { if (buttons[i] != current_buttons[i]) { buttons[i] = current_buttons[i]; if(buttons[i] == '1') { ; } else { switch(i) { case pau: { if(isstart != 0) { if(stop == 0) { system("killall -STOP madplay &"); kill(pid,19); stop = 1; } else { printf("haved stopped!\n"); sleep(1); } mp3_display(shmptr,pau,&volume,&flg,mod); } else { printf("Please input start frist!\n"); sleep(1); } break; } case pre: { if(num != 0) { kill(pid,9); system("killall -STOP madplay &"); system("killall -9 madplay &"); num = 0; } if(mod == 1) { p = shmptr; p = p->left; memset(shmptr,0,sizeof(NODE)); memcpy(shmptr,p,sizeof(NODE)); } else { rand = random() % 14 + 1; while(rand--) { p = shmptr; p = p->left; memset(shmptr,0,sizeof(NODE)); memcpy(shmptr,p,sizeof(NODE)); } } changeflg = 1; } case next: { if(changeflg != 1) { if(num != 0) { kill(pid,9); system("killall -STOP madplay &"); system("killall -9 madplay &"); num = 0; } if(mod == 1) { p = shmptr; p = p->right; memset(shmptr,0,sizeof(NODE)); memcpy(shmptr,p,sizeof(NODE)); } else { rand = random() % 14 + 1; while(rand--) { p = shmptr; p = p->right; memset(shmptr,0,sizeof(NODE)); memcpy(shmptr,p,sizeof(NODE)); } } } } case start: { if(stop == 1) { system("killall -CONT madplay &"); kill(pid,18); stop = 0; mp3_display(shmptr,start,&volume,&flg,mod); } else { if(num != 0) { system("killall -STOP madplay &"); system("killall -9 madplay &"); kill(pid,9); num = 0; } pid = fork(); if(pid < 0) { perror("fork error\n"); } else if(pid == 0) { loopv: playpid = fork(); if(playpid < 0) { perror("fork2 error\n"); } else if(playpid == 0) { execl("/music/madplay","./madplay",shmptr->data,NULL); } wait(&sta); if(WIFEXITED(sta) != 0) { p = shmptr; p = p->right; memset(shmptr,0,sizeof(NODE)); memcpy(shmptr,p,sizeof(NODE)); mp3_display(shmptr,start,&volume,&flg,mod); goto loopv; } else { mp3_display(shmptr,start,&volume,&flg,mod); goto loopv; } } else { changeflg = 0; num = 1; mp3_display(shmptr,start,&volume,&flg,mod); } } isstart = 1; break; } case up: { mp3_display(shmptr,up,&volume,&flg,mod); iLeft = iRight = volume; iLevel = (iRight << 8) + iLeft; ioctl(mix_fd,MIXER_WRITE(SOUND_MIXER_VOLUME),&iLevel); break; } case down: { mp3_display(shmptr,down,&volume,&flg,mod); iLeft = iRight = volume; iLevel = (iRight << 8) + iLeft; ioctl(mix_fd,MIXER_WRITE(SOUND_MIXER_VOLUME),&iLevel); break; } default: { break; } } count_of_changed_key++; } } } if (count_of_changed_key) { printf("\n"); } } shmctl(shmid,IPC_RMID,NULL); close(mix_fd); close(buttons_fd); return 0; }
mp3_display.c:
#include <stdio.h> #include <stdlib.h> #include "mymp3.h" void mp3_display(NODE *p,int choose,int *volume,int *flg,int mod) { system("clear"); switch(choose) { case start: { *flg = 1; break; } case pau: { *flg = 0; break; } case up: { if(*volume == 100) { printf("Volume is already max!\n"); sleep(1); system("clear"); } else { *volume = *volume + 5; } break; } case down: { if(*volume == 0) { printf("Volume is already min!\n"); sleep(1); system("clear"); } else { *volume = *volume - 5; } break; } case pre: { break; } case next: { break; } default: { break; } } printf("\n-----------------------------------------------------------------------------\n"); printf("\n\t\t\t\tZYP MP3 Player\n"); printf("\t\t Pre :%s\n",(mod == 1) ? (p->left->data) : ("Random......")); printf("\t\t Current:%s\n",p->data); printf("\t\t Next :%s\n",(mod == 1) ? (p->right->data) : ("Random......")); printf("\t\t Volume:%d\n",*volume); if(*flg == 0) { printf("\t\t Pause......\n"); } else { printf("\t\t Playing......\n"); } printf("\n-----------------------------------------------------------------------------\n"); printf("\t K1:pre \t\t\tK2:start \n"); printf("\t K3:next \t\t\tK4:pause \n"); printf("\t K5:up \t\t\tK6:down \n"); }
mp3_doubledir.c:
#include<stdio.h> #include<string.h> #include<fcntl.h> #include<dirent.h> #include<stdlib.h> #include "mymp3.h" NODE * mycreatedoublelist() { int i = 1; int j = 0; char * buffer[20]; for(;j < 20; j++) { buffer[j] = (char *)malloc(50); } j = 0; DIR *mydir; struct dirent *myitem; mydir = opendir("/music"); while((myitem = readdir(mydir)) != NULL) { if((strcmp(myitem->d_name,"mymp3") == 0) || (strcmp(myitem->d_name,"madplay") == 0) || (strcmp(myitem->d_name,".") == 0) || (strcmp(myitem->d_name,"..") == 0)) { continue; } strcpy(buffer[j],myitem->d_name); j++; } NODE *last; NODE *head = (struct node *)malloc(sizeof(struct node)); head->left = head; head->right = head; strcpy(head->data,buffer[0]); last = head; for(i = 2;i <= j;i++) { NODE *p = (struct node *)malloc(sizeof(struct node)); head->left = p; p->right = head; last->right = p; p->left = last; strcpy(p->data,buffer[i-1]); last = p; } return head; }
mp3_module.c:
#include <stdio.h> #include <stdlib.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 "mymp3.h" int module(void) { system("clear"); printf("\n\n\n\n\n\n\n\n"); printf("\n-------------------------------------------------------------------------------\n"); printf("\n\t\t\t\tZYP MP3 Player\n"); printf("\n-------------------------------------------------------------------------------\n"); sleep(2); int buttons_fd; char buttons[6] = {'0', '0', '0', '0', '0', '0'}; buttons_fd = open("/dev/my_buttons",0); if (buttons_fd < 0) { perror("open device buttons\n"); exit(1); } for (;;) { system("clear"); printf("\n-------------------------------------------------------------------------------\n"); printf("\n\n\n\t\t\t\tMODULES:\n"); printf("\t\t 1.In order\n"); printf("\t\t 2.Random\n"); printf("\n-------------------------------------------------------------------------------\n"); printf("\n\t\tPlease select module:\n"); char current_buttons[6]; int count_of_changed_key; int i; if (read(buttons_fd, current_buttons, sizeof current_buttons) != sizeof current_buttons) { perror("read buttons:"); exit(1); } for (i = 0, count_of_changed_key = 0; i < sizeof buttons / sizeof buttons[0]; i++) { if (buttons[i] != current_buttons[i]) { buttons[i] = current_buttons[i]; if(buttons[i] == '1') { ; } else { switch(i) { case mod1: { goto loop1; } case mod2: { goto loop2; } default: { printf("\n\n\t\tNo such module!\n"); sleep(1); break; } } //printf("%skey %d is %s", count_of_changed_key ? ", ": "", i+1, buttons[i] == '0' ? "up" : "down"); count_of_changed_key++; } } } if (count_of_changed_key) { printf("\n"); } } close(buttons_fd); loop1: close(buttons_fd); printf("\n\n\t\tYou choose mod1!\n"); sleep(2); return 1; loop2: close(buttons_fd); printf("\n\n\t\tYou choose mod2!\n"); sleep(2); return 2; }