📄 eibdrv.c
字号:
if (ftstation.port.filp->f_op->read(ftstation.port.inodp,ftstation.port.filp,buf,1)==0)#endif return -EAGAIN; return 1;} int timeout_read(unsigned char *buf,int count){ int n_read=0; int result; struct termios help_termios; ftstation.port.tty->termios->c_cc[VTIME]=1; ftstation.port.tty->termios->c_cc[VMIN]=0; ftstation.port.tty->driver.set_termios(ftstation.port.tty,&help_termios); ftstation.port.tty->ldisc.set_termios(ftstation.port.tty,&help_termios); while (n_read<count) { #if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0) if ((result=ftstation.port.filp->f_op->read(ftstation.port.filp,buf+n_read, count-n_read,&ftstation.port.filp->f_pos))==0)#else if ((result=ftstation.port.filp->f_op->read(ftstation.port.inodp,ftstation.port.filp,&buf[n_read], count-n_read))==0) #endif { ftstation.port.tty->termios->c_cc[VTIME]=0; ftstation.port.tty->termios->c_cc[VMIN]=0; ftstation.port.tty->driver.set_termios(ftstation.port.tty,&help_termios); ftstation.port.tty->ldisc.set_termios(ftstation.port.tty,&help_termios); return n_read; } n_read+=result; } ftstation.port.tty->termios->c_cc[VTIME]=0; ftstation.port.tty->termios->c_cc[VMIN]=0; ftstation.port.tty->driver.set_termios(ftstation.port.tty,&help_termios); ftstation.port.tty->ldisc.set_termios(ftstation.port.tty,&help_termios); return n_read;}int repeat_write(unsigned char *msg,int msg_len,int wait_state){ unsigned char ack_msg[4]; int stat_write=0; struct timeval wait_start,wait_actual; unsigned long wait_jiffies; ftstation.wrepeat=0; ftstation.state=wait_state; if (wait_state==FT_STATE_WAIT_FOR_UDATA_ACK) stat_write=1; fs=get_fs(); set_fs(KERNEL_DS); do { ftstation.wrepeat++;#ifdef DEBUG printk(KERN_WARNING "eibdrv (%i): Schreibversuch %i\n",c++,ftstation.wrepeat);#endif line_idle_delay(); do_gettimeofday(&ftstation.start_write);#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0) ftstation.port.filp->f_op->write(ftstation.port.filp,msg,msg_len,&ftstation.port.filp->f_pos);#else ftstation.port.filp->f_op->write(ftstation.port.inodp,ftstation.port.filp,msg,msg_len);#endif do_gettimeofday(&ftstation.last_seract); switch(mode) { case FT_SERVERMODE: unlock(&sv_ser_read);#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0) interruptible_sleep_on_timeout(&wq_wait_for_ack,ftstation.exchange_timeout); #else current->timeout=jiffies+ftstation.exchange_timeout; interruptible_sleep_on(&wq_wait_for_ack);#endif lock(&sv_ser_read); break; case FT_STANDARDMODE: wait_start=ftstation.last_seract; wait_actual=wait_start; while (((wait_jiffies=timeval_to_jiffies(diff_timeval(ftstation.exchange_time, diff_timeval(wait_actual,wait_start))))>0)&&(ftstation.state!=FT_STATE_READY)) {#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0) interruptible_sleep_on_timeout(&ftstation.port.tty->read_wait,wait_jiffies);#else current->timeout=jiffies+wait_jiffies; interruptible_sleep_on(&ftstation.port.tty->read_wait);#endif do_gettimeofday(&wait_actual); while ((immediate_read(&ack_msg[0])==1)&&(ftstation.state!=FT_STATE_READY)) { switch(ack_msg[0]) { case FT_FIXED_LENGTH_MSG: if (timeout_read(&ack_msg[0],3)!=3) break; if ((ack_msg[0]!=ack_msg[1])||(ack_msg[2]!=0x16)) break; if ((ack_msg[0]&0xDF)==(0x0B|((1-FT_DIR)<<7))) { #ifdef DEBUG printk(KERN_WARNING "eibdrv (%i): RESP_STATUS ==> erhalten\n",c++);#endif if (ftstation.state==FT_STATE_WAIT_FOR_RESP_STATUS) ftstation.state=FT_STATE_READY; } break; case FT_ACK: do_gettimeofday(&ftstation.end_write); if (ftstation.wrepeat==1) ftstation.stat.total_w1time=sum_timeval(ftstation.stat.total_w1time, diff_timeval(ftstation.end_write,ftstation.start_write));#ifdef DEBUG printk(KERN_WARNING "eibdrv (%i): ACK ==> erhalten!\n",c++);#endif if ((ftstation.state==FT_STATE_WAIT_FOR_UDATA_ACK)|| (ftstation.state==FT_STATE_WAIT_FOR_RESET_ACK)) ftstation.state=FT_STATE_READY; break; } } break; } } } while ((ftstation.state==wait_state)&&(ftstation.wrepeat<FT_REPEAT_LIMIT)); set_fs(fs); if (ftstation.state==wait_state) { ftstation.state=FT_STATE_READY; if (stat_write==1) { if (ftstation.stat.write[0]<ULONG_MAX) ftstation.stat.write[0]++; else ftstation.stat.overflow=1; } return 0; } else { if (stat_write==1) { if (ftstation.stat.write[ftstation.wrepeat]<ULONG_MAX) ftstation.stat.write[ftstation.wrepeat]++; else ftstation.stat.overflow=1; } return msg_len; }}void ser_write(void){ int udata_len; int msg_len; int checksum; int i,result; unsigned char msg[EIB_BUF_ELEMENT_SIZE+7]; do { interruptible_sleep_on(&wq_ser_write);// interruptible_sleep_on_timeout(&sleep_queue,20*HZ); lock(&sv_ser_write); lock(&sv_ser_read); do { if ((udata_len=eib_read_buf(ftstation.outbuf,&msg[5]))==0) { unlock(&sv_ser_read); unlock(&sv_ser_write); break; } msg_len=udata_len+7; msg[0]=msg[3]=0x68; msg[1]=msg[2]=(unsigned char)(udata_len+1); msg[4]=(FT_DIR<<7) | 0x40 | (ftstation.fcb<<5) | (FT_FCB_VALID<<4) | 0x03; checksum=msg[4];#ifdef DEBUG printk("<1>Gesendetes fcb=%i\n",ftstation.fcb);#endif DEBUG for (i=0;i<udata_len;i++) { checksum+=msg[i+5]; } msg[5+udata_len]=(unsigned char) checksum % 256; msg[6+udata_len]=0x16; if ((result=repeat_write(&msg[0],msg_len,FT_STATE_WAIT_FOR_UDATA_ACK))==msg_len) result=udata_len; if (result>=1) ftstation.fcb=1-ftstation.fcb; eib_result_wpbuf(ftstation.wpbuf,result); wake_up_interruptible(&wq_wproc); } while(1); } while (ftstation.state!=FT_STATE_SHUTDOWN);}int ser_reset(void){ int result=0; unsigned char msg[4]; msg[0]=0x10; msg[1]=msg[2]=(0x40 | (FT_DIR << 7)); msg[3]=0x16; lock(&sv_ser_write); lock(&sv_ser_read); if (repeat_write(&msg[0],4,FT_STATE_WAIT_FOR_RESET_ACK)==0) result=-ENORESET; unlock(&sv_ser_read); unlock(&sv_ser_write); return result;}int ser_status(void){ int result=0; unsigned char msg[4]; msg[0]=0x10; msg[1]=msg[2]=(0x49 | (FT_DIR << 7)); msg[3]=0x16; lock(&sv_ser_write); lock(&sv_ser_read); if (repeat_write(&msg[0],4,FT_STATE_WAIT_FOR_RESP_STATUS)==0) result=-ENORESPSTATUS; unlock(&sv_ser_read); unlock(&sv_ser_write); return result;}void empty_ttyS() { unsigned char msg; struct termios help_termios; ftstation.port.tty->termios->c_cc[VTIME]=0; ftstation.port.tty->termios->c_cc[VMIN]=0; ftstation.port.tty->driver.set_termios(ftstation.port.tty,&help_termios); ftstation.port.tty->ldisc.set_termios(ftstation.port.tty,&help_termios); while (ftstation.port.filp->f_op->read(ftstation.port.filp,&msg,1,&ftstation.port.filp->f_pos)!=0) ; ftstation.port.tty->termios->c_cc[VTIME]=1; ftstation.port.tty->termios->c_cc[VMIN]=0; ftstation.port.tty->driver.set_termios(ftstation.port.tty,&help_termios); ftstation.port.tty->ldisc.set_termios(ftstation.port.tty,&help_termios);} void ser_read(void){ int checksum; int msg_fcb; int i,k=0; int udata_len; unsigned char msg[EIB_BUF_ELEMENT_SIZE+7]; do { k++; interruptible_sleep_on(&ftstation.port.tty->read_wait); if (ftstation.state==FT_STATE_SHUTDOWN) break; fs=get_fs(); set_fs(KERNEL_DS); // if (timeout_read(&msg[0],1)==1) while (immediate_read(&msg[0])==1) { do_gettimeofday(&ftstation.end_write); switch(msg[0]) { case FT_VAR_LENGTH_MSG: // SEND_UDATA received if (timeout_read(&msg[0],4)!=4) break; if ((msg[0]!=msg[1]) || (msg[0]>24) || (msg[2]!=0x68) || ((msg[3]&0xDF)!=(unsigned char)(((1-FT_DIR)<<7) | 0x40 | (FT_FCB_VALID<<4) | 0x03))) break; msg_fcb=(int)((msg[3] & 0x20)>>5); checksum=msg[3]; udata_len=msg[0]-1; if (timeout_read(&msg[0],udata_len+2)!=udata_len+2) break; for (i=0;i<udata_len;i++) checksum+=msg[i]; if ((msg[udata_len]!=(unsigned char)(checksum%256)) || (msg[udata_len+1]!=0x16)) break; if (msg_fcb==(1-ftstation.rec_fcb)) // msg not already received { #ifdef DEBUG printk(KERN_WARNING "eibdrv (%i): SEND_UDATA ==> neue Nachricht\n",c++); printk("<1>fcb erwartet = %i erhalten = %i\n",(1-ftstation.rec_fcb),msg_fcb); #endif ftstation.rec_fcb=1-ftstation.rec_fcb; ftstation.rrepeat=0; eib_wmsg_rpbuf(ftstation.rpbuf,&msg[0],udata_len); wake_up_interruptible(&wq_rproc); if (ftstation.pasync!=NULL) kill_fasync(ftstation.pasync,SIGIO); } else { #ifdef DEBUG printk(KERN_WARNING "eibdrv (%i): SEND_UDATA ==> bereits erhalten\n",c++); printk("<1>fcb erwartet = %i erhalten = %i\n",(1-ftstation.rec_fcb),msg_fcb); #endif if (ftstation.rrepeat!=-1) ftstation.rrepeat++; } if (ftstation.rrepeat<3) { if (ftstation.stat.read[ftstation.rrepeat]<ULONG_MAX) ftstation.stat.read[ftstation.rrepeat]++; else ftstation.stat.overflow=1; if (ftstation.rrepeat>0) ftstation.stat.read[ftstation.rrepeat-1]--; } line_idle_delay(); msg[0]=FT_ACK;#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0) ftstation.port.filp->f_op->write(ftstation.port.filp,&msg[0],1,&ftstation.port.filp->f_pos);#else ftstation.port.filp->f_op->write(ftstation.port.inodp,ftstation.port.filp,&msg[0],1);#endif do_gettimeofday(&ftstation.last_seract); break; case FT_FIXED_LENGTH_MSG: if (timeout_read(&msg[0],3)!=3) break; if ((msg[0]!=msg[1]) || (msg[2]!=0x16)) break; switch(msg[0] & 0xDF) { case (0x40 | ((1-FT_DIR)<<7)): // SEND_RESET#ifdef DEBUG printk(KERN_WARNING "eibdrv (%i): SEND_RESET ==> erhalten!\n",c++);#endif ftstation.fcb=1; ftstation.rec_fcb=0; ftstation.wrepeat=FT_REPEAT_LIMIT; line_idle_delay(); msg[0]=FT_ACK;#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0) ftstation.port.filp->f_op->write(ftstation.port.filp,&msg[0],1, &ftstation.port.filp->f_pos);#else ftstation.port.filp->f_op->write(ftstation.port.inodp,ftstation.port.filp,&msg[0],1);#endif do_gettimeofday(&ftstation.last_seract); break; case (0x49 | ((1-FT_DIR)<<7)): // REQ_STATUS#ifdef DEBUG printk(KERN_WARNING "eibdrv (%i): REQ_STATUS ==> erhalten!\n",c++);#endif DEBUG line_idle_delay(); msg[0]=0x10; msg[1]=msg[2]=(0x0B | (FT_DIR<<7)); msg[3]=0x16;#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0) ftstation.port.filp->f_op->write(ftstation.port.filp,&msg[0],4, &ftstation.port.filp->f_pos);#else ftstation.port.filp->f_op->write(ftstation.port.inodp,ftstation.port.filp,&msg[0],4);#endif do_gettimeofday(&ftstation.last_seract); break; case (0x0B | ((1-FT_DIR)<<7)): // RESP_STATUS#ifdef DEBUG printk(KERN_WARNING "eibdrv (%i): RESP_STATUS ==> erhalten!\n",c++);#endif if (ftstation.state==FT_STATE_WAIT_FOR_RESP_STATUS) ftstation.state=FT_STATE_READY; break; } break; case FT_ACK: // ACK received if (ftstation.wrepeat==1) ftstation.stat.total_w1time=sum_timeval(ftstation.stat.total_w1time, diff_timeval(ftstation.end_write,ftstation.start_write));#ifdef DEBUG printk(KERN_WARNING "eibdrv (%i): ACK ==> erhalten\n",c++);#endif if ((ftstation.state==FT_STATE_WAIT_FOR_UDATA_ACK) || (ftstation.state==FT_STATE_WAIT_FOR_RESET_ACK)) ftstation.state=FT_STATE_READY; break; } // empty_ttyS(); if ((ftstation.state==FT_STATE_WAIT_FOR_UDATA_ACK) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -