# include  <linux/init.h> # include  <linux/module.h> # include  <linux/fs.h> # include  <linux/device.h> # include  <linux/cdev.h> # include  <linux/slab.h> # include  <linux/io.h> # include <linux/of.h> # include <linux/gpio.h> # include <linux/of_gpio.h> # include <linux/uaccess.h> # include <linux/of_irq.h>  # include <linux/interrupt.h>  # include <linux/platform_device.h> # include <linux/mod_devicetable.h> struct  cdev  * cdev; 
unsigned  int  major =  0 ; 
unsigned  int  minor =  0 ; 
dev_t  devno; 
struct  class  * cls; 
struct  device  * dev; 
char  number =  '0' ; 
unsigned  int  irqno; 
struct  gpio_desc  * gpiono; 
wait_queue_head_t  wq_head; 
unsigned  int  condition =  0 ; 
irqreturn_t  myirq_handler ( int  irqno,  void  * dev_id) 
{ 
    
    if ( number ==  '0' ) 
    { 
        number =  '1' ; 
        
        gpiod_set_value ( gpiono, 1 ) ; 
    } 
    else 
    { 
        number =  '0' ; 
        gpiod_set_value ( gpiono, 0 ) ; 
    } 
     
    condition =  1 ; 
    
    wake_up_interruptible ( & wq_head) ; 
    return  IRQ_HANDLED; 
} 
int  mycdev_open ( struct  inode  * inode,  struct  file  * file) 
{ 
    return  0 ; 
} 
ssize_t  mycdev_read  ( struct  file  * file,  char  * ubuf,  size_t  size,  loff_t  * lof) 
{ 
    int  ret; 
    wait_event_interruptible ( wq_head, condition) ; 
    printk ( "size=%d\n" , size) ; 
    ret =  copy_to_user ( ubuf,  & number,  size) ; 
    if ( ret) 
    { 
        printk ( "copy_to_user filed\n" ) ; 
        return  - EIO; 
    } 
    printk ( "num%c\n" , number) ; 
    condition =  0 ; 
    return  0 ; 
} 
ssize_t  mycdev_write  ( struct  file  * file,  const  char  * ubuf,  size_t  size,  loff_t  * lof) 
{ 
    return  0 ; 
} 
int  mycdev_close ( struct  inode  * inode,  struct  file  * file) 
{ 
    printk ( "%s:%s:%d\n" ,  __FILE__ ,  __func__ ,  __LINE__ ) ; 
    return  0 ; 
} 
struct  file_operations  fops = 
    { 
        . open =  mycdev_open, 
        . read =  mycdev_read, 
        . write =  mycdev_write, 
        . release =  mycdev_close, 
} ; 
int  pdrv_probe ( struct  platform_device  * pdev) 
{ 
    int  ret; 
    
    init_waitqueue_head ( & wq_head) ; 
    
    
    irqno =  platform_get_irq ( pdev, 0 ) ; 
    if ( irqno <  0 ) 
    { 
        printk ( "获取中断资源失败\n" ) ; 
        return  irqno; 
    } 
    printk ( "获取中断资源成功%d\n" , irqno) ; 
      
    ret =  request_irq ( irqno, myirq_handler, IRQF_TRIGGER_FALLING, "key1" , NULL ) ; 
    if ( ret) 
    { 
        printk ( "注册驱动失败\n" ) ; 
        return  ret; 
    } 
    printk ( "key1中断注册成功\n" ) ; 
     
    gpiono =  gpiod_get_from_of_node ( pdev-> dev. of_node, "led1" , 0 , GPIOD_OUT_LOW, NULL ) ; 
    if ( IS_ERR ( gpiono) ) 
    { 
        printk ( "gpio编号解析失败" ) ; 
        return  - PTR_ERR ( gpiono) ; 
    } 
     
    gpiod_set_value ( gpiono, 0 ) ; 
    
    cdev =  cdev_alloc ( ) ; 
    if  ( NULL  ==  cdev) 
    { 
        printk ( "字符设备驱动对象空间失败\n" ) ; 
        ret =  - EFAULT; 
        goto  out1; 
    } 
    printk ( "字符设备驱动对象空间申请成功" ) ; 
    
    cdev_init ( cdev,  & fops) ; 
    
    if  ( major >  0 ) 
    { 
        ret =  register_chrdev_region ( MKDEV ( major,  minor) ,  1 ,  "myled" ) ; 
        if  ( ret) 
        { 
            printk ( "静态指定设备号失败\n" ) ; 
            goto  out2; 
        } 
    } 
    else  
    { 
        ret =  alloc_chrdev_region ( & devno,  minor,  1 ,  "myled" ) ; 
        if  ( ret) 
        { 
            printk ( "动态指定设备号失败\n" ) ; 
            goto  out2; 
        } 
        major =  MAJOR ( devno) ; 
        minor =  MINOR ( devno) ; 
    } 
    printk ( "申请设备号成功\n" ) ; 
    
    ret =  cdev_add ( cdev,  MKDEV ( major,  minor) ,  1 ) ; 
    if  ( ret) 
    { 
        printk ( "注册字符设备驱动对象失败\n" ) ; 
        goto  out3; 
    } 
    printk ( "注册字符设备驱动对象成功\n" ) ; 
    
    
    cls =  class_create ( THIS_MODULE,  "myled" ) ; 
    if  ( IS_ERR ( cls) ) 
    { 
        printk ( "向上提交目录失败\n" ) ; 
        ret =  - PTR_ERR ( cls) ; 
        goto  out4; 
    } 
    printk ( "向上提交目录成功\n" ) ; 
    
    
    
        dev =  device_create ( cls,  NULL ,  MKDEV ( major,  0 ) ,  NULL ,  "myled" ) ; 
        if  ( IS_ERR ( dev) ) 
        { 
            printk ( "向上提交设备节点信息失败\n" ) ; 
            ret =  - PTR_ERR ( dev) ; 
            goto  out5; 
        } 
    
    printk ( "线上提交设备节点信息成功\n" ) ; 
    return  0 ; 
out5: 
    
    device_destroy ( cls,  MKDEV ( major,  0 ) ) ; 
    class_destroy ( cls) ; 
out4: 
    cdev_del ( cdev) ; 
out3: 
    unregister_chrdev_region ( MKDEV ( major,  minor) ,  1 ) ; 
out2: 
    kfree ( cdev) ; 
out1: 
    return  ret; 
} 
int  pdrv_remove ( struct  platform_device  * pdev) 
{ 
    
    gpiod_set_value ( gpiono, 0 ) ; 
     
        device_destroy ( cls,  MKDEV ( major,  0 ) ) ; 
    
    class_destroy ( cls) ; 
    
    cdev_del ( cdev) ; 
    
    unregister_chrdev_region ( MKDEV ( major,  minor) ,  1 ) ; 
    
    kfree ( cdev) ; 
    
    gpiod_put ( gpiono) ; 
    
    free_irq ( irqno, NULL ) ; 
    return  0 ; 
} 
struct  of_device_id  oftable[ ] = { 
    { . compatible= "hqyj,myplatform" , } , 
    { . compatible= "hqyj,myplatform1" , } , 
    { } , 
} ; 
struct  platform_driver  pdrv= { 
    . probe =  pdrv_probe, 
    . remove =  pdrv_remove, 
    . driver =  { 
        . name =  "aaaaa" , 
        . of_match_table =  oftable, 
    } , 
} ; 
module_platform_driver ( pdrv) ; 
MODULE_LICENSE ( "GPL" ) ; 
# include  <stdlib.h> # include  <stdio.h> # include  <sys/types.h> # include  <sys/stat.h> # include  <fcntl.h> # include  <unistd.h> # include  <string.h> # include  <sys/ioctl.h> int  main ( int  argc,  char  const  * argv[ ] ) 
{ 
    int  fd; 
    char  number; 
    fd =  open ( "/dev/myled" ,  O_RDWR) ; 
    if  ( fd <  0 ) 
    { 
        printf ( "打开文件失败\n" ) ; 
        exit ( - 1 ) ; 
    } 
    while  ( 1 ) 
    { 
        read ( fd,  & number,  sizeof ( number) ) ; 
        printf ( "number = %c\n" ,  number) ; 
    } 
    close ( fd) ; 
    return  0 ; 
}