get info in a loop from a sysfs entry
Hi all, This might be a silly question, but I want to make sure I understand things correctly. I have a driver with a sysfs entry to get the next data sample every time I read the file. Used like below it works wonderful: # cat next 0x15814 # cat next 0x1682B The last 12 bits are the sample and the first (20) bits are the channel the sample is from (some ADC hardware board with 24 inputs). Now I have some C code that will loop periodically to collect the samples and do some magic with them and I was hoping I could simply keep a FILE * open with a loop like this: for (i = 0; i < count; i++) { if (fscanf(fd_next, "0x%X", &sample) != 1) { /* No data */ continue; } channel = sample >> 12; adc_data = sample & 0xFFF; if (channel > 23) { /* Sample out of range */ error_helper("ADC sample out of range", 0x32000010, 0); continue; } a_in[channel] = adc_data; fseek(fd_next, 0, SEEK_SET); } The problem is that after storing 1 sample, the next samples are never getting updated. I suppose the last line (fseek) does not cause the sysfs function to be called again as I hoped. But the sysfs documentation in the kernel says: If userspace seeks back to zero or does a pread(2) with an offset of '0' the show() method will be called again, rearmed, to fill the buffer. Can anyone tell me what I might be doing wrong? Wouter
On 01/04/2011 11:48 AM, Wouter Simons wrote:
Hi all,
This might be a silly question, but I want to make sure I understand things correctly.
I have a driver with a sysfs entry to get the next data sample every time I read the file. Used like below it works wonderful:
# cat next 0x15814 # cat next 0x1682B
The last 12 bits are the sample and the first (20) bits are the channel the sample is from (some ADC hardware board with 24 inputs).
Now I have some C code that will loop periodically to collect the samples and do some magic with them and I was hoping I could simply keep a FILE * open with a loop like this:
for (i = 0; i < count; i++) { if (fscanf(fd_next, "0x%X", &sample) != 1) { /* No data */ continue; } channel = sample >> 12; adc_data = sample & 0xFFF; if (channel > 23) { /* Sample out of range */ error_helper("ADC sample out of range", 0x32000010, 0); continue; } a_in[channel] = adc_data; fseek(fd_next, 0, SEEK_SET); }
The problem is that after storing 1 sample, the next samples are never getting updated. I suppose the last line (fseek) does not cause the sysfs function to be called again as I hoped.
But the sysfs documentation in the kernel says: If userspace seeks back to zero or does a pread(2) with an offset of '0' the show() method will be called again, rearmed, to fill the buffer.
Can anyone tell me what I might be doing wrong?
I believe I have found the issue. The older kernel my driver is currently running on (a 2.6.21 version maintained by the hardware supplier) does not seem to rearm the show method on seek to 0. crap... Wouter
On Tue, Jan 04, 2011 at 01:46:38PM +0100, Wouter Simons wrote:
I believe I have found the issue. The older kernel my driver is currently running on (a 2.6.21 version maintained by the hardware supplier) does not seem to rearm the show method on seek to 0.
2.6.21 is so obsolete and old and insecure it's not funny. Please use a modern kernel version. good luck, greg k-h
On 01/04/2011 02:56 PM, Greg KH wrote:
On Tue, Jan 04, 2011 at 01:46:38PM +0100, Wouter Simons wrote:
I believe I have found the issue. The older kernel my driver is currently running on (a 2.6.21 version maintained by the hardware supplier) does not seem to rearm the show method on seek to 0.
2.6.21 is so obsolete and old and insecure it's not funny. Please use a modern kernel version.
Yes, I know. It is a shame that I am currently forced to use this. The problem is that the board that I am using is not supported in newer kernel versions. There have been people that tried to put it into the mainline kernel, but that is now basically unmaintained code and I cannot compile a recent kernel for my platform. The long-term solution is to work to integrate required drivers into the mainline, but I work for a commercial company and we are launching a system soon which is running in an embedded style with this platform. The system is a TS-7800 arm based SBC from http://embeddedarm.com, the hardware is good, but unfortunately they have chosen to take a kernel version and make their own fork without making sure it gets updated. The ts7800 platform support in the current kernel does not appear to work, or I am too dumb to make it work ;-) The only good thing about this is that I do not have to run this board connected to the internet or any other untrusted source directly. Hopefully, I will get the time required this year to update the required components to the current kernel version and get it into the ARM arch, but honestly, I started developing a few drivers for this board and am not a linux guru (yet) so it is a daunting task to take up on my own. So yes I would like to move to a newer kernel, but it is not trivial. best regards, Wouter
Hi Wouter, On Tue, Jan 4, 2011 at 2:48 AM, Wouter Simons <lkml@woutersimons.org> wrote:
Hi all,
This might be a silly question, but I want to make sure I understand things correctly.
I have a driver with a sysfs entry to get the next data sample every time I read the file. Used like below it works wonderful:
# cat next 0x15814 # cat next 0x1682B
The last 12 bits are the sample and the first (20) bits are the channel the sample is from (some ADC hardware board with 24 inputs).
Now I have some C code that will loop periodically to collect the samples and do some magic with them and I was hoping I could simply keep a FILE * open with a loop like this:
for (i = 0; i < count; i++) { if (fscanf(fd_next, "0x%X", &sample) != 1) { /* No data */ continue; }
I would change this to use unbuffered I/O routines (i.e. open/read/lseek/close) and use sscanf rather than fscanf. fopen/fread/fseek/fclose use buffering by default. That would eliminate any buffering that the user side runtime library is doing. I suspect that because the data is buffered by the FILE * routines, even doing the seek is just re-returning the data that was read the first time around. Dave Hylands
On 01/04/2011 04:52 PM, Dave Hylands wrote:
On Tue, Jan 4, 2011 at 2:48 AM, Wouter Simons <lkml@woutersimons.org> wrote:
for (i = 0; i < count; i++) { if (fscanf(fd_next, "0x%X", &sample) != 1) { /* No data */ continue; }
I would change this to use unbuffered I/O routines (i.e. open/read/lseek/close) and use sscanf rather than fscanf. fopen/fread/fseek/fclose use buffering by default.
That would eliminate any buffering that the user side runtime library is doing. I suspect that because the data is buffered by the FILE * routines, even doing the seek is just re-returning the data that was read the first time around.
Thanks Dave, a quick test application shows that your solution works perfectly. This saves me a lot of overhead! Best regards, Wouter
participants (3)
-
Dave Hylands -
Greg KH -
Wouter Simons