分享

Openwrt定制按键输入

 云将东游 2016-01-26

在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
  • 1
  • 2

示例:

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,
     },
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153

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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多