/* */ #include #include #include #include #include /* printk() */ #include /* everything... */ #include /* error codes */ #include /* udelay */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define LCD_NR_PORTS 1 /* use 1 ports by default */ #define LCD_MASK 0x0B #define LCD_E 0x08 #define LCD_EN 0x09 #define LCD_RS 0x0C #define LCD_CLEAR 0x01 #define LCD_HOME 0x02 #define LCD_ENTRY 0x04 // this will have to be or to shift right or left #define LCD_OFF 0x08 #define LCD_ON 0x0C #define LCD_CURSOR_ON 0x02 #define LCD_BLINK_ON 0x01 #define LCD_CUR_SHIFT_LEFT 0x10 #define LCD_CUR_SHIFT_RIGHT 0x14 #define LCD_FCNT_SET 0x38 static char lcd_e = 0x08; static char lcd_en = 0x09; static char lcd_rs = 0x0C; void do_scroll(void); /* this is a one to one mapping of the cursor position in the device */ int columns[80]={ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53, 0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, 0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67}; struct timer_list timer; char *buf,*test,*ptr; char * area; int temporary = 0; // this is used for the scrolling. is where the string actually starts (w/o flags) int scrolling = 0; // 0 means is off int current_start; int current_display=0; int current_line; int mmap=0; spinlock_t lock; /* * all of the parameters have no "lcd_" prefix, to save typing when * specifying them at load time */ static int major = 0; /* dynamic by default */ module_param(major, int, 0); /* default is the first printer port on PC's. "lcd_base" is there too because it's what we want to use in the code */ static unsigned long base = 0x378; unsigned long lcd_base = 0; module_param(base, long, 0); int minor; struct inode inode; struct file filp; int count=0,moveby=0;; unsigned long port = 0x378 ; int column=0; unsigned long virt_addr; char temp='0'; void write_command(char); void mmap_print(void); MODULE_AUTHOR ("Alessandro Rubini"); MODULE_LICENSE("Dual BSD/GPL"); int parse_cmd(char * t) { int i=0,j=0; if(t[0]=='-') { //printk(KERN_INFO "flag sets\n"); //check scrolling if(scrolling==1) { if(!((t[i+1] == 'S' || t[i+1] == 's') && (t[i+2] == 'C' || t[i+2] == 'c') && (t[i+3] == 'R' || t[i+3] == 'r') && (t[i+4] == 'O' || t[i+4] == 'o') && (t[i+5] == 'F' || t[i+5] == 'f'))) return -1; } for(i=0;i5) && t[i+3]!=' '){ //three of more digits specified = FAIL //printk(KERN_INFO "move by fail\n"); } if(t[i+2]=='R' || t[i+2]=='r'){ //printk(KERN_INFO "Move right by = %d\n",moveby); write_command(LCD_ON); column+=moveby; column%=80; write_command(0x80^columns[column]); write_command(LCD_ON | LCD_CURSOR_ON); } else if(t[i+2]=='L' || t[i+2]=='l'){ //printk(KERN_INFO "Move left by = %d\n",moveby); write_command(LCD_ON); //printk(KERN_INFO "column before = %d \n",column); column-=moveby; //printk(KERN_INFO "column here = %d \n",column); column%=80; if (column<0) { column+=80; } //printk(KERN_INFO "column after= %d \n",column); write_command(0x80^columns[column]); write_command(LCD_ON | LCD_CURSOR_ON); } } // end of move cursor else if(t[i+1] == 'C' || t[i+1] == 'c'){ if((t[i+2] == 'L' || t[i+2] == 'l') && (t[i+3] == 'R' || t[i+3] == 'r')) write_command(LCD_CLEAR); j=i+5; }// end of clear else if(t[i+1] == 'Z' || t[i+1] == 'z'){ if((t[i+2] == 'O' || t[i+2] == 'o')) { if(t[i+3] == 'n' || t[i+3] == 'N') { //cursor on //printk(KERN_INFO "cursor on\n"); write_command(LCD_ON | LCD_CURSOR_ON); j=i+5; } else if(t[i+3] == 'f' || t[i+3] == 'F') { //cursor off //printk(KERN_INFO "cursor off"); write_command(LCD_ON); j=i+5; } } }// end of cursor on/off else if(t[i+1] == 'd' || t[i+1] == 'D'){ if((t[i+2] == 'O' || t[i+2] == 'o')) { if(t[i+3] == 'n' || t[i+3] == 'N') { //Display on //printk(KERN_INFO "Display on"); write_command(0x0c); j=i+5; } else if(t[i+3] == 'f' || t[i+3] == 'F') { //Display off //printk(KERN_INFO "Display off"); write_command(0x08); j=i+5; } } }// end of display on/off else if(t[i+1] == 'b' || t[i+1] == 'B'){ if((t[i+2] == 'O' || t[i+2] == 'o')) { if(t[i+3] == 'n' || t[i+3] == 'N') { //Backlight on //printk(KERN_INFO "Backlight on"); lcd_e = 0x08; lcd_en = 0x09; lcd_rs = 0x0C; outb((lcd_e ^ LCD_MASK),port+2); mdelay(1); j=i+5; } else if(t[i+3] == 'f' || t[i+3] == 'F') { //Backlight off //printk(KERN_INFO "Backlight off"); lcd_e = 0x00; lcd_en = 0x01; lcd_rs = 0x04; outb((lcd_e ^ LCD_MASK),port+2); mdelay(1); j=i+5; } } } // end of backlight on/off else if((t[i+1] == 'S' || t[i+1] == 's') && (t[i+2] == 'C' || t[i+2] == 'c') && (t[i+3] == 'R' || t[i+3] == 'r') && (t[i+4] == 'O' || t[i+4] == 'o')){ if(t[i+5] == 'N' || t[i+5] == 'n'){ j=i+7; scrolling = 1; } else if(t[i+5] == 'F' || t[i+5] == 'f') { j=i+7; scrolling = 0; column = 0; temporary = 0; /* Set 8-bit mode */ write_command(LCD_FCNT_SET); /* LCD on and cursor on */ write_command(LCD_ON | LCD_CURSOR_ON); /* sets entry mode and cursor moves right */ write_command(LCD_ENTRY | 0x02); write_command(LCD_CLEAR); del_timer_sync(&timer); } } if((t[i+1] == 'M' || t[i+1] == 'm') && (t[i+2] == 'M' || t[i+2] == 'm') && (t[i+3] == 'A' || t[i+3] == 'a') && (t[i+4] == 'P' || t[i+4] == 'p') && (t[i+5] == 'O' || t[i+5] == 'o')){ if(t[i+6] == 'N' || t[i+6] == 'n'){ j=i+8; mmap = 1; } else if(t[i+6] == 'F' || t[i+6] == 'f') { j=i+8; mmap = 0; } } } } } return j; } void do_scroll(void) { int i=0; spin_lock(&lock); current_display = current_start; current_line=0; write_command(LCD_OFF); write_command(LCD_CLEAR); for(i=0;i<80;i++) { if(current_display == count) current_display = temporary; if(buf[current_display]=='\n') { if(current_line==0) { if(current_display+1vm_end - vma->vm_start); if (size > PAGE_SIZE) return -EIO; if (remap_pfn_range(vma, vma->vm_start, virt_to_phys((void *)area) >> PAGE_SHIFT, size, vma->vm_page_prot) < 0) { return -EAGAIN; } //vma->vm_ops = &lcd_vm_ops; return 0; } int lcd_open (struct inode *inode, struct file *filp) { minor = iminor(inode); //printk(KERN_INFO "Open----------------------\n"); return 0; } int lcd_release (struct inode *inode, struct file *filp) { return 0; } /* * Version-specific methods for the fops structure. FIXME don't need anymore. //*/ ssize_t lcd_read(struct file *filp, char __user *buffer, size_t cnt, loff_t *f_pos) { int i, total = cnt; /* copies X character from the memory mapping */ if(mmap == 1){ //printk(KERN_INFO "MEMORY MAPPING READ\n"); if(total > 80) total = 80; for(i=0;i count-temporary) total = count-temporary; for(i=temporary;i