C 如何在Linux下用新内核编译模块

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中使用,解

切换到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中使用,解析后成为
/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触摸);
埃洛尤因