linux2.4的button的驱动

 

注意2.4与2.6的不同:

——————————————————————————————————————————————————————

#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/delay.h>

#include <asm/hardware.h>

#define DEVICE_NAME "buttons"
#define BUTTON_MAJOR 232

static struct key_info {
 int irq_no;
 unsigned int gpio_port;
 int key_no;
} key_info_tab[4] = {
 { IRQ_EINT1, GPIO_F1, 1 },
 { IRQ_EINT2, GPIO_F2, 2 },
 { IRQ_EINT3, GPIO_F3, 3 },
 { IRQ_EINT7, GPIO_F7, 4 },
};

static int ready = 0;
static int key_value = 0;

/* 申明等待队列 */
static DECLARE_WAIT_QUEUE_HEAD(buttons_wait);

static void buttons_irq(int irq, void *dev_id, struct pt_regs *reg)
{
 struct key_info *k;
 int i;
 int found = 0;
 int up;
 int flags;
 
 /* 查找产生中断的按键 */
 for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++)
 {
  k = key_info_tab + i;
  if (k->irq_no == irq)
  {
   found = 1;
   break;
  }
 }
 if (!found)
 {
  printk("bad irq %d in button\n", irq);
  return;
 }

 /* 由于是快速中断处理,所以认为可以不用关中断 */
 //save_flags(flags);
 //cli();
 
 /* 设置端口模式 */
 set_gpio_mode_user(k->gpio_port, GPIO_MODE_IN);
 
 /* 判断是按键弹起还是按下 */
 up = read_gpio_bit(k->gpio_port);
 
 /* 重设中断模式,同时也清除了中断标志位 */
 set_external_irq(k->irq_no, EXT_BOTH_EDGES, GPIO_PULLUP_DIS);
 //restore_flags(flags);
        if (up)
         key_value = k->key_no + 0x80;
        else
         key_value = k->key_no;

        ready = 1;
        
        /* 唤醒等待的进程 */
 wake_up_interruptible(&buttons_wait);
}

static int request_irqs(void)
{
 struct key_info *k;
 int i;
 /* 为4个键分别注册中断 */
 for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++)
 {
  k = key_info_tab + i;
  /* 设置中断标志,考虑如果设置成单沿中断,或者使用上拉电阻会有什么影响? */
  set_external_irq(k->irq_no, EXT_BOTH_EDGES, GPIO_PULLUP_DIS);
  
  if (request_irq(k->irq_no, &buttons_irq, SA_INTERRUPT, DEVICE_NAME, &buttons_irq))
   return -1;
 }
 return 0;
}

static void free_irqs(void)
{
 struct key_info *k;
 int i;
 for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++)
 {
  k = key_info_tab + i;
  free_irq(k->irq_no, buttons_irq);
 }
}

static int sbc2410_buttons_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
 static int key;
 int flags;
 int repeat;
 
 /* 判断是否有数据可读 */
        if (!ready)
         return -EAGAIN;
       
        if (count != sizeof key_value)
                return -EINVAL;
 
 /*
 save_flags(flags);
 
 if (key != key_value)
 {
  key = key_value;
  repeat = 0;
 }
 else
 {
  repeat = 1;
 }
 
 
 restore_flags(flags);

 if (repeat) {
  return -EAGAIN;
 }
 */
 key = key_value;
 
        copy_to_user(buffer, &key, sizeof key);
       
        /* 清除准备好标志 */
        ready = 0;
        return sizeof key_value;
}

static unsigned int sbc2410_buttons_select(
        struct file *file,
        struct poll_table_struct *wait)
{
 /* 判断是否有按键中断产生 */
        if (ready)
                return 1;
       
        /* 如果没有,睡眠 */
        poll_wait(file, &buttons_wait, wait);
        return 0;
}


static struct file_operations sbc2410_buttons_fops = {
 owner: THIS_MODULE,
 poll: sbc2410_buttons_select,
 read: sbc2410_buttons_read,
};

static devfs_handle_t devfs_handle;
static int __init sbc2410_buttons_init(void)
{
 int ret;

 ready = 0;
 
 /* 注册字符设备驱动程序 */
 ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &sbc2410_buttons_fops);
 if (ret < 0) {
   printk(DEVICE_NAME " can't register major number\n");
   return ret;
 }
 
 /* 注册中断处理程序 */
 ret = request_irqs();
 if (ret) {
  unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
  printk(DEVICE_NAME " can't request irqs\n");
  return ret;
 }
 
 /* 创建设备节点 */
 devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
    BUTTON_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &sbc2410_buttons_fops, NULL);

 return 0;
}

static void __exit sbc2410_buttons_exit(void)
{
 devfs_unregister(devfs_handle);
 free_irqs();
 unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
}

module_init(sbc2410_buttons_init);
module_exit(sbc2410_buttons_exit);
MODULE_LICENSE("GPL");

 

在Python中实现一个简单的键盘模拟并通过2.4GHz无线模块通信,通常需要以下几个步骤: 1. **硬件准备**: - 你需要一个USB蓝牙或2.4GHz无线电发射模块(如ESP8266或树莓派的GPIO模块配合RF模块)。 - 接收端也需要一个能够接收到2.4GHz信号的设备,例如另一个相同的发射模块或者蓝牙接收器。 2. **软件库依赖**: - Python的`pyautogui`库可以用来获取键盘输入,模仿真实键盘操作。 - 对于发送2.4GHz信号,可能会使用像`RPi.GPIO`(树莓派GPIO)或第三方库如`uinput`(适用于Linux环境)。 ```python import pyautogui import RPi.GPIO as GPIO # 设置GPIO模式(如果是树莓派) GPIO.setmode(GPIO.BCM) # 设置按键对应的GPIO引脚 button_pin = 17 # 示例,选择一个GPIO引脚 def send_key(event): if event.name == 'keyDown': key_name = pyautogui.keyName(event.keycode) print(f"Sending {key_name} via wireless module") # 使用GPIO库发送信号到无线模块,这里只是一个示例,实际操作需参考对应模块文档 GPIO.output(button_pin, True) # 发送释放信号 time.sleep(0.1) # 短暂延迟再发送按下信号 GPIO.output(button_pin, False) # 监听键盘事件 for event in pyautogui.get ContinuousEvents(): send_key(event) # 键盘退出前清理GPIO资源 GPIO.cleanup() ``` 注意:这只是一个基本的概念演示,具体的实现会依赖于你的硬件配置、所选的Python库以及2.4GHz无线模块的具体驱动程序。实际应用中,你可能需要编写更复杂的错误处理和通信协议代码。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值