&引用;设备的ioctl不合适“;在linux内核3.12中调用网络设备驱动程序时
我正在尝试向Linux内核3.12中的CAN驱动程序添加一个ioctl接口,这是一个网络设备 我以这种方式向驱动程序添加了ioctl处理&引用;设备的ioctl不合适“;在linux内核3.12中调用网络设备驱动程序时,linux,linux-kernel,ioctl,Linux,Linux Kernel,Ioctl,我正在尝试向Linux内核3.12中的CAN驱动程序添加一个ioctl接口,这是一个网络设备 我以这种方式向驱动程序添加了ioctl处理 #define C_CAN_SET_FILTERS _IOW('z', 3, void *) static int c_can_ioctl(struct net_device *dev, struct ifreq *ifr, int arg) { switch (arg) { case C_CAN_SET_FILT
#define C_CAN_SET_FILTERS _IOW('z', 3, void *)
static int c_can_ioctl(struct net_device *dev, struct ifreq *ifr, int arg)
{
switch (arg)
{
case C_CAN_SET_FILTERS:
netdev_err(dev, "CAN: ioctl C_CAN_SET_FILTERS called with arg %d\n", arg);
break;
default:
netdev_err(dev, "CAN: ioctl called with invalid cmd\n");
}
return 0;
}
static const struct net_device_ops c_can_netdev_ops = {
.ndo_open = c_can_open,
.ndo_stop = c_can_close,
.ndo_start_xmit = c_can_start_xmit,
.ndo_do_ioctl = c_can_ioctl,
};
dev->netdev_ops = &c_can_netdev_ops;
我添加了调试,以确保在驱动程序加载时实际执行上述代码,并且该代码是正确的
然后在用户空间我有这个代码
#define C_CAN_SET_FILTERS _IOW('z', 3, void *)
if(ioctl(CANConfig[hndl].s, C_CAN_SET_FILTERS, &filterList) < 0) {
perror("C_CAN install filters failed");
}
#定义C#u可以#u设置#u过滤器#w('z',3,void*)
if(ioctl(CANConfig[hndl].s,C\u可以设置过滤器和过滤器列表)<0){
perror(“C_可安装过滤器失败”);
}
我已经验证了CANConfig[hndl].s是一个整数,其计算结果为进入CAN驱动程序的通道的打开文件描述符(即CAN0)。事实上,代码中其他地方的ioctl调用确实有效
if(ioctl(CANConfig[hndl].s, SIOCGIFINDEX, &ifr) < 0)
if(ioctl(CANConfig[hndl].s、SIOCGIFINDEX和ifr)<0)
响应总是ENOTTY,也称为“设备的ioctl不适当”
似乎定制ioctl没有真正注册,因此内核在调用驱动程序中的定制ioctl代码之前拒绝了userspace ioctl调用。用于网络设备(如SIOCGIFINDEX)的内置IOCTL工作正常
谁能告诉我我做错了什么
我可以看到两件看起来错误但显然不正确的事情:(1)c_can_ioctl()定义的第三个参数应该是无符号long,但却是int。对于非网络设备,网络设备ioctl接口似乎不符合ioctl接口。(2)在网络设备操作结构中有一个.ndo\u do\u ioctl插槽,但没有.ndo\u do\u unlocked\u ioctl。您的ndo\u do\u ioctl是从core/dev.c调用的,您可以在其中查找: 在以下条件下调用
ndo\u do\u ioctl
:
static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) {
/* Code Snipped */
switch(cmd) {
/* Code Snipped */
default:
if ((cmd >= SIOCDEVPRIVATE &&
cmd <= SIOCDEVPRIVATE + 15) ||
cmd == SIOCBONDENSLAVE ||
cmd == SIOCBONDRELEASE ||
cmd == SIOCBONDSETHWADDR ||
cmd == SIOCBONDSLAVEINFOQUERY ||
cmd == SIOCBONDINFOQUERY ||
cmd == SIOCBONDCHANGEACTIVE ||
cmd == SIOCGMIIPHY ||
cmd == SIOCGMIIREG ||
cmd == SIOCSMIIREG ||
cmd == SIOCBRADDIF ||
cmd == SIOCBRDELIF ||
cmd == SIOCSHWTSTAMP ||
cmd == SIOCWANDEV) {
err = -EOPNOTSUPP;
if (ops->ndo_do_ioctl) {
if (netif_device_present(dev))
err = ops->ndo_do_ioctl(dev, ifr, cmd);
else
err = -ENODEV;
}
} else
err = -EINVAL;
} /* [end of switch] */
return err;
}
static int dev_ifsioc(struct net*net,struct ifreq*ifr,unsigned int cmd){
/*代码截取*/
开关(cmd){
/*代码截取*/
违约:
如果((cmd>=SIOCDEVPRIVATE&&
cmd ndo_do_ioctl){
如果(网络设备存在(开发))
err=ops->ndo\u do\u ioctl(dev、ifr、cmd);
其他的
err=-ENODEV;
}
}否则
err=-EINVAL;
}/*[开关末端]*/
返回错误;
}
因此,要么执行一个指定的cmd,要么执行SIOCDEVPRIVATE和SIOCDEVPRIVATE+15之间的某个命令
希望这有帮助:^)您是否尝试过将C_CAN_SET_过滤器设置为等于SIOCDEVPRIVATE+1?