#include #include #include #include "k_file.h" #include "k_debug.h" int SetBaudrate(struct k_file *kfp, int rate) { struct termios ts; int speed=B19200; int rv=0; switch(rate) { case 9600:speed=B9600;break; case 19200:speed=B19200;break; case 38400:speed=B38400;break; default: return -EINVAL; } rv = K_IOCTL(kfp,TCGETS, &ts); if( rv<0 ) { _E("K_IOCTL failed (%d)\n",rv); return rv; } _D("*** old ***\n"); _D("i:0x%08x\n",ts.c_iflag); ts.c_iflag = 0x0000; _D("o:0x%08x\n",ts.c_oflag); ts.c_oflag = 0x0004; _D("c:0x%08x\n",ts.c_cflag); ts.c_cflag = 0x0cbd; _D("l:0x%08x\n",ts.c_lflag); ts.c_lflag = 0x0a30; ts.c_cflag = (ts.c_cflag & 0xfff0) | speed; rv = K_IOCTL(kfp,TCSETS, &ts); if( rv<0 ) { _E("K_IOCTL failed (%d)\n",rv); return rv; } rv = K_IOCTL(kfp,TCGETS, &ts); if( rv<0 ) { _E("K_IOCTL failed (%d)\n",rv); return rv; } _D("*** new ***\n"); _D("i:0x%08x\n",ts.c_iflag); ts.c_iflag = 0; _D("o:0x%08x\n",ts.c_oflag); ts.c_oflag = 0; _D("c:0x%08x\n",ts.c_cflag); ts.c_cflag = 0; _D("l:0x%08x\n",ts.c_lflag); ts.c_lflag = 0; return 0; } int k_ioctl(struct k_file *kfp, unsigned int cmd, unsigned long data) { int rv=-1; if( kfp->filp->f_op->ioctl && kfp->filp->f_dentry->d_inode ) { mm_segment_t oldfs; oldfs = get_fs(); set_fs( KERNEL_DS ); //rv = kfp->filp->f_op->ioctl( kfp->filp->f_dentry->d_inode, kfp->filp, cmd, data ); rv = kfp->filp->f_op->ioctl( 0, kfp->filp, cmd, data ); set_fs(oldfs); } else { _D("[k_ioctl] ioctl not supported\n"); } return rv; } void k_close(struct k_file *kfp) { if( kfp==NULL ) return; if( kfp->filp ) filp_close( kfp->filp, NULL ); kfree( kfp ); } loff_t k_seek(struct k_file *kfp, loff_t offset, int mode) { mm_segment_t oldfs; oldfs = get_fs(); set_fs( KERNEL_DS ); set_fs(oldfs); return 0; } ssize_t k_read(struct k_file *kfp, char __user *buffer, size_t size) { ssize_t len=0; mm_segment_t oldfs; oldfs = get_fs(); set_fs( KERNEL_DS ); //_D("read(%d)",(int)size); len = kfp->filp->f_op->read( kfp->filp, buffer, size, &(kfp->filp->f_pos) ); //_D("->%d\n",len); set_fs(oldfs); return len; } ssize_t k_write(struct k_file *kfp, char __user *buffer, size_t size) { ssize_t len=0; mm_segment_t oldfs; oldfs = get_fs(); set_fs( KERNEL_DS ); //_D("write(%d)",(int)size); len = kfp->filp->f_op->write( kfp->filp, buffer, size, &(kfp->filp->f_pos) ); //_D("->%d\n",len); set_fs(oldfs); return len; } int k_select(struct k_file *kfp) { mm_segment_t oldfs; oldfs = get_fs(); set_fs( KERNEL_DS ); set_fs(oldfs); return 0; } static struct k_file_ops k_fops = { .close = k_close, .seek = k_seek, .read = k_read, .write = k_write, .select = k_select, .ioctl = k_ioctl }; struct k_file * k_open( char *name, int flags, int mode ) { struct k_file *kfp=NULL; struct file *filp=NULL; filp = filp_open( name, flags, mode ); if( IS_ERR(filp) || filp->f_op==NULL || filp->f_op->read==NULL || (filp->f_op->write==NULL && flags!=O_RDONLY) ) { _E("filp_open of [%s] failed (%d)\n",name,(int)filp); filp=NULL; goto failed; } kfp = kmalloc( sizeof( struct k_file ), GFP_KERNEL ); if( kfp==NULL ) { _E("kmalloc failed\n"); goto failed; } kfp->filp = filp; kfp->ops = &k_fops; if( filp->f_dentry && filp->f_dentry->d_inode ) { kfp->size = filp->f_dentry->d_inode->i_size; } return kfp; failed: if( kfp ) kfree( kfp ); if( filp ) filp_close( filp, NULL ); return NULL; }