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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
// *******************************************************************
#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的介绍以及一些使用方法。

你可能感兴趣的:(openwrt)