Reputation: 49363
Not sure if anyone has any ideas here, I haven't seen this before. I'm writing a stub to test out my kernel module, when I check the value of the command in userspace I get a different value vs. when I take a look at the in kernel space.
Part of the stub:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "ain.h"
#include "ain_ioctl.h"
#define AI_DEVICE "/dev/ain"
void main()
{
int fd, error, ioctl_par = 0;
char* dev;
long ret;
dev = AI_DEVICE;
printf("Starting driver test\n");
fd = open(dev, O_RDWR);
if (fd < 0) {
/* Failed to open -> Print error-message and exit */
printf("%s failed to open, error: %s\n", dev, strerror(errno));
}
printf("Doing the IOCTL now... cmd: %d\n", AIN_IOC_GET_AN0_CONF);
fflush(stdout);
ret = ioctl(fd, AIN_IOC_GET_AN0_CONF, &ioctl_par);
The ain_ioctl.h file:
#define AIN_IOC_MAGIC 'e'
#define AIN_IOC_GET_AN0_CONF _IOR(AIN_IOC_MAGIC, 46, int)
The ioctl routine in the kernel:
int ain_ioctl (struct inode * inodep, struct file * filp, unsigned int cmd, unsigned long arg)
{
printk("In the ain_ioctl function, cmd: %d. type: %d, dir: %d, nr: %d, size: %d\n",
cmd, _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
printk("Testing against command: %d. type: %d, dir: %d, nr: %d, size: %d\n",
AIN_IOC_GET_AN0_CONF, _IOC_TYPE(AIN_IOC_GET_AN0_CONF), _IOC_DIR(AIN_IOC_GET_AN0_CONF),
_IOC_NR(AIN_IOC_GET_AN0_CONF), _IOC_SIZE(AIN_IOC_GET_AN0_CONF));
Now I would have expected identical output in the user space print as in the kernel. And in the first set of prints in the kernel to the second. However that's not what I'm seeing...
Output:
mike@linux-4puc:~> ./a.out
Starting driver test
Doing the IOCTL now... cmd: -2147195602
mike@linux-4puc:~> dmesg | tail
[75253.205136] In the ain_ioctl function, cmd: -1078168112. type: 117, dir: 2, nr: 208, size: 16316
[75253.205140] Testing against cmd: -2147195602. type: 101, dir: 2, nr: 46, size: 4
Anyone have any ideas on why my command is acting differently when I pass it to the kernel via the ioctl command vs when I just check the values by hard coding them (as I am doing in my prints)?
The only warnings I'm seeing when I build seem nothing to do with the ioctl calls:
makedepend: warning: ignoring option -Wall
makedepend: warning: ignoring option -Wall
makedepend: warning: ain.c (reading /usr/src/linux/include/linux/compiler-gcc.h), line 94: incomplete include == "#include gcc_header(__GNUC__)"
makedepend: warning: ain.c (reading /usr/src/linux/include/linux/string.h, line 13): cannot find include file "stdarg.h"
Thanks.
Upvotes: 1
Views: 3873
Reputation: 49363
Alan Curry's answer was not the complete "correct" answer, but it lead me to the solution. The hex value of the command was way off so I took a look at other ioctl calls in the kernel.
The system I have is based off an older 2.4X kernel, and I'm updating it for 3.1. The issue here is the parameter list for the ioctl call. Having the inode pointer in the parameter list was causing the problem as it was taking the file pointer to be the command.
Proper solution:
long ain_ioctl (struct file * filp, unsigned int cmd, unsigned long arg) {
...
Upvotes: 1
Reputation: 14711
The -1078168112 (why aren't you printing these in hex?) looks like a stack pointer. Possibly &ioctl_par
. This suggests that your ioctl method is receiving different parameters than you expected.
In the current kernel source I see ioctl methods taking 3 parameters, not 4. The 4-argument ioctl seems to be an older interface.
Do you get any warnings during the module compilation? Pay attention to them!
Upvotes: 4