歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> linuxfl2440開發板驅動開發之按鍵驅動

linuxfl2440開發板驅動開發之按鍵驅動

日期:2017/3/3 10:59:20   编辑:Linux技術

linuxfl2440開發板驅動開發之按鍵驅動[luxibao@centos ~]$ mkdir input_kbd

[luxibao@centos input_kbd]$ ls

event_button.c kbd_device.c kbd_driver.c kbd_driver.h Makefile

驅動相關頭文件kbd_driver.h:/********************************************************************************

* Copyright: (C) 2016 Guo Wenxue<[email protected]>

* All rights reserved.

*

* Filename: kbd_driver.h

* Description: This head file is for s3c keyboard driver

*

* Version: 1.0.0(07/26/2016)

* Author: Guo Wenxue <[email protected]>

* ChangeLog: 1, Release initial version on "07/26/2016 06:54:47 PM"

*

********************************************************************************/

#ifndef _KBD_DRIVER_H_

#define _KBD_DRIVER_H_

/* keyboard hardware informtation structure definition */

typedef struct s3c_kbd_info_s

{

int code; /* input device key code */

int nIRQ; /* keyboard IRQ number*/

unsigned int setting; /* keyboard IRQ Pin Setting*/

unsigned int gpio; /* keyboard GPIO port */

} s3c_kbd_info_t;

/* keyboard platform device private data structure */

typedef struct s3c_kbd_platform_data_s

{

s3c_kbd_info_t *keys;

int nkeys;

} s3c_kbd_platform_data_t;

#endif /* ----- #ifndef _KBD_DRIVER_H_ ----- */

platform_device相關驅動文件 kbd_device.c:/*********************************************************************************

* Copyright: (C) 2016 Guo Wenxue<[email protected]>

* All rights reserved.

*

* Filename: kbd_device.c

* Description: This file

*

* Version: 1.0.0(07/26/2016)

* Author: Guo Wenxue <[email protected]>

* ChangeLog: 1, Release initial version on "07/26/2016 05:01:25 PM"

*

********************************************************************************/

#include <linux/module.h>

#include <linux/init.h>

#include <linux/platform_device.h>

#include <linux/input.h>

#include <mach/hardware.h>

#include <asm/gpio.h>

#include <asm/irq.h>

#include <mach/regs-gpio.h>

#include "kbd_driver.h"

static s3c_kbd_info_t s3c_kbd_gpios[] = {

[0] = {

.code = KEY_1,

.nIRQ = IRQ_EINT0,

.gpio = S3C2410_GPF(0),

.setting = S3C2410_GPF0_EINT0,

},

[1] = {

.code = KEY_2,

.nIRQ = IRQ_EINT2,

.gpio = S3C2410_GPF(2),

.setting = S3C2410_GPF2_EINT2,

},

[2] = {

.code = KEY_3,

.nIRQ = IRQ_EINT3,

.gpio = S3C2410_GPF(3),

.setting = S3C2410_GPF3_EINT3,

},

[3] = {

.code = KEY_4,

.nIRQ = IRQ_EINT4,

.gpio = S3C2410_GPF(4),

.setting = S3C2410_GPF4_EINT4,

},

};

/* keyboard platform device private data */

static s3c_kbd_platform_data_t s3c_kbd_data = {

.keys = s3c_kbd_gpios,

.nkeys = ARRAY_SIZE(s3c_kbd_gpios),

};

static void platform_kbd_release(struct device * dev)

{

return;

}

static struct platform_device s3c_keyboard_device = {

.name = "s3c_kbd",

.id = 1,

.dev =

{

.platform_data = &s3c_kbd_data,

.release = platform_kbd_release,

},

};

static int __init s3c_keyboard_dev_init(void)

{

int rv;

rv = platform_device_register(&s3c_keyboard_device);

if(rv)

{

printk("S3C keyboard platform device register failure\n");

return rv;

}

printk("S3C keyboard platform device register ok\n");

return 0;

}

static void __exit s3c_keyboard_dev_exit(void)

{

printk("S3C keyboard device exit\n");

platform_device_unregister(&s3c_keyboard_device);

return ;

}

module_init(s3c_keyboard_dev_init);

module_exit(s3c_keyboard_dev_exit);

MODULE_DESCRIPTION("FL2440 board keyboard input driver platform_device");

MODULE_AUTHOR("Guo Wenxue<[email protected]>");

MODULE_LICENSE("GPL");

MODULE_ALIAS("platform:FL2440 keyboard device");

platform_driver相關驅動文件 kbd_driver.c:/*********************************************************************************

* Copyright: (C) 2016 Guo Wenxue<[email protected]>

* All rights reserved.

*

* Filename: kbd_driver.c

* Description: This file

*

* Version: 1.0.0(07/26/2016)

* Author: Guo Wenxue <[email protected]>

* ChangeLog: 1, Release initial version on "07/26/2016 05:01:25 PM"

*

********************************************************************************/

#include <linux/module.h>

#include <linux/init.h>

#include <linux/platform_device.h>

#include <linux/input.h>

#include <linux/irq.h>

#include <linux/interrupt.h>

#include <mach/hardware.h>

#include <asm/gpio.h>

#include <asm/irq.h>

#include <linux/slab.h>

#include <mach/regs-gpio.h>

#include "kbd_driver.h"

/* 1HZ=100*jiffies 1*jiffies=10ms => 1HZ=100*10ms = 1s */

#define CANCEL_DITHERING_DELAY (HZ/50) /* Remove button push down dithering timer delay 20ms */

typedef struct s3c_kbd_s

{

struct timer_list *timers; /* every key get a cancel dithering timer */

struct input_dev *input_dev;

s3c_kbd_platform_data_t *pdata;

} s3c_kbd_t; /*--- end of struct s3c_kbd_s ---*/

s3c_kbd_t *s3c_kbd = NULL;

static irqreturn_t s3c_kbd_intterupt(int irq, void *dev_id)

{

int i;

int found = 0;

struct platform_device *pdev = dev_id;

s3c_kbd_t *s3c_kbd = NULL;

s3c_kbd = platform_get_drvdata(pdev);

for(i=0; i<s3c_kbd->pdata->nkeys; i++)

{

if(irq == s3c_kbd->pdata->keys[i].nIRQ)

{

found = 1;

break;

}

}

if(!found) /* An ERROR interrupt */

return IRQ_NONE;

mod_timer(&s3c_kbd->timers[i], jiffies+CANCEL_DITHERING_DELAY);

return IRQ_HANDLED;

}

static void cancel_dithering_timer_handler(unsigned long data)

{

int which =(int)data;

unsigned int pinval;

pinval = s3c2410_gpio_getpin(s3c_kbd->pdata->keys[which].gpio);

if( pinval )

{

//printk("s3c_kbd key[%d] code[%d] released\n", which, s3c_kbd->pdata->keys[which].code);

input_event(s3c_kbd->input_dev, EV_KEY, s3c_kbd->pdata->keys[which].code, 0);

}

else

{

//printk("s3c_kbd key[%d] code[%d] pressed\n", which, s3c_kbd->pdata->keys[which].code);

input_event(s3c_kbd->input_dev, EV_KEY, s3c_kbd->pdata->keys[which].code, 1);

}

input_sync(s3c_kbd->input_dev);

}

static int s3c_kbd_probe(struct platform_device *pdev)

{

int i = 0;

int rv = -ENOMEM;

struct input_dev *input_dev = NULL;

s3c_kbd_platform_data_t *pdata = pdev->dev.platform_data;

/* malloc s3c_kbd struct */

s3c_kbd = kmalloc(sizeof(s3c_kbd_t), GFP_KERNEL);

if( !s3c_kbd )

{

printk("error: s3c_kbd_probe kmalloc() for s3c_kbd failure\n");

goto fail;

}

memset(s3c_kbd, 0, sizeof(s3c_kbd_t));

/* malloc cancel dithering timer for every key */

s3c_kbd->timers = (struct timer_list *) kmalloc(pdata->nkeys*sizeof(struct timer_list), GFP_KERNEL);

if( !s3c_kbd->timers )

{

printk("error: s3c_kbd_probe kmalloc() for s3c_kbd timers failure\n");

goto fail;

}

memset(s3c_kbd->timers, 0, pdata->nkeys*sizeof(struct timer_list));

/* malloc input_dev for keyboard */

input_dev=input_allocate_device();

if( !input_dev )

{

printk("error: s3c_kbd_probe input_allocate_device() failure\n");

goto fail;

}

/* setup input_dev */

input_dev->name = pdev->name;

input_dev->dev.parent = &pdev->dev;

input_dev->id.bustype = BUS_HOST;

input_dev->id.vendor = 0x0001;

input_dev->id.product = 0x0001;

input_dev->id.version = 0x0100;

set_bit(EV_KEY,input_dev->evbit);

set_bit(EV_REP,input_dev->evbit);

/* Initialize all the keys and interrupt */

for(i=0; i<pdata->nkeys; i++)

{

set_bit(pdata->keys[i].code, input_dev->keybit);

s3c2410_gpio_cfgpin(pdata->keys[i].gpio, pdata->keys[i].setting);

irq_set_irq_type(pdata->keys[i].nIRQ, IRQ_TYPE_EDGE_BOTH);

rv = request_irq(pdata->keys[i].nIRQ, s3c_kbd_intterupt, IRQF_DISABLED, pdev->name, pdev);

if( rv )

{

printk("error: request IRQ[%d] for key<%d> failure\n", pdata->keys[i].nIRQ, i);

rv = -EBUSY;

goto fail;

}

//printk("s3c_kbd request IRQ[%d] for key<%d> ok\n", pdata->keys[i].nIRQ, i);

/* Initialize all the keys cancel dithering timer */

setup_timer(&s3c_kbd->timers[i], cancel_dithering_timer_handler, i);

}

/* register input device */

rv = input_register_device(input_dev);

if( rv )

{

printk("error: s3c_kbd_probe input_register_device error!\n");

goto fail;

}

/* set s3c_kbd as private data in pdev */

s3c_kbd->input_dev = input_dev;

s3c_kbd->pdata = pdata;

platform_set_drvdata(pdev, s3c_kbd);

printk("s3c_kbd_probe ok\n");

return 0;

fail:

while(i--)

{

disable_irq(pdata->keys[i].nIRQ);

free_irq(pdata->keys[i].nIRQ, pdev);

del_timer( &s3c_kbd->timers[i] );

}

if(input_dev)

{

input_free_device(input_dev);

}

if(s3c_kbd && s3c_kbd->timers)

{

kfree(s3c_kbd->timers);

}

if(s3c_kbd)

{

kfree(s3c_kbd);

}

printk("s3c_kbd_probe failed\n");

return -ENODEV;

}

static int s3c_kbd_remove(struct platform_device *pdev)

{

int i = 0;

s3c_kbd_t *s3c_kbd = platform_get_drvdata(pdev);

for(i=0; i<s3c_kbd->pdata->nkeys; i++)

{

del_timer( &s3c_kbd->timers[i] );

disable_irq(s3c_kbd->pdata->keys[i].nIRQ);

free_irq(s3c_kbd->pdata->keys[i].nIRQ, pdev);

}

input_unregister_device(s3c_kbd->input_dev);

kfree(s3c_kbd->timers);

kfree(s3c_kbd);

printk("s3c_kbd_remove ok\n");

return 0;

}

static struct platform_driver s3c_keyboard_driver = {

.probe = s3c_kbd_probe,

.remove = s3c_kbd_remove,

.driver = {

.name = "s3c_kbd",

.owner = THIS_MODULE,

},

};

static int __init s3c_keyboard_drv_init(void)

{

int rv;

rv = platform_driver_register(&s3c_keyboard_driver);

if(rv)

{

printk("s3c keyboard platform driver register failure\n");

return rv;

}

printk("s3c keyboard platform driver register ok\n");

return 0;

}

static void __exit s3c_keyboard_drv_exit(void)

{

printk("s3c keyboard driver exit\n");

platform_driver_unregister(&s3c_keyboard_driver);

return ;

}

module_init(s3c_keyboard_drv_init);

module_exit(s3c_keyboard_drv_exit);

MODULE_DESCRIPTION("FL2440 board keyboard input driver platform_driver");

MODULE_AUTHOR("Guo Wenxue<[email protected]>");

MODULE_LICENSE("GPL");

MODULE_ALIAS("platform:FL2440 keyboard driver");

驅動測試文件event_button.c:/*********************************************************************************

* Copyright: (C) 2012 Guo Wenxue<Email:[email protected] QQ:281143292>

* All rights reserved.

*

* Filename: event_button.c

* Description: This file used to test GPIO button driver builtin Linux kernel on ARM board

*

* Version: 1.0.0(07/13/2012~)

* Author: Guo Wenxue <[email protected]>

* ChangeLog: 1, Release initial version on "07/13/2012 02:46:18 PM"

*

********************************************************************************/

#include <stdio.h>

#include <unistd.h>

#include <errno.h>

#include <string.h>

#include <stdlib.h>

#include <unistd.h>

#include <fcntl.h>

#include <libgen.h>

#include <getopt.h>

#include <sys/types.h>

#include <sys/ioctl.h>

#include <linux/input.h>

#include <linux/kd.h>

#include <linux/keyboard.h>

#if 0 /* Just for comment here, Reference to linux-3.3/include/linux/input.h */

struct input_event

{

struct timeval time;

__u16 type; /* 0x00:EV_SYN 0x01:EV_KEY 0x04:EV_MSC 0x11:EV_LED*/

__u16 code; /* key value, which key */

__s32 value; /* 1: Pressed 0:Not pressed 2:Always Pressed */

};

#endif

#define TRUE 1

#define FALSE 0

#define EV_RELEASED 0

#define EV_PRESSED 1

#define EV_REPEAT 2

#define BUTTON_CNT 5

#define MODE_POLL 0x01

#define MODE_NORMAL 0x02

void usage(char *name);

void display_button_event(struct input_event *ev, int cnt);

int main(int argc, char **argv)

{

char *kbd_dev = NULL;

char kbd_name[256] = "Unknown";

int kbd_fd = -1;

int rv, opt;

int mode = MODE_NORMAL;

int size = sizeof (struct input_event);

struct input_event ev[BUTTON_CNT];

struct option long_options[] = {

{"device", required_argument, NULL, 'd'},

{"poll", no_argument, NULL, 'p'},

{"help", no_argument, NULL, 'h'},

{NULL, 0, NULL, 0}

};

while ((opt = getopt_long(argc, argv, "d:ph", long_options, NULL)) != -1)

{

switch (opt)

{

case 'd':

kbd_dev = optarg;

break;

case 'p':

mode = MODE_POLL;

break;

case 'h':

usage(argv[0]);

return 0;

default:

break;

}

}

if(NULL == kbd_dev)

{

usage(argv[0]);

return -1;

}

if ((getuid ()) != 0)

printf ("You are not root! This may not work...\n");

if ((kbd_fd = open(kbd_dev, O_RDONLY)) < 0)

{

printf("Open %s failure: %s", kbd_dev, strerror(errno));

return -1;

}

ioctl (kbd_fd, EVIOCGNAME (sizeof (kbd_name)), kbd_name);

printf ("Monitor input device %s (%s) event with %s mode:\n", kbd_dev, kbd_name, MODE_POLL==mode?"poll":"infilit loop");

#if 0 /* Not implement in the Linux GPIO button driver */

unsigned char key_b[BUTTON_CNT/8 + 1];

memset(key_b, 0, sizeof(key_b));

if(ioctl(kbd_fd, EVIOCGKEY(sizeof(key_b)), key_b) < 0)

{

printf("EVIOCGKEY ioctl get error: %s\n", strerror(errno));

return -1;

}

#endif

#if 0 /* Not implement in the Linux GPIO button driver */

/* rep[0]表示在按鍵重復出現之前 delay的時間,rep[1]表示按鍵重復出現的時間間隔。 */

int rep[2] ={2500, 1000} ;

if(ioctl(kbd_fd, EVIOCSREP, rep) < 0)

{

printf("EVIOCSREP ioctl get error: %s\n", strerror(errno));

return -1;

}

if(ioctl(kbd_fd, EVIOCGREP, rep) < 0)

{

printf("EVIOCGKEY ioctl get error: %s\n", strerror(errno));

return -1;

}

else

{

printf("repeate speed: [0]= %d, [1] = %d/n", rep[0], rep[1]);

}

#endif

while (1)

{

if(MODE_POLL==mode)

{

fd_set rds;

FD_ZERO(&rds);

FD_SET(kbd_fd, &rds);

rv = select(kbd_fd + 1, &rds, NULL, NULL, NULL);

if (rv < 0)

{

printf("Select() system call failure: %s\n", strerror(errno));

goto CleanUp;

}

else if (FD_ISSET(kbd_fd, &rds))

{

if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)

{

printf("Reading data from kbd_fd failure: %s\n", strerror(errno));

break;

}

else

{

display_button_event(ev, rv/size);

}

}

}

else

{

if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)

{

printf("Reading data from kbd_fd failure: %s\n", strerror(errno));

break;

}

else

{

display_button_event(ev, rv/size);

}

}

}

CleanUp:

close(kbd_fd);

return 0;

}

void usage(char *name)

{

char *progname = NULL;

char *ptr = NULL;

ptr = strdup(name);

progname = basename(ptr);

printf("Usage: %s [-p] -d <device>\n", progname);

printf(" -d[device ] button device name\n");

printf(" -p[poll ] Use poll mode, or default use infinit loop.\n");

printf(" -h[help ] Display this help information\n");

free(ptr);

return;

}

void display_button_event(struct input_event *ev, int cnt)

{

int i;

struct timeval pressed_time, duration_time;

for(i=0; i<cnt; i++)

{

//printf("type:%d code:%d value:%d\n", ev[i].type, ev[i].code, ev[i].value);

if(EV_KEY==ev[i].type && EV_PRESSED==ev[i].value)

{

if(BTN_1 == ev[i].code)

{

pressed_time = ev[i].time;

printf("S1 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);

}

else if(BTN_2 == ev[i].code)

{

pressed_time = ev[i].time;

printf("S2 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);

}

else if(BTN_3 == ev[i].code)

{

pressed_time = ev[i].time;

printf("S3 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);

}

else if(BTN_4 == ev[i].code)

{

pressed_time = ev[i].time;

printf("S4 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);

}

else

{

pressed_time = ev[i].time;

printf("button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);

}

}

if(EV_KEY==ev[i].type && EV_RELEASED==ev[i].value)

{

if(BTN_1 == ev[i].code)

{

timersub(&ev[i].time, &pressed_time, &duration_time);

printf("S1 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);

printf("S1 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);

}

else if(BTN_2 == ev[i].code)

{

timersub(&ev[i].time, &pressed_time, &duration_time);

printf("S2 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);

printf("S2 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);

}

else if(BTN_3 == ev[i].code)

{

timersub(&ev[i].time, &pressed_time, &duration_time);

printf("S3 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);

printf("S3 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);

}

else if(BTN_4 == ev[i].code)

{

timersub(&ev[i].time, &pressed_time, &duration_time);

printf("S4 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);

printf("S4 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);

}

else

{

timersub(&ev[i].time, &pressed_time, &duration_time);

printf("button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);

printf("button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);

}

}

} /* for(i=0; i<cnt; i++) */

}

驅動和測試程序編譯Makefile文件TEST_APP=event_button

KERNEL_VER = linux-3.0

LINUX_SRC ?= /home/luxibao/fl2440/kernel/$(KERNEL_VER)

CROSS_COMPILE=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-

PWD := $(shell pwd)

obj-m += kbd_device.o

obj-m += kbd_driver.o

modules:

@make -C $(LINUX_SRC) M=$(PWD) modules

@make clear

@chmod a+x *.ko && cp *.ko

@make testapp

clear:

@rm -f *.o *.cmd *.mod.c

@rm -rf *~ core .depend .tmp_versions Module.symvers modules.order -f

@rm -f .*ko.cmd .*.o.cmd .*.o.d

clean: clear

@rm -f *.ko ${TEST_APP}

testapp:

${CROSS_COMPILE}gcc ${TEST_APP}.c -o ${TEST_APP}

[luxibao@centos input_kbd]$ makemake[1]: Entering directory `/home/luxibao/fl2440/kernel/linux-3.0'

CC [M] /home/luxibao/input_kbd/kbd_device.o

CC [M] /home/luxibao/input_kbd/kbd_driver.o

Building modules, stage 2.

MODPOST 2 modules

CC /home/luxibao/input_kbd/kbd_device.mod.o

LD [M] /home/luxibao/input_kbd/kbd_device.ko

CC /home/luxibao/input_kbd/kbd_driver.mod.o

LD [M] /home/luxibao/input_kbd/kbd_driver.ko

make[1]: Leaving directory `/home/luxibao/fl2440/kernel/linux-3.0'

make[1]: Entering directory `/home/luxibao/input_kbd'

make[1]: Leaving directory `/home/luxibao/input_kbd'

make[1]: Entering directory `/home/luxibao/input_kbd'

/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc event_button.c -o event_button

make[1]: Leaving directory `/home/luxibao/input_kbd'

[luxibao@centos input_kbd]$ lsevent_button kbd_device.c kbd_driver.c kbd_driver.ko

event_button.c kbd_device.ko kbd_driver.h Makefile[luxibao@centos input_kbd]$ rm -rf event_button

[luxibao@centos input_kbd]$ lsevent_button.c kbd_device.ko kbd_driver.h Makefile

kbd_device.c kbd_driver.c kbd_driver.ko[luxibao@centos input_kbd]$ /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gccevent_button.c

[luxibao@centos input_kbd]$ lsa.out kbd_device.c kbd_driver.c kbd_driver.ko

event_button.c kbd_device.ko kbd_driver.h Makefile在開發板上的操作:

下載設備驅動:>: tftp -gr kbd_device.ko 192.168.1.2

kbd_device.ko 100% |*******************************| 3358 0:00:00 ETA

>: tftp -gr kbd_driver.ko 192.168.1.2

kbd_driver.ko 100% |*******************************| 3358 0:00:00 ETA

>: tftp -gr a.out 192.168.1.2

a.out 100% |*******************************| 12829 0:00:00 ETA

運行測試:>: insmod kbd_device.ko

S3C keyboard platform device register ok

>: insmod kbd_driver.ko

input: s3c_kbd as /devices/platform/s3c_kbd.1/input/input0

s3c_kbd_probe ok

s3c keyboard platform driver register ok

>: ./a.out

Usage: a.out [-p] -d <device>

-d[device ] button device name

-p[poll ] Use poll mode, or default use infinit loop.

-h[help ] Display this help information

>: ./a.out -p -d /dev/event0

Monitor input device /dev/event0 (s3c_kbd) event with poll mode:

button key[2] pressed time: 919.885106

button key[2] released time: 920.65095

button key[2] duration time: 1092937936.65087

button key[3] pressed time: 921.5096

button key[3] released time: 921.190084

button key[3] duration time: 1092937937.190076

button key[4] pressed time: 922.330099

button key[4] released time: 922.485089

button key[4] duration time: 1092937938.485081

遇到的問題問題1:

解決:刪除/tftp 用sz命令就行問題2:驅動加載不了第二個

解決:

交叉編譯器編譯event_button.c生成的event_button,刪除後進行後面操作

重新生成的.ko和a.out就可以正常加載和運行了

Copyright © Linux教程網 All Rights Reserved