I am currently working on a device driver where I want to write a sentence to that driver and display it in the kernel. Reading an internal buffer and calling the driver with cat works perfectly fine. However, if I try to write to the device driver it returns the following message:
I have the following code for my device driver. I can’t seem to find where I went wrong in my write function…
#include "device_file.h" #include <linux/fs.h> /* file stuff */ #include <linux/kernel.h> /* printk() */ #include <linux/errno.h> /* error codes */ #include <linux/module.h> /* THIS_MODULE */ #include <linux/cdev.h> /* char device stuff */ #include <linux/uaccess.h> /* copy_to_user() */ static const char g_s_Hello_World_string[] = "Hello from Job & Arief!n"; static const ssize_t g_s_Hello_World_size = sizeof(g_s_Hello_World_string); static char memory_buffer[500]; /*===============================================================================================*/ static ssize_t device_file_read(struct file *file_ptr, char __user *user_buffer, size_t count, loff_t *possition){ printk( KERN_NOTICE "Kurniawan_Meulenbeld-driver: Device file is read at offset = %i, read bytes count = %un" , (int)*possition , (unsigned int)count ); if( *possition >= g_s_Hello_World_size ) return 0; if( *possition + count > g_s_Hello_World_size ) count = g_s_Hello_World_size - *possition; if( copy_to_user(user_buffer, g_s_Hello_World_string + *possition, count) != 0 ) return -EFAULT; *possition += count; return count; } /*===============================================================================================*/ static ssize_t memory_write( struct file *filp, const char *buf, size_t count, loff_t *f_pos) { const char *tmp; tmp=buf+count-1; if( copy_from_user(memory_buffer,tmp,1) != 0 ) return -EFAULT; return count; } /*===============================================================================================*/ static struct file_operations Kurniawan_Meulenbeld_driver_fops = { .owner = THIS_MODULE, .read = device_file_read, .write = memory_write, }; static int device_file_major_number = 0; static const char device_name[] = "Kurniawan_Meulenbeld-driver"; /*===============================================================================================*/ int register_device(void) { int result = 0; printk( KERN_NOTICE "Kurniawan_Meulenbeld-driver: register_device() is called.n" ); result = register_chrdev( 0, device_name, &Kurniawan_Meulenbeld_driver_fops ); if( result < 0 ) { printk( KERN_WARNING "Kurniawan_Meulenbeld-driver: can't register character device with errorcode = %in", result ); return result; } device_file_major_number = result; printk( KERN_NOTICE "Kurniawan_Meulenbeld-driver: registered character device with major number = %i and minor numbers 0...255n" , device_file_major_number ); return 0; } /*===============================================================================================*/ void unregister_device(void) { printk( KERN_NOTICE "Kurniawan_Meulenbeld-driver: unregister_device() is calledn" ); if(device_file_major_number != 0) { unregister_chrdev(device_file_major_number, device_name); } }
Advertisement
Answer
Note that redirection >/dev/my-driver
is done by the shell under the current user before sudo
is invoked. EINVAL
from write
means fd is attached to an object which is unsuitable for writing.
It is not clear whether hello
is a file or a string. cat
expects it to be a file.
To write string hello
into your device try:
echo "hello" | sudo tee /dev/my-driver
To write file hello
into your device try:
cat hello | sudo tee /dev/my-driver # or sudo tee /dev/my-driver <hello