C 如何在Linux下用新内核编译模块
切换到Ubuntu 13.10后,我需要为新内核编译一个设备驱动程序。调用C 如何在Linux下用新内核编译模块,c,linux,ubuntu,kernel,kernel-module,C,Linux,Ubuntu,Kernel,Kernel Module,切换到Ubuntu 13.10后,我需要为新内核编译一个设备驱动程序。调用make会导致两个错误: error: implicit declaration of function ‘kzalloc’ error: implicit declaration of function ‘kfree’ 同样的make命令在Ubuntu 13.04中运行良好,但现在失败了。我还检查了 KDIR := /lib/modules/$(shell uname -r)/build 在Makefile中使用,解
make
会导致两个错误:
error: implicit declaration of function ‘kzalloc’
error: implicit declaration of function ‘kfree’
同样的make
命令在Ubuntu 13.04中运行良好,但现在失败了。我还检查了
KDIR := /lib/modules/$(shell uname -r)/build
在Makefile中使用,解析后成为/lib/modules/3.11.0-18-generic/build
。与此相比,Makefile似乎相当标准
13点10分的时候我错过了什么?是否需要额外的套餐?已安装build essentials包。13.10的时候还有什么变化吗
make
的完整错误消息是:
user1@pc:/etc/opt/elo-mt-usb/elo_mt_input_mod_src$ sudo make
make -C /lib/modules/3.11.0-18-generic/build SUBDIRS=/etc/opt/elo-mt-usb/elo_mt_input_mod_src modules
make[1]: Betrete Verzeichnis '/usr/src/linux-headers-3.11.0-18-generic'
CC [M] /etc/opt/elo-mt-usb/elo_mt_input_mod_src/elo_mt_input.o
/etc/opt/elo-mt-usb/elo_mt_input_mod_src/elo_mt_input.c: In function ‘elo_input_write’:
/etc/opt/elo-mt-usb/elo_mt_input_mod_src/elo_mt_input.c:79:2: error: implicit declaration of function ‘kzalloc’ [-Werror=implicit-function-declaration]
if(!(buffer = kzalloc(count, GFP_KERNEL)))
^
/etc/opt/elo-mt-usb/elo_mt_input_mod_src/elo_mt_input.c:79:14: warning: assignment makes pointer from integer without a cast [enabled by default]
if(!(buffer = kzalloc(count, GFP_KERNEL)))
^
/etc/opt/elo-mt-usb/elo_mt_input_mod_src/elo_mt_input.c:148:3: error: implicit declaration of function ‘kfree’ [-Werror=implicit-function-declaration]
kfree(buffer);
^
cc1: some warnings being treated as errors
make[2]: *** [/etc/opt/elo-mt-usb/elo_mt_input_mod_src/elo_mt_input.o] Fehler 1
make[1]: *** [_module_/etc/opt/elo-mt-usb/elo_mt_input_mod_src] Fehler 2
make[1]: Verlasse Verzeichnis '/usr/src/linux-headers-3.11.0-18-generic'
make: *** [default] Fehler 2
生成文件包含:
obj-m := elo_mt_input_mod.o
elo_mt_input_mod-objs := elo_mt_input.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
install:
cp ./elo_mt_input_mod.ko ../elo_mt_input_mod_`uname -r`.ko
clean:
rm -f *.o *.cmd *.mod.c .*.o* .*.ko* *~ *.ko Module.markers modules.order Module.symvers
rm -rf .tmp_versions/
幸运的是,制造商在GPL下发布了驱动程序源代码。需要编译的elo_mt_input.c文件是:
// --------------------------------------------------------------
// Name: Linux input module for Elo MultiTouch(MT) devices
// License: GPL
// Author: Elo Touch Solutions Inc
// Version: 1.0.0
// Date: 26 August 2013
// --------------------------------------------------------------
//Header Files
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/version.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
#include <linux/input/mt.h>
#else
#include <linux/input.h>
#endif
//Driver Information
#define DRIVER_VERSION "1.0.0"
#define DRIVER_AUTHOR "Elo Touch Solutions Inc"
#define DRIVER_DESC "Linux input module for Elo MultiTouch(MT) devices"
#define DRIVER_LICENSE "GPL"
// Kernel Module Information
MODULE_VERSION(DRIVER_VERSION);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);
// Global Definitions
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
#define _MULTITOUCH_KERNEL_
#else
#undef _MULTITOUCH_KERNEL_
#endif
#ifdef _MULTITOUCH_KERNEL_
#define ELO_MT_MAXCONTACTS 2 // Maximum number of multi touch contacts
#endif
#define MIN_X (0) // Min X Axis resolution
#define MAX_X (4095) // Max X Axis resolution
#define MIN_Y (0) // Min Y Axis resolution
#define MAX_Y (4095) // Max Y Axis resolution
#define MIN_PRESSURE (0) // Min Pressure
#define MAX_PRESSURE (1) // Max Pressure
// Global Data Structures
struct touch_event {
u16 touch_count; // Total touch count in the entire frame
u16 touch_index; // Current Touch Index for this contact
u16 contact_id; // Contact ID for this contact
u16 touch_status; // Indicates if touch is active or not for this contact
u16 x; // ABS X value for this contact
u16 y; // ABS Y value for this contact
};
struct input_dev *elo_input_device = NULL;
struct proc_dir_entry *proc_entry = NULL;
// Functions
static ssize_t elo_input_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
return 0;
}
static ssize_t elo_input_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
int rc = -1;
const u8 *ptr = NULL;
u8 *buffer = NULL;
size_t size = count;
struct touch_event *event = NULL;
if(!(buffer = kzalloc(count, GFP_KERNEL)))
{
printk(KERN_ERR "elo_mt_input: Unable to allocate memory\n");
rc = -ENOMEM;
goto done;
}
if(copy_from_user(buffer, buf, count))
{
printk(KERN_ERR "elo_mt_input: Unable to copy data\n");
rc = -EFAULT;
goto done;
}
/* Process each touch event */
ptr = buffer;
while(size >= sizeof(*event))
{
event = (struct touch_event *)ptr;
// printk(KERN_INFO "elo_mt_input: mt event touch#:%d cid=%d x=%d y=%d status=%d\n", event->touch_index, event->contact_id, event->x, event->y, event->touch_status);
#ifdef _MULTITOUCH_KERNEL_
// Actions for sending Multitouch events
input_mt_slot(elo_input_device, event->contact_id); //Use contact_id for slot numbering [ max 2 slots ]
input_mt_report_slot_state(elo_input_device, MT_TOOL_FINGER, event->touch_status);
if(event->touch_status)
{// If touch is active
input_event(elo_input_device, EV_ABS, ABS_MT_POSITION_X, event->x);
input_event(elo_input_device, EV_ABS, ABS_MT_POSITION_Y, event->y);
input_event(elo_input_device, EV_ABS, ABS_MT_PRESSURE, event->touch_status);
}
// Send primary touch events to move the pointer
input_mt_report_pointer_emulation(elo_input_device, true);
// Check if this is the last touch event based on touch count and touch id, then send SYN_REPORT
if(event->touch_count == (event->touch_index + 1))
{
input_sync(elo_input_device);
}
#else
// Actions for sending Single Touch as Mouse events for primary touch only
if(event->touch_index == 0)
{
if(event->touch_status)
{// If touch is active
input_event(elo_input_device, EV_ABS, ABS_X, event->x);
input_event(elo_input_device, EV_ABS, ABS_Y, event->y);
input_event(elo_input_device, EV_KEY, BTN_LEFT, event->touch_status);
}
else
{
input_event(elo_input_device, EV_ABS, ABS_X, event->x);
input_event(elo_input_device, EV_ABS, ABS_Y, event->y);
input_event(elo_input_device, EV_KEY, BTN_LEFT, 0);
}
input_sync(elo_input_device);
}
#endif
ptr += sizeof(*event);
size -= sizeof(*event);
}
rc = count;
done:
if(buffer)
kfree(buffer);
*ppos += count;
return rc;
}
static const struct file_operations elo_input_fops = {
.read = elo_input_read,
.write = elo_input_write
};
static int __init elo_input_init(void)
{
int rc = 0;
if(!(elo_input_device = input_allocate_device()))
{
printk(KERN_ERR "elo_mt_input: Unable to create input_dev\n");
rc = -EBUSY;
goto done;
}
// Input device will report ABS events
set_bit(EV_ABS, elo_input_device->evbit);
#ifdef _MULTITOUCH_KERNEL_
// Setup for direct devices [touchscreens]
set_bit(INPUT_PROP_DIRECT, elo_input_device->propbit);
// Corresponding to HID TIPSWITCH field (Pointer emulation)
input_set_capability(elo_input_device, EV_KEY, BTN_TOUCH);
elo_input_device->name = "Elo MultiTouch(MT) Device Input Module";
#else
// Corresponding to HID TIPSWITCH field - Send LEFT Mouse button event
input_set_capability(elo_input_device, EV_KEY, BTN_LEFT);
elo_input_device->name = "Elo Single Touch Device Input Module";
#endif
// Set appropriate dimensions
input_set_abs_params(elo_input_device, ABS_X, MIN_X, MAX_X, 0, 0);
input_set_abs_params(elo_input_device, ABS_Y, MIN_Y, MAX_Y, 0, 0);
#ifdef _MULTITOUCH_KERNEL_
input_set_abs_params(elo_input_device, ABS_MT_POSITION_X, MIN_X, MAX_X, 0, 0);
input_set_abs_params(elo_input_device, ABS_MT_POSITION_Y, MIN_Y, MAX_Y, 0, 0);
input_set_abs_params(elo_input_device, ABS_MT_PRESSURE, MIN_PRESSURE, MAX_PRESSURE, 0, 0);
input_set_abs_params(elo_input_device, ABS_PRESSURE, MIN_PRESSURE, MAX_PRESSURE, 0, 0);
// Corresponding to HID contact ID
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
input_mt_init_slots(elo_input_device, ELO_MT_MAXCONTACTS, INPUT_MT_DIRECT); // Kernel 3.7 or later [Added 3rd parameter - flags]
#else
input_mt_init_slots(elo_input_device, ELO_MT_MAXCONTACTS);
#endif
#endif
if((rc = input_register_device(elo_input_device)))
{
printk(KERN_ERR "elo_mt_input: Unable to register input_dev\n");
goto done;
}
// Create the proc entry
proc_entry = proc_create("elo_mt_input", S_IWUSR | S_IRUSR, NULL, &elo_input_fops);
if(proc_entry == NULL)
{
printk(KERN_ERR "elo_mt_input: Failed to create /proc/elo_mt_input\n");
input_unregister_device(elo_input_device);
rc = -EBUSY;
goto done;
}
printk(KERN_INFO "elo_mt_input: Input device registered\n");
done:
return rc;
}
static void __exit elo_input_exit(void)
{
remove_proc_entry("elo_mt_input", NULL);
input_unregister_device(elo_input_device);
}
module_init(elo_input_init);
module_exit(elo_input_exit);
//---------------------------------EOF---------------------------------
//--------------------------------------------------------------
//名称:用于Elo多点触控(MT)设备的Linux输入模块
//许可证:GPL
//作者:埃洛触摸解决方案公司
//版本:1.0.0
//日期:2013年8月26日
// --------------------------------------------------------------
//头文件
#包括
#包括
#包括
#包括
#如果(LINUX版本代码>=内核版本(2,6,38))
#包括
#否则
#包括
#恩迪夫
//驾驶员信息
#定义驱动程序_版本“1.0.0”
#定义驱动程序作者“Elo Touch Solutions Inc”
#定义驱动程序描述“Elo多点触控(MT)设备的Linux输入模块”
#定义驾驶执照“GPL”
//内核模块信息
模块版本(驱动程序版本);
模块作者(驱动程序作者);
模块描述(驾驶员描述);
模块驾照(驾驶证);
//全球定义
#如果(LINUX版本代码>=内核版本(2,6,38))
#定义多点触摸内核_
#否则
#undef(多点触摸)内核_
#恩迪夫
#ifdef_多点触摸_内核_
#定义ELO_MT_MAXCONTACTS 2//多点触摸触点的最大数量
#恩迪夫
#定义最小X(0)//最小X轴分辨率
#定义MAX_X(4095)//最大X轴分辨率
#定义最小Y(0)//最小Y轴分辨率
#定义最大Y轴(4095)//最大Y轴分辨率
#定义最小压力(0)//最小压力
#定义最大压力(1)//最大压力
//全球数据结构
结构触摸事件{
u16 touch_count;//整个帧中的总触摸计数
u16 touch_index;//此联系人的当前触摸索引
u16联系人\u id;//此联系人的联系人id
u16 touch_status;//指示此触点的触摸是否处于活动状态
u16 x;//此触点的ABS x值
u16 y;//此触点的ABS y值
};
结构输入设备*elo输入设备=NULL;
struct proc_dir_entry*proc_entry=NULL;
//功能
静态ssize_t elo_输入_读取(结构文件*文件,字符*用户*buf,大小计数,loff_t*ppos)
{
返回0;
}
静态ssize_t elo_输入_写入(结构文件*文件、常量字符*用户*buf、大小计数、loff_t*ppos)
{
int rc=-1;
常量u8*ptr=NULL;
u8*缓冲区=NULL;
大小=计数;
struct touch_event*event=NULL;
如果(!(缓冲区=kzalloc(计数,GFP_内核)))
{
printk(KERN_ERR“elo_mt_输入:无法分配内存\n”);
rc=-ENOMEM;
去做;
}
if(从用户(缓冲区、buf、计数)复制)
{
printk(KERN_ERR“elo_mt_输入:无法复制数据\n”);
rc=-EFAULT;
去做;
}
/*处理每个触摸事件*/
ptr=缓冲区;
而(大小>=sizeof(*事件))
{
事件=(结构触摸事件*)ptr;
//printk(KERN_INFO“elo_mt_输入:mt事件触摸#):%d cid=%d x=%d y=%d status=%d\n”,事件->触摸索引,事件->联系人id,事件->x,事件->y,事件->触摸状态);
#ifdef_多点触摸_内核_
//发送多点触控事件的操作
input_mt_插槽(elo_input_设备,事件->联系人id);//使用联系人id进行插槽编号[最多2个插槽]
输入mt报告插槽状态(elo输入设备、mt工具手指、事件->触摸状态);
如果(事件->触摸屏状态)
{//如果触摸处于活动状态
输入事件(elo输入设备、电动汽车ABS、ABS机器位置X、事件->X);
输入事件(elo输入设备、EV ABS、ABS MT位置Y、事件->Y);
输入事件(elo输入设备、电动汽车ABS、ABS机器压力、事件->触摸状态);
}
//发送主触摸事件以移动指针
输入报告指针模拟(elo输入设备,真);
//根据触摸计数和触摸id检查这是否是最后一次触摸事件,然后发送SYN_报告
如果(事件->触摸计数==(事件->触摸索引+1))
{
输入同步(elo输入设备);
}
#否则
//仅将单触作为鼠标事件发送给主触的操作
如果(事件->触摸索引==0)
{
如果(事件->触摸屏状态)
{//如果触摸处于活动状态
输入事件(elo\U输入设备、EV\U ABS、ABS\U X、事件->X);
输入事件(elo\U输入设备、EV\U ABS、ABS\U Y、事件->Y);
输入事件(elo输入设备、EV键、BTN左、事件->触摸状态);
}
其他的
{
输入事件(elo\U输入设备、EV\U ABS、ABS\U X、事件->X);
输入事件(elo\U输入设备、EV\U ABS、ABS\U Y、事件->Y);
输入事件(elo输入设备,EV键,BTN左,0);
}
输入同步(elo输入设备);
}
#恩迪夫
ptr+=sizeof(*事件);
大小-=大小(*事件);
}
rc=计数;
完成:
if(缓冲区)
kfree(缓冲区);
*ppos+=计数;
返回rc;
}
静态常量结构文件\u操作elo\u输入\u fops={
.read=elo_输入_读取,
.write=elo\u输入\u写入
};
静态整数初始化elo输入初始化(无效)
{
int rc=0;
如果(!(elo\U input\U device=input\U allocate\U device())
{
printk(KERN_ERR“elo_mt_输入:无法创建输入\u dev\n”);
rc=-EBUSY;
去做;
}
//输入设备将报告ABS事件
设置位(EV\U ABS,elo\U输入设备->evbit);
#ifdef_多点触摸_内核_
//直接设备[触摸屏]的设置
设置字节(直接输入字节,elo字节输入字节设备->字节);
//对应HID TIPS开关字段(指针模拟)
输入设置功能(elo输入设备、EV键、BTN触摸);
埃洛尤因