📄 trlight.c
字号:
#include <linux/kernel.h>#include <linux/config.h>#include <linux/module.h>#include <linux/version.h>#include <linux/types.h>#include <linux/ioport.h>#include <linux/mm.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/tqueue.h>#include <linux/ctype.h>#include <asm/segment.h>#include <asm/io.h>#include <asm/uaccess.h>#include "ring.h"#include "trlight.h"#define ADDRRANGE 3static int trlight_major = 99;static int base=0x378;ring_buf write_buf;static int write_open = 0;static int read_open =0; int traffic_setval = 0;int traffic_delay = 120;unsigned short word =3;static int tick_counter = 0;static void timer_handler(void *);static struct tq_struct time_queue_entry = { routine:timer_handler, };int queue_flag=1; static DECLARE_WAIT_QUEUE_HEAD(tick_wait);void turn_on_off(){ if(word!=0) word=~word; outw((word & 0x00FF),base+0); }void start(){ word=3;}void stop(){ word=0;}static void bottom_half(){ tick_counter++; if (ring_buf_read(&write_buf, &traffic_setval)==1) { traffic_delay=traffic_setval; } if(traffic_delay<=tick_counter) { tick_counter=0; turn_on_off(); } if(queue_flag==1) queue_task(&time_queue_entry,&tq_timer); else wake_up(&tick_wait); } static void timer_handler(void *tick){ bottom_half();}static int trlight_read(struct file *fp,char *buf, size_t count, loff_t* pos);static int trlight_write(struct file* fp, const char *buf,size_t count, loff_t* pos);static int trlight_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg);static int trlight_open(struct inode *inode,struct file *file);static int trlight_release(struct inode *inode,struct file *file); static struct file_operations trlight_fops = { THIS_MODULE, /*module owner*/ NULL, /* lseek */ trlight_read, /* read */ trlight_write, /* write */ NULL, /* readdir */ NULL, /* select */ trlight_ioctl, /* ioctl */ NULL, /* mmap */ trlight_open, /* open */ NULL, trlight_release, /* close */ NULL, /* fsync */ NULL, /* fasync */ NULL, NULL, NULL, NULL, NULL,};static int trlight_read(struct file *fp,char *buf, size_t count, loff_t* pos){ int len; char kbuf[64]; sprintf(kbuf,"delay=%d\n",traffic_delay); len=strlen(kbuf)+1; len=len<count?len:count; if(verify_area(VERIFY_WRITE,buf,len) < 0){ printk("trlight_read:verify area failed\n"); return(-1); } copy_to_user(buf,kbuf,len); return len;} static int trlight_write(struct file* fp, const char *buf,size_t count, loff_t* pos){ static int counter=0; int *value; static char local[sizeof(int)]; int ret; if(!write_open){ printk("trlight:ERROR: not open for writing\n"); return -1; } if((verify_area(VERIFY_READ,buf,count)) < 0){ printk("trlight_write:verify area failed\n"); return(-1); } if(counter<sizeof(int)-1){ copy_from_user(local+counter,buf,1); counter++; return 1; } else if(counter==sizeof(int)-1){ counter=0; value=(int*)local; if(*value<0) { printk("trlight:ERROR: invalid value\n"); return -1; } ret = ring_buf_write(&write_buf,*value); if(ret==1) return 1; else return -1; }else return -1;}static int trlight_ioctl(struct inode *inode,struct file *file,unsigned int cmd, unsigned long arg){ if (cmd==TRLIGHT_STOP) { printk("in stop\n"); stop(); return 0; } if (cmd==TRLIGHT_START) { printk("in start\n"); start(); return 0; } return -1;}static int trlight_open(struct inode *inode,struct file *file){ printk("trlight:trlight_open()-file->f_mode=%d\n",file->f_mode); if(file->f_mode == 1){ /* read */ if(write_open){ printk("trlight:trlight_open()- write busy\n"); return(-EBUSY); } MOD_INC_USE_COUNT; read_open++; }else{ if(file->f_mode == 2){ /* write */ if(write_open){ printk("trlight:trlight_open()- write busy\n"); return(-EBUSY); }else{ if(read_open>0){ printk("trlight:trlight_open()- read busy\n"); return(-EBUSY); } write_open = 1; MOD_INC_USE_COUNT; } }else{ printk("trlight:trlight_open()-unknown mode\n"); return(-EINVAL); } } return 0;}int trlight_release(struct inode *inode,struct file *file){ if(file->f_mode == 1){ /* read */ MOD_DEC_USE_COUNT; read_open--; }else if(file->f_mode ==2){ /* write */ if(write_open){ write_open = 0; MOD_DEC_USE_COUNT; }else{ printk("trlight:no write device to close-ERROR\n"); return -1; } }else{ printk("trlight:trlight_release()-unknown mode\n"); return -1; } return 0;}int init_module(void){ int major; ring_buf_init(&write_buf); if((major = register_chrdev(trlight_major,"trlight",&trlight_fops))<0){ printk("trlight:unable to get major device\n"); return(-EIO); } printk("trlight:major number=%d\n",trlight_major); if(check_region(base,ADDRRANGE)){ printk("trlight:port in use"); return -1; } request_region(base,ADDRRANGE,"trlight"); if(!queue_task(&time_queue_entry,&tq_timer)) return -1; printk("trlight:module loaded\n"); return(0);} void cleanup_module(void){ release_region(base,ADDRRANGE); if(MOD_IN_USE){ printk("trlight:device busy, del delayed\n"); return; } printk("unregister_chrdev(%d,%s)\n",trlight_major,"trlight"); if(unregister_chrdev(trlight_major,"trlight")!=0){ printk("trlight: unregister_chrdev() failed.\n"); printk("trlight:/proc/devices will cause core dumps\n"); } if(queue_flag){ queue_flag=0; sleep_on(&tick_wait); } printk("trlight:module unloaded\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -