1
0
mirror of https://github.com/richardghirst/PiBits.git synced 2025-02-26 19:54:16 +01:00

Change dev_read to use per-process data.

This commit is contained in:
Robin Mallinson 2012-11-18 21:12:36 +00:00
parent 38101f8a62
commit e993a088eb

View File

@ -316,31 +316,32 @@ void cleanup_module(void)
unregister_chrdev_region(devno, 1); unregister_chrdev_region(devno, 1);
} }
// This stores the /dev/servoblaster content for a given user process. // This struct is used to store all temporary data required per process
struct userReturnedData { // which reads/writes the device file.
int idx; struct process_data
char returnedData[NUM_SERVOS * 10]; {
}; // Stores the /dev/servoblaster content for a given user process.
// Allowing 10 chars per line.
int ret_idx;
char ret_data[NUM_SERVOS * 10];
// This stores one user command (single line) for a given user process. // Stores one user command (single line) for a given user process.
// e.g. "3=180" // e.g. "3=180"
// Line length is expected to be <32 // Line length is expected to be <32
struct userCommandData { int cmd_idx;
int idx; char cmd_data[32];
char commandData[32];
}; };
// kmalloc the temporary data required for each user: // kmalloc the temporary data required for each user:
// *returnedData string for dev_read
// *useCommand buffer for dev_write to allow incremental writing of data.
static int dev_open(struct inode *inod,struct file *fil) static int dev_open(struct inode *inod,struct file *fil)
{ {
fil->private_data = kmalloc( 32, GFP_KERNEL ); fil->private_data = kmalloc( sizeof(struct process_data), GFP_KERNEL );
if (0 == fil->private_data) if (0 == fil->private_data)
{ {
printk(KERN_WARNING "ServoBlaster: Failed to allocate user data\n"); printk(KERN_WARNING "ServoBlaster: Failed to allocate user data\n");
return -ENOMEM; return -ENOMEM;
} }
memset(fil->private_data, 0, sizeof(struct process_data));
return 0; return 0;
} }
@ -351,47 +352,52 @@ static int written_data[NUM_SERVOS] = { 0 };
static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) static ssize_t dev_read(struct file *filp,char *buf,size_t count,loff_t *f_pos)
{ {
ssize_t bytesPrinted = 0; ssize_t bytesPrinted = 0;
int servo; struct process_data* const pdata = filp->private_data;
static int idx=0;
// Allow 10 chars per line:
static char returnedData[NUM_SERVOS * 10] = {0};
if (0 == *f_pos) // Only proceed if we have private data, else return EOF.
if (0 != pdata)
{ {
// Get fresh data int servo;
for (servo=0, idx=0; servo < NUM_SERVOS; ++servo) int* const idx = &(pdata->ret_idx);
char* const returnedData = pdata->ret_data;
if (0 == *f_pos)
{ {
idx += snprintf(returnedData+idx, sizeof(returnedData)-idx, // Get fresh data
"%i %i\n", for (servo=0, *idx=0; servo < NUM_SERVOS; ++servo)
servo, {
written_data[servo] *idx += snprintf(returnedData+*idx, sizeof(pdata->ret_data)-*idx,
); "%i %i\n",
servo,
written_data[servo]
);
}
} }
}
if (*f_pos >= idx) if (*f_pos >= *idx)
{ {
//EOF //EOF
bytesPrinted=0; bytesPrinted=0;
} }
else if ( (*f_pos + count) < idx ) else if ( (*f_pos + count) < *idx )
{ {
// Sufficient data to fulfil request // Sufficient data to fulfil request
if (copy_to_user(buf,returnedData+*f_pos,count)) { if (copy_to_user(buf,returnedData+*f_pos,count)) {
return -EFAULT; return -EFAULT;
}
*f_pos+=count;
bytesPrinted=count;
}
else
{
// Return all the data we have
const int nBytes = *idx-*f_pos;
if (copy_to_user(buf,returnedData+*f_pos, nBytes)) {
return -EFAULT;
}
*f_pos+=nBytes;
bytesPrinted=nBytes;
} }
*f_pos+=count;
bytesPrinted=count;
}
else
{
// Return all the data we have
const int nBytes = idx-*f_pos;
if (copy_to_user(buf,returnedData+*f_pos, nBytes)) {
return -EFAULT;
}
*f_pos+=nBytes;
bytesPrinted=nBytes;
} }
return bytesPrinted; return bytesPrinted;
} }