JOKKEU TINKERINO
JOKKEU TINKERINO

Reputation: 49

No such device or address. Char device driver

I started studying char device drivers and encountered such a problem that with any attempt to interact with char device via read, write, ioctl, it writes "No such device or address". The device is created with the specified parameters, and a class of devices is also created.

logs from dmesg

[24102.683168] DBG: param in (struct data)
[24102.683169] DBG: struct transfer_string->buffer: 00000000dd1a65b0 && buffer: hello from kernel space!
[24102.683170] DBG: struct device_class: 18446614143144514304
[24102.683171] DBG: struct device_device: 0
[24102.683172] DBG: buffer_pos: 0
[24102.683172] DBG: struct data_dev: 18446614151544970752
[24102.683173] DBG: data_dev->dev: 527433729 | 503 : 1
[24102.683174] DBG: data_dev->major: 503
[24102.683175] DBG: data_dev->minor: 1
[24102.683176] DBG: data_dev->count: 0
[24102.683177] DBG: data_dev->module_name: my_ioc_device

[24102.683177] DBG: data->fops.open: 18446744072663138320
[24102.683178] DBG: data->fops.release: 18446744072663138384
[24102.683179] DBG: data->fops.read: 18446744072663140048
[24102.683180] DBG: data->fops.write: 18446744072663138432
[24102.683180] DBG: data->fops.unlocked_ioctl: 18446744072663138704
[24102.683181] DBG: ===================================================
[24102.683395] DBG: add char device
[24102.683395] INFO: ================== module installed 503:1 ==================

structure that logs

void logging_all_param(void)
{
    DBG("===================================================\n");
    DBG("param in (struct data)\n");
    DBG("struct transfer_string->buffer: %p && buffer: %s\n", data->transfer_string->buffer, data->transfer_string->buffer);
    DBG("struct device_class: %lu\n", (data->device_class != NULL) ? (uintptr_t)data->device_class : 0);
    DBG("struct device_device: %lu\n", (data->device_device != NULL) ? (uintptr_t)data->device_device : 0);
    DBG("buffer_pos: %lld\n", data->buffer_pos);
    DBG("struct data_dev: %lu\n", (data->data_dev != NULL) ? (uintptr_t)data->data_dev : 0);
    DBG("data_dev->dev: %d | %d : %d", data->data_dev->dev, MAJOR(data->data_dev->dev), MINOR(data->data_dev->dev));
    DBG("data_dev->major: %d\n", MAJOR(data->data_dev->major));
    DBG("data_dev->minor: %d\n", MINOR(data->data_dev->minor));
    DBG("data_dev->count: %d\n", data->data_dev->count);
    DBG("data_dev->module_name: %s\n\n", data->data_dev->module_name);
    DBG("data->fops.open: %lu\n", (data->fops.open != NULL) ? (uintptr_t)data->fops.open : 0);
    DBG("data->fops.release: %lu\n", (data->fops.release != NULL) ? (uintptr_t)data->fops.release : 0);
    DBG("data->fops.read: %lu\n", (data->fops.read != NULL) ? (uintptr_t)data->fops.read : 0);
    DBG("data->fops.write: %lu\n", (data->fops.write != NULL) ? (uintptr_t)data->fops.write : 0);
    DBG("data->fops.unlocked_ioctl: %lu\n", (data->fops.unlocked_ioctl != NULL) ? (uintptr_t)data->fops.unlocked_ioctl : 0);
    DBG("===================================================\n");
}

example of error:

jokkeu@jokkeu-host:/dev$ ls -la my_ioc_device 
crw-------. 1 root root 503, 1 Mar  3 02:49 my_ioc_device
jokkeu@jokkeu-host:/dev$ sudo cat my_ioc_device 
[sudo] password for jokkeu: 
cat: my_ioc_device: No such device or address

also:

jokkeu@jokkeu-host:/sys/class/ioc_dev/my_ioc_device$ cd ..
jokkeu@jokkeu-host:/sys/class/ioc_dev$ ls -la
total 0
drwxr-xr-x.  2 root root 0 Mar  3 03:08 .
drwxr-xr-x. 76 root root 0 Mar  3 02:49 ..
lrwxrwxrwx.  1 root root 0 Mar  3 03:08 my_ioc_device -> ../../devices/virtual/ioc_dev/my_ioc_device
jokkeu@jokkeu-host:/sys/class/ioc_dev$ cd my_ioc_device/
jokkeu@jokkeu-host:/sys/class/ioc_dev/my_ioc_device$ ls
dev  power  subsystem  uevent
jokkeu@jokkeu-host:/sys/class/ioc_dev/my_ioc_device$ cat dev
503:1

data sturct

struct _DEV
{
    int32_t major;
    int32_t minor;
    int32_t count;
    struct cdev hcdev;  
    dev_t dev;
    char class_name[50];
    char module_name[50];
};

struct _DATA
{
    struct _TRANSFER_STRING* transfer_string;
    struct class* device_class;
    struct device* device_device;
    loff_t buffer_pos;
    struct _DEV* data_dev;
    struct file_operations fops;
};

struct file_operations function:

ssize_t dev_read(struct file* file, char __user* buffer, size_t count, loff_t* ppos)
{
    DBG("start dev_read\n");
    LOGGING_ALL;
    size_t ret_bytes = 0;
    int ret;
    
    if (!data || !data->transfer_string) { ERR("Data or transfer_string is NULL\n"); ret = -EFAULT; goto out;}
    if (*ppos >= data->buffer_pos) {  DBG("No more data to read\n"); return EOK; }

    size_t bytes_to_read = min(count, data->buffer_pos - *ppos);
    
    LOGGING_ALL;
    DBG("bytes_to_read: %lu\n", bytes_to_read);
    DBG("ppos: %lu\n", *ppos);
        
    if (copy_to_user(buffer, data->transfer_string->buffer + *ppos, bytes_to_read)) 
    {
        ret = -EFAULT;
        goto out;
    }

    ret_bytes += bytes_to_read;
    *ppos += bytes_to_read; 

    DBG("=== read bytes: %ld\n=== buffer_pos: %llu\n=== ppos: %llu\n",
        ret_bytes,
        data->buffer_pos,
        *ppos);



    return ret_bytes; 

out:
    ERR("in dev_read: err = %d\n", ret);
    return ret;
}

ssize_t dev_write(struct file* file, const char __user* buffer, size_t count, loff_t* ppos)
{
    DBG("=== device write === \n");
    if (!data || !data->transfer_string) { ERR("Data or transfer_string is NULL\n"); return -EFAULT; }
    if (*ppos > BUFFER_SIZE - 1) {*ppos = BUFFER_SIZE - 1;} 
    if (copy_from_user(data->transfer_string->buffer, buffer, count)) {ERR("Failed to copy data from user\n"); return -EFAULT;}
    data->transfer_string->buffer[count] = '\0';
    data->buffer_pos = count;
    DBG("=== device write end === \n");
    return count;
}


int dev_open(struct inode* inode, struct file* file)
{
    if (device_open)
    {
        return -EBUSY;
    }
    
    device_open++;
    return EOK;
}

int dev_release(struct inode*, struct file* file)
{
    device_open--;
    return EOK;
}

Please tell me how to deal with this error. Thanks

Upvotes: 1

Views: 57

Answers (0)

Related Questions