📄 pcommx.c~
字号:
#include <stdio.h>#include <fcntl.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/stat.h>#include <sys/types.h>#include <linux/pmacisa.h>#include <linux/errno.h>#include <pthread.h>#include "pcommx.h"////////////////////////////defines////////////////////////////////////////#define ISDEVICEOPEN(device)(pmac[device].count)////////////////////////////global variales///////////////////////////////struct Pmac_Comm_Device pmac[PMAC_NO];int devices_found = 0;////////////////////////////functions Implementation//////////////////////int find_pmac_devices(){ int device, result; char pmac_isa_node[14]="/dev/pmacisa0\0"; char pmac_pci_node[14]="/dev/pmacpci0\0"; for(device = 0; device < PMAC_NO; device++){ pmac_isa_node[12] = devnos[device]; if((result=open(pmac_isa_node, O_RDWR)) >= 0){ strncpy(pmac[devices_found].dev_node, pmac_isa_node, 14); //store the /dev entry of device found devices_found++; //found a device close(result); } } for(device = 0; device < PMAC_NO; device++){ pmac_pci_node[12] = devnos[device]; if(devices_found >= PMAC_NO) break; if((result=open(pmac_pci_node, O_RDWR)) >= 0){ strncpy(pmac[devices_found].dev_node, pmac_pci_node, 14); //store the /dev entry of device found devices_found++; //found a device close(result); } } return devices_found;} /*open_pmac_device() tries to open a device if its present in slot and is not in watch dog state. This requires device as integer, provided by calling application and returns 0 for successful operation, else returns a -ve status number. This function opens the device in BUS mode. Along with the close_pmac_device, this function keeps book keeping of the opened devices. */int open_pmac_device(int device){ int result; if(!devices_found) find_pmac_devices(); if(device>PMAC_NO) return -ENODEV; if(pmac[device].count==0){ if((result=open(pmac[device].dev_node, O_RDWR)) < 0) return result; else{ pmac[device].node = result; pmac[device].progress = 0; pmac[device].ascii_mode = BUS; /**default mode is BUS */ } } pmac[device].count++; return 0;} /*close_pmac_device() closes any opened device previously opened by open_pmac_device(). If this device is opened by more than one applications the device will be close only after the last application requests for closing the device.On successful closure the function returns a 0. */int close_pmac_device(int device){ if(pmac[device].count==0) close(pmac[device].node); pmac[device].count--; return 0;}int pmac_download_progress(int device){ return pmac[device].progress;}//////////////////////////////////////////////port functions////////////////////////////////////// /*pmac_bus_get_line() communicates with device through the port. It requires device number as interger and a buffer to store the data sent by the device. On successful operation it returns the number of charcters sent by the device. On any error it returns the -ve number identifying the error. */int pmac_bus_get_line(int device, char *buf){ int result, len=0; if(!ISDEVICEOPEN(device)) return -ENODEV; while(pmac[device].ext.status!=COMM_EOT){ if(pmac[device].ext.status==COMM_ERROR){ pmac[device].read_error = COMM_ERROR; break; } if(pmac[device].ext.status==COMM_TIMEOUT){ pmac_bus_send_line(device, "I3=2 I6=1 I63=1 I64=1"); pmac[device].read_error = COMM_TIMEOUT; break; } result=ioctl(pmac[device].node, IOCTL_MOTION_READLN_PORT, &pmac[device].ext); strncpy(buf+len, pmac[device].ext.buffer, result); len+=result; } buf[len] = NULL_CHR; pmac[device].ext.status = COMM_OK; return len;} /*pmac_bus_send_line() communicates with device through the port. It requires device number as interger and buffered data to be sent to the device. On successful operation it returns 0. On any error it returns the -ve number identifying the error. */int pmac_bus_send_line(int device, char *buf){ if(!ISDEVICEOPEN(device)) return -ENODEV; strncpy(pmac[device].ext.buffer, buf, 256); ioctl(pmac[device].node, IOCTL_MOTION_WRITELN_PORT, &pmac[device].ext); return 0;}//////////////////////////////////////////dpram functions////////////////////////////////////// /*pmac_dpr_get_line() communicates with device through the dpr. It requires device number as interger and a buffer to store the data sent by the pmac. On successful operation it returns the number of charcters sent by the device. On any error it returns the -ve number identifying the error. */int pmac_dpr_get_line(int device, char *buf){ int result, len=0; if(!ISDEVICEOPEN(device)) return -ENODEV; while(pmac[device].ext.status!=COMM_EOT){ if(pmac[device].ext.status==COMM_ERROR){ pmac[device].read_error = COMM_ERROR; break; } if(pmac[device].ext.status==COMM_TIMEOUT){ pmac[device].read_error = COMM_TIMEOUT; break; } result=ioctl(pmac[device].node, IOCTL_MOTION_READLN_MEM, &pmac[device].ext); strncpy(buf+len, pmac[device].ext.buffer, result); len+=result; } buf[len] = NULL_CHR; pmac[device].ext.status = COMM_OK; return len;} /*pmac_dpr_send_line() communicates with device through the dpr. It requires device number as interger and buffered data to be sent to the device. On successful operation it returns 0. On any error it returns the -ve number identifying the error. */int pmac_dpr_send_line(int device, char *buf){ if(!ISDEVICEOPEN(device)) return -ENODEV; strncpy(pmac[device].ext.buffer, buf, 256); ioctl(pmac[device].node, IOCTL_MOTION_WRITELN_MEM, &pmac[device].ext); return 0;}//////////////////////////////////////generic functions//////////////////////////////////////// /*pmac_read_ready() checks whether a particular device is ready to be read. It requires device number as integer of a previously opened device. On successful operation it returns a 0, else a -ve number identifing the error. */int pmac_read_ready(int device){ if(!ISDEVICEOPEN(device)) return -ENODEV; switch(pmac[device].ascii_mode){ case BUS: return ioctl(pmac[device].node, IOCTL_MOTION_PORT_READREADY); break; case DPR: return ioctl(pmac[device].node, IOCTL_MOTION_MEM_READREADY); break; } return 0;} /*pmac_get_line() is the generic function to capture data from the device. It requires the device number as integer and a buffer space to hold the data sent by the device. Based on the previously set mode it either communicates through port or dpr. On successful operation it returns the number of characters read else a -ve number identifing the error. */int pmac_get_line(int device, char *buf){ int result; if(!ISDEVICEOPEN(device)) return -ENODEV; switch(pmac[device].ascii_mode){ case BUS: result = pmac_bus_get_line(device, buf); break; case DPR: result = pmac_dpr_get_line(device, buf); break; } return result;} /*pmac_send_line() is the generic function to send data to the device. It requires the device number as integer and buffered data to be sent to the device. Based on the previously set mode it either communicates through port or dpr. On successful operation it returns the number of characters read else a -ve number identifing the error. */int pmac_send_line(int device, char *buf){ int result; if(!ISDEVICEOPEN(device)) return -ENODEV; switch(pmac[device].ascii_mode){ case BUS: result = pmac_bus_send_line(device, buf); break; case DPR: result = pmac_dpr_send_line(device, buf); break; } return result;} /*pmac_get_response() is the generic function to commnicate with the device. It requires the device number as integer and a buffered data to be sent to the device. It saves the captured data sent by device in the same buffer. Based on the previously set mode it either communicates through port or dpr. On successful operation it returns the number of characters read else a -ve number identifing the error. */int pmac_get_response(int device, char *buf){ if(!ISDEVICEOPEN(device)) return -ENODEV; pmac[device].ext.status = COMM_OK; ioctl(pmac[device].node, IOCTL_MOTION_FLUSH_PORT); ioctl(pmac[device].node, IOCTL_MOTION_FLUSH_MEM); pmac_send_line(device, buf); return pmac_get_line(device, buf);} /*pmac_get_control_response() is the generic function to obtain the the device response of the control characters. It requires the device number as integer and buffered control character(s) to be sent to the device. It saves the captured response by device in the same buffer. Based on the previously set mode it either communicates through port or dpr. On successful operation it returns the number of characters read else a -ve number identifing the error. */int pmac_get_control_response(int device, char *buf){ int result; if(!ISDEVICEOPEN(device)) return -ENODEV; strncpy(pmac[device].ext.buffer, buf, 256); switch(pmac[device].ascii_mode){ case BUS: result = ioctl(pmac[device].node, IOCTL_MOTION_CTRLRESP_PORT, &pmac[device].ext); break; case DPR: result = ioctl(pmac[device].node, IOCTL_MOTION_CTRLRESP_MEM, &pmac[device].ext); break; } if(pmac[device].ext.status!=COMM_EOT) result = pmac_get_line(device, buf); //multiline response e.g ^I and ^E else{ strncpy(buf, pmac[device].ext.buffer, result); buf[result] = NULL_CHR; pmac[device].ext.status = COMM_OK; } return result;} /*pmac_set_ascii_comm() sets the mode of communication of a previously opened device. It requires the device number as integer and mode as ASCII_MODE. The legal values for ASCII_MODE as defined in pcommx.h are BUS and DPR. On successful operation it returns a 0 else a -ve number identifing the error. */int pmac_set_ascii_comm(int device, ASCII_MODE mode){ int i; if(!ISDEVICEOPEN(device)) return -ENODEV; if(mode==DPR){ i = ioctl(pmac[device].node, IOCTL_MOTION_DPRAM); if(i){ pmac_send_line(device, "I58=1"); pmac[device].ascii_mode = DPR; }else{ close_pmac_device(device); return -ENODEV; } }else pmac[device].ascii_mode = BUS; return 0;} /*pmac_download_file() downloads *.pmc file, a text file containing the configuration and motion programs, to the device. It requires device number as integer and a pointer to the file. This function may take time and while executing the application may not respond(A multithreaded version is underprogress). On successful operation it returns ACK else a -ve number identifing he error. */int pmac_download_file(int device, const char *fname){ FILE *fsrc; int nc, lsent=0, result=0, line=0; char instr[256], outstr[256], buf[MAX_COMM_BUFFER + 4]; // +4 to protect stack in case of dpr long flen, fpos; struct stat sbuf; if(!ISDEVICEOPEN(device)) return -ENODEV; if((fsrc = fopen(fname, "rt")) < 0 ) return -ENOENT; if((fstat(fileno(fsrc), &sbuf)) < 0) return; flen = sbuf.st_size; pmac[device].read_error = 0; pmac_send_line(device, "close"); fseek(fsrc, 0, SEEK_SET); while(!feof(fsrc)){ if(lsent){ result = pmac_get_line(device, buf); if(pmac[device].read_error < 0) return; lsent = 0; }else{ fgets(instr, 255, fsrc); nc = 0; while(nc < 256){ if(instr[nc] == '\0' || instr[nc] == ';' || instr[nc] == '\r'|| instr[nc] == '\n') break; else if(CTRL_A <= instr[nc] && instr[nc] <= CTRL_Z) nc++; else outstr[nc] = instr[nc++]; } outstr[nc] = '\0'; if(outstr[0] != '\0'){ pmac_send_line(device, outstr); lsent = 1; } line++; if(line % 5 == 0){ fpos = ftell(fsrc); pmac[device].progress = (int) ((fpos* 100) / flen) ; } } } fclose(fsrc); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -