Hello,
I a friend of me has to write a kernel driver module for an university lecture.
So im trying to help him but we cant get a solution for out problem.
we have to set the serial port to 115200 baud rate, 8 bit, 1 stop bit and no parity.
the port is connected to an i2c serial modem
http://www.horter.de/i2c/i2c-usb-mod...b-modem_1.html
this modem is connected to an i2c lm75 temperature sensor.
http://www.horter.de/i2c/i2c-tempera...peratur_1.html
so now we are trying to read out the temp.
we have to send a few hex values to the modem, which is working wonderful.
then we have to read out the data from the fifo buffer.
the first and second value are correct. but the next 3 values are totally wrong.
Im thinking that the fifo buffer is doing something strange with our values. it does some sort of shifting or adding with the next 3 values.
so we get sometimes 2 and sometimes 3 values. it depends from the temperature. is it 19.0 degree, so the last value is 0x04 but if its 19.5 the last value is 0xFF but it should be 10000000 (128) and the last one should be 0x04 or 00000100 but its some sort of crumbled together when the temperature is .5
can someone please help?
here is the code:
Code:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/tty.h>
#include <linux/string.h>
#include <linux/proc_fs.h>
//#include <asm/page.h>
#include <linux/slab.h>
#include <asm/io.h> // outb()
#include <linux/ioport.h> // check_region
//#include <asm/uaccess.h> // put_user
#include <linux/delay.h> //sleep
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Felix Blumenstein");
MODULE_DESCRIPTION("Temperatur-Sensor-Treiber");
#define PORT 0x2E8
#define DEVICE_NAME "t-meter"
static int isOpened = 0; //Gerät in verwendung (1) oder nicht (0)
int print_x(char* str){
struct tty_struct *my_tty;
my_tty = get_current_tty();
if (my_tty == NULL) return -ENOTTY;
(my_tty->driver->ops->write)(my_tty, str, strlen(str));
return 0;
}
int rec_data(void) {
return inb(PORT + 5) & 1;
}
void rec_temp(void) {
char msgbyte;
//unsigned char temp[8] = {"00000000"};
// unsigned char msghex;
int i;
i=0;
while (rec_data() == 1){
msleep(200);
msgbyte = inb(PORT);
for(i = 7; i >= 0 ; --i) {
if(msgbyte & (1 << i)) {
print_x("1");
}
else {
print_x("0");
}
}
print_x("\r\n");
}
//bin2hex(&msghex, &temp, 2);
//print_x(&temp);
}
void init_serial(void){
outb(0x00, PORT + 1); // Interupt Enable Register auf 0 setzen (IR deaktivieren)
outb(0x80, PORT + 3); // Divisor Latch Bit auf 1 setzen - dazu line Control register in Bit 7 auf high
outb(0x01, PORT + 0); // Divisor auf 1 setzen (low byte) um Baudrate von 115200 einzustellen
outb(0x00, PORT + 1); // (hi byte)
outb(0x0B, PORT + 3); // 8 bits, no parity, one stop bit
outb(0x00, PORT + 3); // Baudratenkonfig abgeschlossen (DLAB 0)
outb(0x87, PORT + 2); // FIFO-Register zurücksetzen
outb(0x0B, PORT + 4);
}
static void temp_init(void){
outb(0x31, PORT);
outb(0x01, PORT);
outb(0x07, PORT);
outb(0x04, PORT);
}
static void rot(void){
msleep(20);
outb(0x31, PORT);
msleep(20);
outb(0x01, PORT);
msleep(20);
outb(0x00, PORT);
msleep(20);
outb(0x04, PORT);
}
static void gruen(void){
outb(0x31, PORT);
outb(0x01, PORT);
outb(0x05, PORT);
outb(0x04, PORT);
}
static void gelb(void){
outb(0x31, PORT);
outb(0x01, PORT);
outb(0x06, PORT);
outb(0x04, PORT);
}
static void send_temp(void){
outb(0x33, PORT);
outb(0x03, PORT);
outb(0x91, PORT);
outb(0x00, PORT);
outb(0x02, PORT);
outb(0x04, PORT);
}
static int device_open(struct inode* in, struct file* f){
if (isOpened) { return -EBUSY; }
print_x("open() \n\r");
isOpened = 1; // Geraet sperren, da es in Verwendung ist
return 0;
}
static int device_release(struct inode* in, struct file* f){
print_x("release() \n\r");
isOpened = 0; // Geraet wieder freigeben
return 0;
}
static ssize_t device_write(struct file* f, const char* buf, size_t len, loff_t* off) {
int i;
print_x("hello write\n\r");
for (i = 0; i<len; i++){
if (buf[i] == 'r'){
rot();
msleep(50);
rec_temp();
}
if (buf[i] == 'y'){
gelb();
msleep(50);
rec_temp();
}
if (buf[i] == 'g'){
gruen();
msleep(50);
rec_temp();
}
if (buf[i] == 't'){
temp_init();
msleep(100);
rec_temp();
print_x("Temp: \r\n");
send_temp();
msleep(100);
rec_temp();
}
}
return len;
}
static ssize_t device_read(struct file *filp, char *buffer, size_t len, loff_t *offs){
print_x("hello read\n\r");
return len;
}
static struct file_operations fops = {
.write = device_write,
.read = device_read,
.open = device_open,
.release = device_release,
.owner = THIS_MODULE };
static int modu_init(void){
proc_create(DEVICE_NAME, 0777, NULL, &fops);
print_x("Treiber geladen\n\r");
printk("ModuleÂ*loaded \n");
init_serial();
rec_temp();
return 0;
}
static void modu_exit(void){
print_x("Treiber entladen\n\r");
printk("ModuleÂ*unloadedÂ*\n");
outb(0x31, PORT);
outb(0x01, PORT);
outb(0x04, PORT);
outb(0x04, PORT);
rec_temp();
remove_proc_entry(DEVICE_NAME, NULL);
}
module_init(modu_init);
module_exit(modu_exit);