我一直在尝试将驱动程序从2.6移植到4.n,而没有原始板制造商的支持(并且Linux经验非常有限)。
原始驱动程序使用init_timer()并传入指向timer_list结构的指针。该limer_list结构的“数据”元素设置为指向另一个内存结构的指针,而“功能”元素设置为回调。在回调函数中,“数据”元素用于访问其他内容。
当前的计时器初始化方法使用timer_setup(timer_list *,callback,(unsigned int)标志);并且更改了timer_list结构以消除“数据”字段。
我不确定将等效的“数据”元素告知回调函数的最佳/正确方法是什么。谁能提供一些指导?
这是旧驱动程序的摘要...
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;
回调函数如下启动:
void GetIntrTimerCallback(unsigned long devAddr)
{
myDevice *dev = (myDevice *) devAddr;
dev->blahBlah++; // etc.
因此,旧代码将指针传递给myDevice,以便在回调内部可以访问该结构。
但是使用新的timer方法时,只能使用一个4字节的int,但一个指针是8(或任何其他值)。
我想做的是这样
dev->getIntrTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
timer_setup(dev->getIntrTimer, GetIntrTimerCallback, dev);
但是当然会生成编译错误,因为dev是类型为myDevice的指针,该指针不适合int。
我想念一些愚蠢的东西,不是吗?
答案 0 :(得分:5)
从4.14 Linux内核开始存在带有三个参数的timer_setup()
(仅供参考,在稍早的版本中就有setup_timer()
)。如果您维护一些与最新内核相关的代码,则每次API更改时都必须以适当的方式进行更改。现在,您可以通过基于container_of()
的特殊功能from_timer()
访问数据。
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
回调函数:
#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" */
另请参阅: