Openwrt定制按键输入

在OpenWRT中修改一个定制的按键输入需要涉及几个地方的修改:
1. 内核修改,添加需要操作的GPIO端口;
2. 在程序中使用netlink机制借助于socket API,检测按键输入。
3. 如果只是简单的操作,可以通过修改/etc/hotplug.d/button/buttons实现。

1、内核修改:
以AR9331为例,源代码路径:
openwrt/build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.49/arch/mips/ath79
修改对应的mach-xxx.c文件,具体的修改格式,参见其他mach-xxx.c文件。修改完成后,重新编译,更新内核即可。

build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.49/arch/mips/ath79/match-el-150.c
build_dir/target-mips_34kc_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.10.49/arch/mips/ath79/match-el-mini.c

示例:

static struct gpio_keys_button mini_gpio_keys[] __initdata = {
     {
          .desc          = "reset",
          .type          = EV_KEY,
          .code          = KEY_RESTART,
          .debounce_interval = MINI_KEYS_DEBOUNCE_INTERVAL,
          .gpio          = MINI_GPIO_BTN_RESET,
          .active_low     = 0,
     },
     {
          .desc          = "BTN_6",
          .type          = EV_KEY,
          .code          = BTN_6,
          .debounce_interval = MINI_KEYS_DEBOUNCE_INTERVAL,
          .gpio          = MINI_GPIO_BTN6,
          .active_low     = 1,
     },
};

2、使用Netlink机制
应用程序使用netlink,借助于socket API来实现按键的状态获取。当有按键按下的时候,read()函数会返回一个字符串,通过解析字字符串可以得知按下的按键以及按键的行为。
在使用时,必须包含的头文件:

#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <stddef.h>
#include <sys/wait.h>
#include <sys/epoll.h>
#include <sys/time.h>
// *******************************************************************
#define BUTTON_CONFIG        "BTN_6"
#define BUTTON_CONFIG_SIZE   (uint8_t)5
#define BUTTON_RESET         "reset"
// *******************************************************************
typedef struct  ButtonType {
  int type;
  int pressedTime;
} ButtonType;
// *******************************************************************
typedef struct  ButtonInputEvent {
  char *button;
  char *action;
} ButtonInputEvent;
// *******************************************************************
// static variables
static  ButtonType buttonType;
static  ButtonType *type;
static int  ButtonFd;
// *******************************************************************
int  InitNetlinkSock(void)
{
  struct sockaddr_nl snl;
  int retval;

  memset(&snl, 0x00, sizeof(struct sockaddr_nl));
  snl.nl_family = AF_NETLINK;
  snl.nl_pid = getpid();
  snl.nl_groups = 1;

  int hotplug_sock = socket(PF_NETLINK,SOCK_DGRAM,NETLINK_KOBJECT_UEVENT);
  if (hotplug_sock == -1) {
    printf("error get socket:%s",strerror(errno));
    return -1;
  }
  /* set receive buffersize */
  retval = bind(hotplug_sock,(struct sockaddr *)&snl,sizeof(struct sockaddr_nl));
  if (retval < 0) {
    printf("bind failed:%s",strerror(errno));
    close(hotplug_sock);
    hotplug_sock = -1;
    return -1;
  }

  return hotplug_sock;
}

int  ButtonInputParse( ButtonInputEvent *Button, char *msg)
{
  // When a button is pressed or released, we will get the following data:
  // string:
  // pressed@HOME=/PATH=/sbin:/bin:/usr/sbin:/usr/binSUBSYSTEM=buttonACTION=pressed\
  // BUTTON=BTN_7SEEN=1280SEQNUM=658 
  // Hex:
  // 70 72 65 73 73 65 64 40 00 48 4f 4d 45 3d 2f 00 50 41 54 48 3d 2f 73 62 69 6e 3a\
  // 2f 62 69 6e 3a 2f 75 73 72 2f 73 62 69 6e 3a 2f 75 73 72 2f 62 69 6e 00 53 55 42\
  // 53 59 53 54 45 4d 3d 62 75 74 74 6f 6e 00 41 43 54 49 4f 4e 3d 70 72 65 73 73 65\
  // 64 00 42 55 54 54 4f 4e 3d 42 54 4e 5f 37 00 53 45 45 4e 3d 31 32 38 30 00 53 45\
  // 51 4e 55 4d 3d 36 35 38 00
  // From the message, we will get the button and the action
  while(*msg) {
    if(!strncmp(msg, "ACTION=", 7)) {
      msg += 7;
      Button->action = msg;
    } else if (!strncmp(msg, "BUTTON=", 7)) {
      msg += 7;
      Button->button = msg;
      return  SUCCESS;
    }
    // advance to after the next \0
    while(*msg++);
  }

  return  ERR_FATAL;
}
// *******************************************************************
int  GetButtonAction(uint32_t interval)
{
  // TODO: add the code to return different command according to 
  // the interval 
  return  BUTTON_NULL;
}

int  ButtonActionParse( ButtonInputEvent *button)
{
  if (!strncmp(button->button,  BUTTON_CONFIG,  BUTTON_CONFIG_SIZE)){
    if (!strncmp(button->action, "pressed", 7)) {
      type->pressedTime =  GetCurrentSysTimeMillisecond();
    }

    if (!strncmp(button->action, "released", 8)) {
      uint32_t time;
      time =  GetCurrentSysTimeMillisecond();
      time = time - type->pressedTime;
      type->type =  GetButtonAction(time);
      return type->type !=  BUTTON_NULL?  SUCCESS:  ERR_FATAL;
    }
  }
  return  ERR_FATAL;
}
int  ButtonInput(uint8_t *inputType)
{
#define  NETLINK_BUF_SIZE  ((uint32_t)512)
  char buf[ NETLINK_BUF_SIZE];
  char *msg = buf;
  int netlinkSock;
  int result;

  netlinkSock =  ButtonFd;
  result = read(netlinkSock, buf,  NETLINK_BUF_SIZE - 1);
  result = result <  NETLINK_BUF_SIZE - 1? result:  NETLINK_BUF_SIZE - 1;
  buf[result] = '\0';
  buf[result + 1] = '\0';

  if (0 < result) {
    // Now we just handle a button
    // TODO: if two or more buttons are pressed, 
    // we should use other way to handle Buttons input.
     ButtonInputEvent button;
    result =  ButtonInputParse(&button, buf);
    if (result == SUCCESS) {
      result =  ButtonActionParse(&button);
    }
    *inputType = type->type;
  }
  return result;
}
// *******************************************************************
int  ButtonInputInit(void)
{
  type = &buttonType;
  ButtonFd = InitNetlinkSock();
  return  ButtonFd;
}

3、使用/etc/hotplug.d/button/buttons
如何使用Hotplug方式,响应按键。
关于Hotplug的介绍以及一些使用方法。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
再次更新,添加RGA100支持,添加LED触发器类型, 删除了按钮脚本,要自定义功能自己写脚本放在/etc/hotplud.d/button/ 下面 openwrt-RG100A_DB120-squashfs-cfe.bin http://115.com/file/c2bjz3px# 我的DB120-WG,双UBS,看着那么多的LED无法使用,于是泡论坛,看教程, 经过无数次的make, make V=99,终于修正了DB120的所有LED驱动,共9个LED, power和internet为双色LED,触发用time, 调整红色和绿色分量,可以显示绿色,橙色,红色等, 美中不足的是红灯太亮了,绿灯太弱,有条件的换下LED限流电阻 2012-2-1 增加了3个按钮 BTN_0 RESET 按住8秒后放开,系统复位 BTN_1 WLAN 无线开关 BTN_2 WPS umount 以后不要手贱,随便捅菊花了,结果你懂的 基本完美了,发挥你的想象吧 集成的软件都是我自己要用的,如motion做监控,图片保存在移动硬盘上, 当画面有变化时 mutt和ssmtp 发送邮件到139邮箱,有实时短信提醒. 通过N2N,配合视频监控软件可以随时随地查看家里状况 看到有个帖子里面用用Mplayer做网络收音机,又塞了个mplayer进去 集成USB声卡驱动,基本影音全能了 基于官方 OpenWrt Backfire 10.03.1 编译而成 软件包名称 版本 alsa-lib 1.0.24.1-1 alsa-utils 1.0.24.2-1 base-files 43.32-r29685 block-mount 0.1.0-2.2 bridge 1.4-1 busybox 1.15.3-3.4 bzip2 1.0.6-1 crda 1.1.1-1 dnsmasq 2.55-6.1 dropbear 0.53.1-5 firewall 2-34.8 gpioctl 1.0-1 hd-idle 1.03-1 hotplug2 1.0-beta-3 iptables 1.4.6-3.1 iptables-mod-conntrack 1.4.6-3.1 iptables-mod-conntrack-extra 1.4.6-3.1 iptables-mod-filter 1.4.6-3.1 iptables-mod-imq 1.4.6-3.1 iptables-mod-ipopt 1.4.6-3.1 iptables-mod-nat 1.4.6-3.1 iw 0.9.22-2 kernel 2.6.32.27-1 kmod-b43 2.6.32.27+2011-12-01-1 kmod-button-hotplug 2.6.32.27-1 kmod-cfg80211 2.6.32.27+2011-12-01-1 kmod-crc-ccitt 2.6.32.27-1 kmod-crypto-aes 2.6.32.27-1 kmod-crypto-arc4 2.6.32.27-1 kmod-crypto-core 2.6.32.27-1 kmod-fs-ext2 2.6.32.27-1 kmod-fs-ext3 2.6.32.27-1 kmod-fuse 2.6.32.27-1 kmod-i2c-core 2.6.32.27-1 kmod-input-core 2.6.32.27-1 kmod-input-gpio-buttons 2.6.32.27-1 kmod-input-polldev 2.6.32.27-1 kmod-ipt-conntrack 2.6.32.27-1 kmod-ipt-conntrack-extra 2.6.32.27-1 kmod-ipt-core 2.6.32.27-1 kmod-ipt-filter 2.6.32.27-1 kmod-ipt-imq 2.6.32.27-1 kmod-ipt-ipopt 2.6.32.27-1 kmod-ipt-nat 2.6.32.27-1 kmod-mac80211 2.6.32.27+2011-12-01-1 kmod-nls-cp437 2.6.32.27-1 kmod-nls-iso8859-1 2.6.32.27-1 kmod-nls-utf8 2.6.32.27-1 kmod-ppp 2.6.32.27-1 kmod-sched 2.6.32.27-1 kmod-scsi-core 2.6.32.27-1 kmod-sound-core 2.6.32.27-1 kmod-switch 2.6.32.27-4 kmod-textsearch 2.6.32.27-1 kmod-tun 2.6.32.27-1 kmod-usb-audio 2.6.32.27-1 kmod-usb-core 2.6.32.27-1 kmod-usb-ohci 2.6.32.27-1 kmod-usb-printer 2.6.32.27-1 kmod-usb-storage 2.6.32.27-1 kmod-usb-uhci 2.6.32.27-1 kmod-usb2 2.6.32.27-1 kmod-video-core 2.6.32.27-1 kmod-video-uvc 2.6.32.27-1 kmod-zd1211rw 2.6.32.27+2011-12-01-1 lame-lib 398-2-3 libao 1.1.0-1 libc 0.9.30.1-43.32 libevent 1.4.14b-1 libfaad2 2.7-1 libffmpeg 0.5.4-2 libfuse 2.8.3-1 libgcc 4.3.3+cs-43.32 libgsm 1.0.13-1 libiconv 5 libiconv-full 1.11.1-1 libid3tag 0.15.1b-3 libip4tc 1.4.6-3.1 libiwinfo 18 libiwinfo-lua 18 libjpeg 6b-1 libltdl 2.4-1 liblua 5.1.4-7 liblzo 2.04-1 libmad 0.15.1b-3 libncurses 5.7-2 libnl-tiny 0.1-1 libogg 1.1.4-2 libopenssl 0.9.8s-1 libpthread 0.9.30.1-43.32 librrd1 1.0.50-1 librt 0.9.30.1-43.32 libsamplerate 0.1.7-1 libsndfile 1.0.21-1 libuci 12012009.7-4 libuci-lua 12012009.7-4 libusb-1.0 1.0.8-1 libv4l 0.6.1-1 libvorbis 1.2.3-1 libvorbisidec 1.0.2+svn14261-1 libxtables 1.4.6-3.1 lua 5.1.4-7 luci 0.10.0-1 luci-app-firewall 0.10.0-1 luci-app-hd-idle 0.10.0-1 luci-app-ntpc 0.10.0-1 luci-app-qos 0.10.0-1 luci-app-samba 0.10.0-1 luci-app-voice-core 0.10.0-1 luci-i18n-chinese 0.10.0-1 luci-i18n-english 0.10.0-1 luci-lib-core 0.10.0-1 luci-lib-ipkg 0.10.0-1 luci-lib-lmo 0.10.0-1 luci-lib-lucid 0.10.0-1 luci-lib-lucid-http 0.10.0-1 luci-lib-nixio 0.10.0-1 luci-lib-px5g 0.10.0-1 luci-lib-sys 0.10.0-1 luci-lib-web 0.10.0-1 luci-mod-admin-core 0.10.0-1 luci-mod-admin-full 0.10.0-1 luci-proto-core 0.10.0-1 luci-proto-ppp 0.10.0-1 luci-sgi-cgi 0.10.0-1 luci-theme-base 0.10.0-1 luci-theme-openwrt 0.10.0-1 mjpg-streamer r136-1 motion 3.2.11.1-1 mtd 13 mutt 1.5.21-1 n2n 3875-1 ntfs-3g 2011.4.12-1-fuseext ntpclient 2007_365-4 openssl-util 0.9.8s-1 opkg 576-2 qos-scripts 1.2.1-3.2 resolveip 1 samba3 3.0.24-8 screen 4.0.3-2 sox 14.0.1-3 ssmtp 2.64-3 tc 2.6.29-1-2 uci 12012009.7-4 udevtrigger 106-1 uhttpd 28 usbutils 003-1 wireless-tools 29-4 wpad-mini 20111103-2 zlib 1.2.3-5

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值