草庐IT

c - 如何在 Linux 中使用新内核编译模块

coder 2023-06-20 原文

切换到 Ubuntu 13.10 后,我需要为新内核编译设备驱动程序。调用 make 会导致 2 个错误:

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。与此 module compilation guide 相比,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

Makefile 包含:

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---------------------------------

最佳答案

kzalloc/kfree/等。在 <linux/slab.h> 中声明,因此您应该包含该头文件。

也许它是通过您在旧版本中包含的其他头文件间接包含的,所以它恰好可以与旧内核一起使用。

关于c - 如何在 Linux 中使用新内核编译模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22452090/

有关c - 如何在 Linux 中使用新内核编译模块的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  7. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  8. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  9. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  10. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

随机推荐