📄 eibdrv_comm.c
字号:
/* --------------------------------------------------------------------------- eibdrv_comm.c --------------------------------------------------------------------------- eibdrv_comm Version 0.2.1 Copyright (C) 2002, Wolfgang Tumfart Donaustrasse 104/9 A-2344 Maria Enzersdorf Austria (Europe) tumfart@auto.tuwien.ac.at This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. --------------------------------------------------------------------------- *//* --------------------------------------------------------------------------- Dieses Programm stellt eine Oberflaeche zur Kommunikation mit dem EIB- System auf Ebene des FT1.2-Protokolls unter direkter Benutzung des eibdrv-Treibers zur Verfuegung. * Im Read Mode koennen Nachrichten vom eibdrv-Treiber empfangen und in einem Browser dargestellt werden. Das Lesen erfolgt nonblocking. Ist der eibdrv-Treiber im Standard Mode geladen, ist nicht garantiert, dass alle bzw. ueberhaupt irgendwelche Nachrichten von diesem Programm abgefangen werden koennen, wenn noch weitere Applikationen das eib-Device geoeffnet haben und damit der Scheduler bestimmt, welche Applikation eine Nachricht konsumierend abholen kann. Weiters werden im Read-Mode alle empfangenen Nachrichten in die Log-Datei eibdrv_comm.log im Startverzeichnis geschrieben. Start: eibdrv_comm r /dev/eibdrv (Beispiel) * Im Write Mode koennen Nachrichten zusammengestellt werden und an den eibdrv-Treiber uebertragen werden. Das Schreiben erfolgt im Server Mode des Treibers blocking mit Acknowledgement; im StandardMode blocking ohne Bestaetigung. Start: eibdrv_comm w /dev/eibdrv (Beispiel) --------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------- FormsLibrary is copyrighted by T.C. Zhao and Mark Overmars. It is not public domain, but may be used for running publically available free software. --------------------------------------------------------------------------- */#include <stdlib.h>#include <errno.h>#include <fcntl.h>#include <signal.h>#include <time.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/sem.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/time.h>#include "forms.h"#include "eibdrv.h"#include "eibdrv_fl.h"/* Dateiname der Paneldatei fuer eibdrv_comm und Anzahl der darin enthaltenen Panels. */#define EIBDRV_COMM_LOGFILE "eibdrv_comm.log"#define EIBDRV_COMM_PANELFILE "/sbin/eibdrv_comm.panel"#define EIBDRV_COMM_PANELFILESIZE 10#define EIBDRV_COMM_MODE_WRITE 1 // Write Msg to eibdrv driver#define EIBDRV_COMM_MODE_READ 2 // Read Msg from eibdrv driver#define EIBDRV_COMM_STATE_START 0 // Initialising#define EIBDRV_COMM_STATE_READY 1 // Ready for WriteBtn#define EIBDRV_COMM_STATE_WAITWRITE 2 // Waiting for ACK from write-idle#define EIBDRV_COMM_BROWSERMAXLINE 20 // maximal number of lines in msgbrowser#define EIBDRV_COMM_BROWSERDELLINE 5 // number of lines to be deleted/* Struct des Hauptfensters und seiner visuellen Elemente fuer Write und Read Mode. */ typedef struct { FL_FORM *VisForm; void *vdata; char *cdata; long ldata; FL_OBJECT *DeviceText; FL_OBJECT *ModeText; FL_OBJECT *MsgEditfield[EIB_BUF_ELEMENT_SIZE]; FL_OBJECT *SentMsgBrowser; FL_OBJECT *ReceivedMsgBrowser; FL_OBJECT *NewBtn; FL_OBJECT *WriteBtn; FL_OBJECT *StatusBtn; FL_OBJECT *ExitBtn; } FD_VisForm;/* Zentrale Struktur des communicator fuer Write und Read Mode */typedef struct { FD_VisForm *Form; // Visual Form PanelContent *Panels; // all error and message panels int state; // state in write mode int eib_fd; // filedescriptor of eibdrv device FILE *log_fd; // filedescriptor of logfile (read mode) int comm_mode; // read/write mode of communicator int cleanup_code; // entry point in cleanup function } Eib_bcu2_comm;/* Struktur des shared memory segments fuer den Nachrichtenaustausch zwischen communicator process (write mode) und write-idle process, der die Nachricht auf eibdrv schreibt. */typedef struct { size_t len; // length of msg to be written to eibdrv unsigned char msg[EIB_BUF_ELEMENT_SIZE]; // msg ssize_t n_written; // result value of write call } write_shm_struct;Eib_bcu2_comm *comm; // communicator variable; must be global because // of signal handler functionspid_t write_pid=0; // pid of write idle process, forked in write modeint write_shm_id; // ID of shared memory segment for write modewrite_shm_struct *write_shm; // adress of shared memory segmentint write_shm_sem_id; // ID of semaphor guarding shared memory segment // for write mode/* --------------------------------------------------------------------------- Anforderung Freigabe der zentralen Struktur des Communicator --------------------------------------------------------------------------- */ Eib_bcu2_comm *getEib_bcu2_comm(){ Eib_bcu2_comm *help=(Eib_bcu2_comm *)fl_calloc(1,sizeof(Eib_bcu2_comm)); help->Form=NULL; help->Panels=NULL; help->state=EIBDRV_COMM_STATE_START; help->cleanup_code=0; help->log_fd=NULL; help->comm_mode=0; return help;}void returnEib_bcu2_comm(Eib_bcu2_comm *comm){ free(comm->Form); returnPanelContentA(comm->Panels,EIBDRV_COMM_PANELFILESIZE); free(comm);}/* --------------------------------------------------------------------------- Aufbau des Hauptfensters und Callbacks der visuellen Elemente fuer Write und Read Mode. --------------------------------------------------------------------------- */void panel_cb(void *arg,int btn){ ; }void Null_cb(FL_OBJECT *obj,long data){ ; } void NewBtn_cb(FL_OBJECT *obj,long data){ int i; Eib_bcu2_comm *comm=(Eib_bcu2_comm *)obj->form->u_vdata; for (i=0;i<EIB_BUF_ELEMENT_SIZE;i++) fl_set_input(comm->Form->MsgEditfield[i],""); fl_set_focus_object(comm->Form->VisForm,comm->Form->MsgEditfield[i]);}void WriteBtn_cb(FL_OBJECT *obj, long data){ Eib_bcu2_comm *comm=(Eib_bcu2_comm *)obj->form->u_vdata; int len=0; int msg; if (comm->state==EIBDRV_COMM_STATE_READY) { comm->state=EIBDRV_COMM_STATE_WAITWRITE; P(write_shm_sem_id); while ((len<EIB_BUF_ELEMENT_SIZE) && (strlen(fl_get_input(comm->Form->MsgEditfield[len]))>0)) { sscanf(fl_get_input(comm->Form->MsgEditfield[len]),"%x",&(write_shm->msg[len])); len++; } write_shm->len=len; write_shm->n_written=0; V(write_shm_sem_id); kill(write_pid,SIGUSR1); }}void StatusBtn_cb(FL_OBJECT *ob, long data){ int result; if (ioctl(comm->eib_fd,FT_RESP_STATUS)<0) { switch(result=errno) { case ENORESPSTATUS: fl_ext_panel1(comm->Panels+8,comm,panel_cb); break; } } else fl_ext_panel1(comm->Panels+7,comm,panel_cb);}void ExitBtn_cb(FL_OBJECT *obj, long data){ raise(SIGTERM);}FD_VisForm *create_form_VisForm(Eib_bcu2_comm *comm){ int i,height; char string[3]; FL_OBJECT *obj; FD_VisForm *fdui = (FD_VisForm *) fl_calloc(1, sizeof(*fdui)); switch(comm->comm_mode) { case EIBDRV_COMM_MODE_WRITE: height=360; break; case EIBDRV_COMM_MODE_READ: height=255; break; } fdui->VisForm = fl_bgn_form(FL_NO_BOX, 660, height); fl_ext_formobjects_add_box(FL_UP_BOX,0,0,660,height,"", FL_RESIZE_NONE,FL_NorthWest,FL_SouthEast); fl_ext_formobjects_add_box(FL_EMBOSSED_BOX,470,20,170,80,"", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_ext_formobjects_add_text(&obj,FL_NO_BOX,480,25,150,30,"eibdrv_comm", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_object_lcolor(obj,FL_BLUE); fl_set_object_lsize(obj,FL_LARGE_SIZE); fl_set_object_lalign(obj,FL_ALIGN_RIGHT|FL_ALIGN_INSIDE); fl_set_object_lstyle(obj,FL_BOLD_STYLE+FL_EMBOSSED_STYLE); fl_ext_formobjects_add_text(&obj,FL_NO_BOX,520,50,110,20,"Version 0.2.1", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_object_lsize(obj,FL_NORMAL_SIZE); fl_set_object_lalign(obj,FL_ALIGN_RIGHT|FL_ALIGN_INSIDE); fl_set_object_lstyle(obj,FL_BOLD_STYLE); fl_ext_formobjects_add_text(&obj,FL_NO_BOX,510,70,120,20,"(C) Wolfgang Tumfart", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_object_lalign(obj,FL_ALIGN_RIGHT|FL_ALIGN_INSIDE); fl_ext_formobjects_add_labelframe(FL_ENGRAVED_FRAME,20,20,430,80,"Settings", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_ext_formobjects_add_text(&obj,FL_NO_BOX,35,30,40,20,"Device:", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_ext_formobjects_add_text(&fdui->DeviceText,FL_BORDER_BOX,80,30,350,20,"", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_object_lalign(fdui->DeviceText,FL_ALIGN_LEFT|FL_ALIGN_INSIDE); fl_ext_formobjects_add_text(&obj,FL_NO_BOX,35,55,40,20,"Mode:", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_ext_formobjects_add_text(&fdui->ModeText,FL_BORDER_BOX,80,55,350,20,"", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_object_lalign(fdui->ModeText,FL_ALIGN_LEFT|FL_ALIGN_INSIDE); fl_ext_formobjects_add_btn(&fdui->StatusBtn,FL_NORMAL_BUTTON,550,height-80,90,25, "Request Status",FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_object_callback(fdui->StatusBtn,StatusBtn_cb,0); fl_ext_formobjects_add_btn(&fdui->ExitBtn,FL_NORMAL_BUTTON,550,height-45,90,25, "Exit",FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_object_callback(fdui->ExitBtn,ExitBtn_cb,0); switch(comm->comm_mode) { case EIBDRV_COMM_MODE_WRITE: fl_ext_formobjects_add_labelframe(FL_ENGRAVED_FRAME,20,120,510,85,"New Message (Hex)", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); for (i=0;i<EIB_BUF_ELEMENT_SIZE;i++) { sprintf(&string[0],"%i",i+1); fl_ext_formobjects_add_inp(&fdui->MsgEditfield[i],FL_NORMAL_INPUT, 35+40*(i%12),130+35*(i/12),30,20,&string[0],2,FL_RETURN_END_CHANGED, FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_input_filter(fdui->MsgEditfield[i],hex_input_filter); fl_set_object_lalign(fdui->MsgEditfield[i],FL_ALIGN_BOTTOM); fl_set_object_callback(fdui->MsgEditfield[i],Null_cb,i); } fl_ext_formobjects_add_browser(&fdui->SentMsgBrowser,FL_NORMAL_BROWSER, 20,225,510,115,"Sent Messages", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_object_lalign(fdui->SentMsgBrowser,FL_ALIGN_TOP); fl_set_object_callback(fdui->SentMsgBrowser,Null_cb,0); fl_ext_formobjects_add_btn(&fdui->NewBtn,FL_NORMAL_BUTTON,550,145,90,25, "New Message",FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_object_callback(fdui->NewBtn,NewBtn_cb,0); fl_ext_formobjects_add_btn(&fdui->WriteBtn,FL_NORMAL_BUTTON,550,180,90,25, "Write Message",FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_object_callback(fdui->WriteBtn,WriteBtn_cb,0); break; case EIBDRV_COMM_MODE_READ: fl_ext_formobjects_add_browser(&fdui->ReceivedMsgBrowser,FL_NORMAL_BROWSER, 20,120,510,115,"Received Messages", FL_RESIZE_NONE,FL_NorthWest,FL_NorthWest); fl_set_object_lalign(fdui->ReceivedMsgBrowser,FL_ALIGN_TOP); fl_set_object_callback(fdui->ReceivedMsgBrowser,Null_cb,0); break; } fl_end_form(); fdui->VisForm->fdui = fdui; fdui->VisForm->u_vdata=comm; return fdui;}/* --------------------------------------------------------------------------- Funktionen fuer Write und Read Mode. --------------------------------------------------------------------------- */ void cleanup(void *arg,int btn){ /* Rueckgabe der Semaphore, Shared Memory Segmente; Schliessen offener Dateien und Beenden der visuellen Forms, Rueckgabe der zentralen communicator Struktur. Die Funktion wird bei Fehlern im Zuge des Prozessaufbaus sowie beim Eintreffen eines SIGCHLD-Signals bei Beendigung des write idle processes verwendet. */ Eib_bcu2_comm *comm=(Eib_bcu2_comm *)arg; switch(comm->cleanup_code) { case 6: semctl(write_shm_sem_id,0,IPC_RMID,(int)0); case 5: shmdt(write_shm); case 4: shmctl(write_shm_id,IPC_RMID,(int)0); case 3: fl_hide_form(comm->Form->VisForm); fl_free_form(comm->Form->VisForm); case 2: close(comm->eib_fd); case 1: returnEib_bcu2_comm(comm); fl_finish(); exit(3); }}/* --------------------------------------------------------------------------- Funktionen fuer Write Mode. --------------------------------------------------------------------------- */void write_idle_sigterm_handler(){ shmdt(write_shm); exit(1);}void write_idle_sigusr1_handler(){ P(write_shm_sem_id); write_shm->n_written=write(comm->eib_fd,&write_shm->msg[0],write_shm->len); V(write_shm_sem_id); kill(getppid(),SIGUSR1);}void eibdrv_comm_write_idle(){ struct sigaction write_idle_sigterm; struct sigaction write_idle_sigusr1; write_idle_sigterm.sa_handler=write_idle_sigterm_handler; sigfillset(&write_idle_sigterm.sa_mask); write_idle_sigterm.sa_flags=0; if (sigaction(SIGTERM,&write_idle_sigterm,NULL)==-1) exit(2); write_idle_sigusr1.sa_handler=write_idle_sigusr1_handler; sigfillset(&write_idle_sigusr1.sa_mask); write_idle_sigusr1.sa_flags=0; if (sigaction(SIGUSR1,&write_idle_sigusr1,NULL)==-1) exit(2); if ((write_shm=(write_shm_struct *)shmat(write_shm_id,NULL,0))==(void *)-1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -