El *_*ldo 2 c linux linux-device-driver linux-kernel
我一直试图在没有原始主板制造商支持的情况下将驱动程序从2.6移植到4.n(并且Linux经验非常有限).
原始驱动程序使用init_timer()并传入指向timer_list结构的指针.该limer_list结构的'data'元素被设置为指向另一个内存结构的指针,并且'function'元素被设置为回调.在回调函数内部,'data'元素用于访问其他东西.
当前的timer init方法使用timer_setup(timer_list*,callback,(unsigned int)flags); 并且timer_list结构已更改为消除'data'字段.
我不确定通知等效'data'元素的回调函数的最佳/正确方法是什么.谁能提供一些指导?
这是老司机的片段......
myDevice * dev;
dev->getIntrTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
init_timer(dev->getIntrTimer);
dev->getIntrTimer->data = (unsigned long) dev;
dev->getIntrTimer->function = GetIntrTimerCallback;
Run Code Online (Sandbox Code Playgroud)
回调函数如下所示:
void GetIntrTimerCallback(unsigned long devAddr)
{
myDevice *dev = (myDevice *) devAddr;
dev->blahBlah++; // etc.
Run Code Online (Sandbox Code Playgroud)
因此,旧代码将指针传递给myDevice,因此在回调中可以访问该结构.
但是使用新的计时器方法只有一个4字节的int,但指针是8(或其他).
我想做的是:
dev->getIntrTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
timer_setup(dev->getIntrTimer, GetIntrTimerCallback, dev);
Run Code Online (Sandbox Code Playgroud)
但是当然会产生编译错误,因为dev是一个指向myDevice类型的指针,它不适合int.
我想念傻事,不是吗?
该timer_setup()自4.14 Linux内核(FYI有一个与三个参数存在setup_timer()略微更早版本).如果您维护一些与最新内核相关的代码 - 每次API更改时都必须以适当的方式更改它.现在您可以通过from_timer()基于的特殊功能访问您的数据container_of().
timer_list 通常不用作struct中的指针,因此该示例意味着正常使用,可能类似于:
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0)
init_timer(&dev->getIntrTimer);
dev->getIntrTimer.data = (unsigned long) dev;
dev->getIntrTimer.function = GetIntrTimerCallback;
/* ... */
add_timer(&dev->getIntrTimer);
#else
timer_setup(&dev->getIntrTimer, GetIntrTimerCallback, 0);
/* the third argument may include TIMER_* flags */
/* ... */
#endif
Run Code Online (Sandbox Code Playgroud)
回调函数:
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0)
void GetIntrTimerCallback(unsigned long devAddr)
{
myDevice *dev = (myDevice *) devAddr;
#else
void GetIntrTimerCallback(struct timer_list *t)
{
myDevice *dev = from_timer(dev, t, getIntrTimer);
#endif
/* Do something with "dev" */
Run Code Online (Sandbox Code Playgroud)
阅读: