📄 eibdrv.c
字号:
therefore rejected; or 0 otherwise. */ int eib_resize_wpbuf(Eib_wpbuf **buf,unsigned long new_size); /* This function counts the occurences of processes with process-ID pid in the process list. */ unsigned long eib_countinst_wpbuf(Eib_wpbuf *buf,pid_t pid);unsigned long eib_get_wpbuf_count(Eib_wpbuf *buf);unsigned long eib_get_wpbuf_size (Eib_wpbuf *buf);void eib_display_wpbuf(Eib_wpbuf *buf);// for internal use onlyvoid eib_init_wpbuf(Eib_wpbuf *buf);/* =========================================================================== *//* List of read processes *//* =========================================================================== *//* A reference to all processes opening the device is kept in an unordered list, until they close the device. Each process has an individual message buffer, where all unread messages received from the BCU2 are stored. */unsigned long rpbuf_size=30; unsigned long rpbuf_msgbuf_size=10; #if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)MODULE_PARM(rpbuf_size,"l");MODULE_PARM(rpbuf_msgbuf_size,"l");#endiftypedef struct Eib_rproc { struct file *filp; // open device int flags; // type, in use int wmode; // Standard/Acknowledged Write Mode Eib_buf *msgbuf; // message buffer } Eib_rproc;struct Eib_rpbuf { struct Eib_rproc *mem; // start of memory region for slots unsigned long count; // number of open devices unsigned long size; // number of available slots unsigned long msgbuf_size; // number of messages per open device }; /* This function allocates memory for a process list of size elements (slots), which can store a maximum of msgbuf_size messages for each process. The function returns a pointer to the buffer, which is used as parameter for all other function calls regarding the process list, or NULL, if the necessary memory could not be allocated. */Eib_rpbuf *eib_get_rpbuf(unsigned long size,unsigned long msgbuf_size); /* This function deallocates the memory used for a process list and has to be called if the process list is not longer to be used. */void eib_return_buf(Eib_buf *buf); /* This function inserts a process into the first free slot of the process list. flags indicates whether the device is in blocking (FT_PROC_BLOCKED) or nonblocking (FT_PROC_NONBLOCKED) read mode. The function returns -ENOBUFS, if no empty slot in the process list is available, -EDEVISOPEN, if the device has already been opened by this process or 0 otherwise. */int eib_ins_rpbuf(Eib_rpbuf *buf,struct file *filp,int flags); /* This function removes an open process from the process list. The function return -ENOPROC, if the process is not kept in the process list or 0 otherwise. */ int eib_rm_rpbuf(Eib_rpbuf *buf,struct file *filp); /* This function copies len characters (maximum is EIB_BUF_ELEMENT_SIZE) from element into the message buffers of all processes in the process list, if these buffers have empty message slots. The function returns -ENOBUFS, if at least one message buffer is full - although the message is copied into all other message buffers - or 0 otherwise. */ int eib_wmsg_rpbuf(Eib_rpbuf *buf,unsigned char *element,int len); /* This function returns the oldest unread message from the message buffer of a process. The argument element points to a preallocated array of type unsigned character, into which the message is copied. It is safe to choose the size of the array not shorter than EIB_BUF_ELEMENT_SIZE. The functions returns the length of the message or 0, if there is no message available in the buffer or the process is not kept in the process list. */int eib_rmsg_rpbuf(Eib_rpbuf *buf,struct file *filp,unsigned char *element); /* This function resizes the proces list to new_size and/or the message buffers of the processes to new_msgbuf_size. It returns -ENOMEM, if memory cannot be allocated for the new list; -ESIZE, if the new list is too small to hold all entries of the old lists and the resizing is therefore rejected; or 0 otherwise. */int eib_resize_rpbuf(Eib_rpbuf **buf,unsigned long new_size,unsigned long new_msgbuf_size); /* This function returns the number of messages in the buffer for a process or -ENOPROC, if the process is not kept in the process list. */ unsigned long eib_get_rpbuf_msgcount(Eib_rpbuf *buf,struct file *filp);int eib_set_rpbuf_wmode(Eib_rpbuf *buf,struct file *filp,int wmode);int eib_get_rpbuf_wmode(Eib_rpbuf *buf,struct file *filp);void eib_display_rpbuf(Eib_rpbuf *buf);unsigned long eib_get_rpbuf_count(Eib_rpbuf *buf);unsigned long eib_get_rpbuf_size(Eib_rpbuf *buf);unsigned long eib_get_rpbuf_msgbuf_size(Eib_rpbuf *buf);// for internal use onlyvoid eib_init_rpbuf(Eib_rpbuf *pbuf);/* =========================================================================== */Eib_buf *eib_get_buf(unsigned long size){ Eib_buf *buf; buf=(Eib_buf *)kmalloc(sizeof(Eib_buf)+size*(EIB_BUF_ELEMENT_SIZE+1)* sizeof(unsigned char),GFP_KERNEL); if (buf!=NULL) { buf->mem=(unsigned char *)(buf+1); buf->size=size; eib_init_buf(buf); } return buf;}void eib_return_buf(Eib_buf *buf) { kfree(buf); }int eib_read_buf(Eib_buf *buf,unsigned char *element){ int i,len; if (buf->next_read==NULL) return 0; len=(int)*buf->next_read; for (i=0;i<len;i++) *(element+i)=*(buf->next_read+1+i); buf->count--; if (buf->count>0) eib_calc_nextpos_buf(buf,&buf->next_read); else buf->next_read=NULL; return len;}int eib_write_buf(Eib_buf *buf,unsigned char *element,int len){ int i; if (buf->count==buf->size) return -ENOBUFS; if (len>EIB_BUF_ELEMENT_SIZE) len=EIB_BUF_ELEMENT_SIZE; *buf->next_write=(unsigned char)len; for (i=0;i<len;i++) *(buf->next_write+1+i)=*(element+i); buf->count++; if (buf->next_read==NULL) buf->next_read=buf->next_write; eib_calc_nextpos_buf(buf,&buf->next_write); return 0;}void eib_copymem_buf(Eib_buf *old_buf,Eib_buf *new_buf){ unsigned long diff_size; diff_size=new_buf->size-old_buf->size; if (old_buf->next_write>old_buf->next_read) { memcpy(new_buf->mem,old_buf->next_read, (old_buf->next_write-old_buf->next_read)*sizeof(unsigned char)); new_buf->next_read=new_buf->mem; new_buf->next_write=new_buf->mem+(old_buf->next_write-old_buf->next_read); } else // old_buf->next_write <= old_buf->next_read { memcpy(new_buf->mem,old_buf->mem, (old_buf->next_write-old_buf->mem)*sizeof(unsigned char)); memcpy(new_buf->mem+(old_buf->next_read-old_buf->mem+ diff_size*(EIB_BUF_ELEMENT_SIZE+1)*sizeof(unsigned char)), old_buf->next_read, (old_buf->mem+old_buf->size*(EIB_BUF_ELEMENT_SIZE+1)*sizeof(unsigned char))-(old_buf->next_read)); new_buf->next_read= new_buf->mem+(old_buf->next_read-old_buf->mem+(diff_size*(EIB_BUF_ELEMENT_SIZE+1)*sizeof(unsigned char))); new_buf->next_write=new_buf->mem+(old_buf->next_write-old_buf->mem); } new_buf->count=old_buf->count;}int eib_resize_buf(Eib_buf **buf,unsigned long new_size){ Eib_buf *old_buf,*new_buf; if ((new_buf=eib_get_buf(new_size))==NULL) return -ENOMEM; old_buf=(*buf); if (new_size==old_buf->size) { eib_return_buf(new_buf); return 0; } if ((new_size<old_buf->count) || (new_size==0)) { eib_return_buf(new_buf); return -ESIZE; } if (old_buf->count>0) eib_copymem_buf(old_buf,new_buf); eib_return_buf(*buf); *buf=new_buf; return 0;}void eib_calc_nextpos_buf(Eib_buf *buf,unsigned char **nextpos){ if (*nextpos == buf->mem+(buf->size-1)*(EIB_BUF_ELEMENT_SIZE+1)*sizeof(unsigned char)) *nextpos=buf->mem; else *nextpos+=(EIB_BUF_ELEMENT_SIZE+1);}unsigned long eib_get_buf_count(Eib_buf *buf) { return buf->count; }unsigned long eib_get_buf_size(Eib_buf *buf) { return buf->size; }void eib_init_buf(Eib_buf *buf){ buf->next_read=NULL; buf->next_write=buf->mem; buf->count=0;}void eib_display_buf(Eib_buf *buf){ int i,k,len; unsigned long old_count; unsigned char *old_next_read; unsigned char text[EIB_BUF_ELEMENT_SIZE]; old_next_read=buf->next_read; old_count=eib_get_buf_count(buf); for (i=0;i<old_count;i++) { len=eib_read_buf(buf,&text[0]); printk(KERN_WARNING "eibdrv: len = %i ==> ",len); if (len>0) { for (k=0;k<len;k++) printk("%i ",(int)text[k]); } else printk("empty"); printk("\n"); } buf->next_read=old_next_read; buf->count=old_count;}/* --------------------------------------------------------------------------- */Eib_wpbuf *eib_get_wpbuf(unsigned long size){ Eib_wpbuf *buf; buf=(Eib_wpbuf *)kmalloc(sizeof(Eib_wpbuf)+size*sizeof(Eib_wproc),GFP_KERNEL); if (buf!=NULL) { buf->mem=(Eib_wproc *)(buf+1); buf->size=size; eib_init_wpbuf(buf); } return buf;}void eib_return_wpbuf(Eib_wpbuf *buf) { kfree(buf); } int eib_write_wpbuf(Eib_wpbuf *buf,pid_t pid,int flags){ unsigned long i; Eib_wproc *proc; if (buf->count==buf->size) return -ENOBUFS; proc=buf->mem; i=0; while ((proc->pid!=0)||(proc->flags!=0)) { proc++; i++; } proc->pid=pid; proc->flags=flags; proc->prev=buf->last; proc->next=0; if (buf->count==0) buf->first=i+1; else (buf->mem+(buf->last-1))->next=i+1; buf->count++; buf->last=i+1; if (buf->next_result==0) buf->next_result=i+1; return 0;}int eib_condrm_wpbuf(Eib_wpbuf *buf,pid_t pid){ unsigned long i; Eib_wproc *proc; if (buf->count==0) return -ENOPROC; proc=buf->mem+(buf->first-1); i=buf->first; while ((proc->pid!=pid)&&(proc->next!=0)) { i=proc->next; proc=buf->mem+(proc->next-1); } if (proc->pid!=pid) return -ENOPROC; if ((proc->flags&FT_PROC_FREE)==0) return -ENORESULT; if (buf->first==i) buf->first=proc->next; else (buf->mem+(proc->prev-1))->next=proc->next; if (buf->last==i) buf->last=proc->prev; else (buf->mem+(proc->next-1))->prev=proc->prev; proc->pid=0; proc->flags=0; buf->count--; wake_up_interruptible(&wq_fullwproc); return proc->result;}void eib_result_wpbuf(Eib_wpbuf *buf,int result){ Eib_wproc *proc; if (buf->next_result==0) return; proc=buf->mem+(buf->next_result-1); proc->result=result; proc->flags|=FT_PROC_FREE; buf->next_result=proc->next; if ((proc->flags&FT_RMPROC_AUTO)!=0) eib_condrm_wpbuf(buf,proc->pid);}int eib_resize_wpbuf(Eib_wpbuf **buf,unsigned long new_size){ unsigned long i,j; Eib_wproc *proc,*new_proc; Eib_wpbuf *new_buf,*old_buf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -