fseek - llseek not behaving in kernel driver -
i have been writing lcd kernel driver lcd module. going well, can write display, create /dev/lcd node can write , display results on screen. thought using llseek fops callback position cursor on lcd good, way use rewind fseek etc. not working expected, below summary of seeing:
the relevant lines of code driver side are:
loff_t lcd_llseek(struct file *filp, loff_t off, int whence) { switch (whence) { case 0: // seek_set if (off > 4*line_length || off < 0) { printk(kern_err "unsupported seek_set offset %llx\n", off); return -einval; } lcd_gotoxy(&lcd, off, 0, whence_abs); break; case 1: // seek_cur if (off > 4*line_length || off < -4*line_length) { printk(kern_err "unsupported seek_cur offset %llx\n", off); return -einval; } lcd_gotoxy(&lcd, off, 0, whence_rel); break; case 2: // seek_end (not supported, hence fall though) default: // how did here ! printk(kern_err "unsupported seek operation\n"); return -einval; } filp->f_pos = lcd.pos; printk(kern_info "lcd_llseek complete\n"); return lcd.pos; } int lcd_open(struct inode *inode, struct file *filp) { if (!atomic_dec_and_test(&lcd_available)) { atomic_inc(&lcd_available); return -ebusy; // open } return 0; } static struct file_operations fops = { .owner = this_module, .write = lcd_write, .llseek = lcd_llseek, .open = lcd_open, .release = lcd_release, }; int lcd_init(void) { ... // allocate new dev number (this can dynamic or // static if passed in module param) if (major) { devno = mkdev(major, 0); ret = register_chrdev_region(devno, 1, module_name); } else { ret = alloc_chrdev_region(&devno, 0, 1, module_name); major = major(devno); } if (ret < 0) { printk(kern_err "alloc_chrdev_region failed\n"); goto fail; } // create dummy class lcd cl = class_create(this_module, "lcd"); if (is_err(cl)) { printk(kern_err "class_simple_create class lcd failed\n"); goto fail1; } // create cdev interface cdev_init(&cdev, &fops); cdev.owner = this_module; ret = cdev_add(&cdev, devno, 1); if (ret) { printk(kern_err "cdev_add failed\n"); goto fail2; } // create /sys/lcd/fplcd/dev udev add our device /dev/fplcd device = device_create(cl, null, devno, null, "lcd"); if (is_err(device)) { printk(kern_err "device_create fplcd failed\n"); goto fail3; } ... }
to test lseek call have following unit test:
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #define log(msg, ...) fprintf(stdout, __file__ ":%s():[%d]:" msg, __func__, __line__, __va_args__) int lcd; void test(void) { int k; // lot of hello's log("hello world test\n",1); if (lseek(lcd, 0, seek_cur) == -1) { log("failed seek\n", 1); } } int main(int argc, char **argv) { lcd = open("/dev/lcd", o_wronly); if (lcd == -1) { perror("unable open lcd"); exit(exit_failure); } test(); close(lcd); return 0; }
the files cross compiled so:
~/workspace/ts4x00/lcd-module$ cat makefile obj-m += fls_lcd.o all: make -c $(kpath) m=$(pwd) modules $(cross_compile)gcc -g -fpic $(cflags) lcd_unit_test.c -o lcd_unit_test clean: make -c $(kpath) m=$(pwd) clean rm -rf lcd_unit_test ~/workspace/ts4x00/lcd-module$ make cflags+="-march=armv4 -ffunction-sections -fdata-sections" make -c ~/workspace/ts4x00/linux-2.6.29 m=~/workspace/ts4x00/lcd-module modules make[1]: entering directory `~/workspace/ts4x00/linux-2.6.29' cc [m] ~/workspace/ts4x00/lcd-module/fls_lcd.o ~/workspace/ts4x00/lcd-module/fls_lcd.c:443: warning: 'lcd_entry_mode' defined not used building modules, stage 2. modpost 1 modules cc ~/workspace/ts4x00/lcd-module/fls_lcd.mod.o ld [m] ~/workspace/ts4x00/lcd-module/fls_lcd.ko make[1]: leaving directory `~/workspace/ts4x00/linux-2.6.29' ~/workspace/ts4x00/arm-2008q3/bin/arm-none-linux-gnueabi-gcc -g -fpic -march=armv4 -ffunction-sections -fdata-sections lcd_unit_test.c -o lcd_unit_test
this output of running driver unit test is:
root@ts4700:~/devel# insmod ./fls_lcd.ko root@ts4700:~/devel# ./lcd_unit_test lcd_unit_test.c:test():[61]:hello world test lcd_unit_test.c:test():[63]:failed seek root@ts4700:~/devel# dmesg fls lcd driver started unsupported seek_set offset bf0a573c
i cannot figure out why parameters being mucked badly on kernel side, tried seek_cur position 0 , in driver seek_set (no matter put in unit test) , crazy big number off?
does know going on please ?
btw compiling kernel 2.6.29 on arm dev kit
ok sorry guys after trying debug last night comes down compiling against wrong kernel (i had kpath left different config of kernel on sdcard)
sorry wasting everyones time, if seeing looks crazy stack in kernel driver might set them straight.
oh , :)
Comments
Post a Comment