Question

I am trying to run a simple IOCTL example on Android. I am using kernel 2.6 and ICS. The module is properly registered/unregistered (insmod/rmmod). However, every time a try to execute ./user_app on the emulator, I always get

error: first ioctl: Not a typewriter 
error: second ioctl: Not a typewriter 
message: `�

This is clearly a ENOTTY. I debugged the application, and no fops procedure (device_ioctl, read_ioctl and write_ioctl) is being executed.

I would like to know if there is any restriction with the usage/implementation of IOCTL on Android. Thank you very much in advance.

--Raul

Here is the code:

module.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>

#define MY_MACIG 'G'
#define READ_IOCTL _IOR(MY_MACIG, 0, int)
#define WRITE_IOCTL _IOW(MY_MACIG, 1, int)


int main(){
    char buf[200];
    int fd = -1;
    if ((fd = open("/data/local/afile.txt", O_RDWR)) < 0) {
        perror("open");
        return -1;
    }
    if(ioctl(fd, WRITE_IOCTL, "hello world") < 0)
        perror("first ioctl");
    if(ioctl(fd, READ_IOCTL, buf) < 0)
        perror("second ioctl");

    printf("message: %s\n", buf);
    return 0;

}

user_app.c

#include <stdio.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#define MY_MACIG 'G'
#define READ_IOCTL _IOR(MY_MACIG, 0, int)
#define WRITE_IOCTL _IOW(MY_MACIG, 1, int)

static char msg[200];

static ssize_t device_read(struct file *filp, char __user *buffer, size_t length, loff_t *offset)
{
    ...
}


static ssize_t device_write(struct file *filp, const char __user *buff, size_t len, loff_t *off)
{
    ...
}
char buf[200];
int device_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) {
    int len = 200;
    switch(cmd) {
    case READ_IOCTL:    
        ...
        break;

    case WRITE_IOCTL:
        ...
        break;

    default:
        return -ENOTTY;
    }
    return len;

}
static struct file_operations fops = {
    .read = device_read, 
    .write = device_write,
    .unlocked_ioctl = device_ioctl,
};

static int __init example_module_init(void)
{
    printk("registering module");
    return 0;
}

static void __exit example_module_exit(void)
{
    printk("unregistering module");
}  

module_init(example_module_init);
module_exit(example_module_exit);
MODULE_LICENSE("GPL");
Was it helpful?

Solution

It this the whole code that you've posted? You don't register a char device when initializing a module, so this can't work.
Also, be carefull when assigning IOCTLS numbers. When using reserved IOCTL on a wrong file, you will get ENOTTY. Consult this to make sure you don't have conflicts.
Read more about char drivers here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top