Concise version at the end.
Intro:
I am making a char driver (type of scull. emulates the driver by allocating a memory area in the kernel and treating it as a device). From : https://www.youtube.com/playlist?list=PL16941B715F5507C5 -videos no. 7 and 8 from this.
The code for driver till now is working fine.
Current Code:
struct fake_device
{
char data[100];
struct semaphore sem;
} virtual_device;
As I said, above code creates a fake char device named virtual_device.
ssize_t device_write(struct file* filp, const char* bufSourceData,size_t bufCount, loff_t* curOffset)
{
printk(KERN_INFO "soliduscode: writing to device");
printk (KERN_INFO "%s",bufSourceData);
ret = copy_from_user(virtual_device.data, bufSourceData, bufCount);
return ret;
}
I use the above function to write to the fake device
Question:
As you see, device_write() reads the data from the node it's attached to (file: /dev/solidusmodule in my case) and writes exactly the same data to the device.
Now I am supposed to reverse (make palindrome) of this string and this conversion should be performed in the module code (this code) and not the user application.
Solutions I've tried:
The problem is device_write() has syntax
ssize_t write(struct file *filp, const char __user *buff, size_t count, loff_t *offp);
It takes a constant character user space pointer. Changing the syntax isn't permitted. I can't change the values pointed by bufSourceData. So I tried
ssize_t device_write(struct file* filp, const char* bufSourceData,size_t bufCount, loff_t* curOffset)
{
char temptry2[100]; //user app has the same size for writing to /dev/solidusdevice
int i, len, ascii_null = 0;
len = strlen(bufSourceData);
for(i=0;i<len;i++)
{
temptry2[i] = bufSourceData[len-i-1];
}
temptry2[i] = ascii_null;
for(i=len + 1; i<100;i++)
{
temptry2[i] = '0';
}
const char* palindrome_pointer = temptry2;
ret = copy_from_user(virtual_device.data, palindrome_pointer, bufCount);
return ret;
}
But this doesn't write the string to virtual_device.data. value of ret isn't 0. copy_from_user() fails.
From Linux Device Drivers by Jonathan Corbett, I found that copy_from_user(void *to, const void __user *mypointer, unsigned long count) only works for user space pointers in the source. So I tried
const char __user *palindrome_pointer = temptry2; //tried to make it a user space pointer so that I can pass it to copy_from_user( ,const void __user *mypointer, )
even tried (don't laugh):
const void __user *palindrome_pointer = temptry2; //changed from char to void
Still doesn't work.
TL;DR (Concise Question): How to I create a constant character type user space pointer (const char __user *my_pointer) to hold a string so that I can pass it as a source to copy_from_user(destination,source,size) ?
Please tell me if you know the solution. Is it even possible to do such operations in the module code or should I keep it in the user application itself?
Thanks
EDIT: If you find any link on this site or other that answers my question partially or fully, please do tell. I am just a beginner in device driver programming.