/* * logical level switch I/O thread */ msg_t thdJbus485IO(void *arg) { (void)arg; chRegSetThreadName("thd JBUS 485 IO"); while (initJbus485 () != TRUE) { chThdSleepMilliseconds(1000); if (chThdShouldTerminate()) goto cleanAndExit; } chThdSleepMilliseconds(10); do { eMBPoll (); } while (!chThdShouldTerminate()); cleanAndExit: eMBDisable (); eMBClose (); DebugTrace ("thdJbusIO 485 Thread Is stopping"); return 0; }
static void *modbus_pollthread(void *pvarg) { eMBErrorCode mberr; int ret; /* Initialize the modbus */ ret = modbus_initialize(); if (ret != OK) { fprintf(stderr, "modbus_main: " "ERROR: modbus_initialize failed: %d\n", ret); return NULL; } srand(time(NULL)); /* Then loop until we are commanded to shutdown */ do { /* Poll */ mberr = eMBPoll(); if (mberr != MB_ENOERR) { break; } /* Generate some random input */ g_modbus.reginput[0] = (uint16_t)rand(); } while (g_modbus.threadstate != SHUTDOWN); /* Disable */ (void)eMBDisable(); /* Release hardware resources. */ (void)eMBClose(); /* Free/uninitialize data structures */ (void)pthread_mutex_destroy(&g_modbus.lock); g_modbus.threadstate = STOPPED; return NULL; }
/* ----------------------- Start implementation -----------------------------*/ int main( void ) { _SetupHardware( ); const UCHAR ucSlaveID[] = { 0xAA, 0xBB, 0xCC }; eMBErrorCode eStatus; for( ;; ) { if( MB_ENOERR != ( eStatus = eMBInit( MB_RTU, 0x0A, 1, 38400, MB_PAR_EVEN ) ) ) { /* Can not initialize. Add error handling code here. */ } else { if( MB_ENOERR != ( eStatus = eMBSetSlaveID( 0x34, TRUE, ucSlaveID, 3 ) ) ) { /* Can not set slave id. Check arguments */ } else if( MB_ENOERR != ( eStatus = eMBEnable( ) ) ) { /* Enable failed. */ } else { usRegHoldingBuf[0] = 1; do { ( void )eMBPoll( ); /* Here we simply count the number of poll cycles. */ usRegInputBuf[0]++; } while( usRegHoldingBuf[0] ); ( void )eMBDisable( ); ( void )eMBClose( ); } } } return 1; }
static void vTaskMODBUS( void *pvArg ) { const UCHAR ucSlaveID[] = { 0xAA, 0xBB, 0xCC }; eMBErrorCode eStatus; for( ;; ) { if( MB_ENOERR != ( eStatus = eMBInit( MB_ASCII, 0x0A, 1, 38400, MB_PAR_EVEN ) ) ) { /* Can not initialize. Add error handling code here. */ } else { if( MB_ENOERR != ( eStatus = eMBSetSlaveID( 0x34, TRUE, ucSlaveID, 3 ) ) ) { /* Can not set slave id. Check arguments */ } else if( MB_ENOERR != ( eStatus = eMBEnable( ) ) ) { /* Enable failed. */ } else { usRegHoldingBuf[0] = 1; do { ( void )eMBPoll( ); /* Here we simply count the number of poll cycles. */ usRegInputBuf[0]++; } while( usRegHoldingBuf[0] ); } ( void )eMBDisable( ); ( void )eMBClose( ); } vTaskDelay( 50 ); } }
int main( int argc, char *argv[] ) { int c; int option_index = 0; int received; int mq_id; struct sIPCMsg mymsg; char *ttydev = DEFAULT_TTY; char *parity_s = DEFAULT_PAR; int parity; int baud = DEFAULT_BAUD; USHORT result[255] = {0,}; int result_int = 0; USHORT usLen; eMBErrorCode err = MB_ENOERR; int reg_start = DEFAULT_REGISTER_START; int address = DEFAULT_ADDRESS; int regt = -1; int reg_action = -1; int reg_action_param = -1; int no_reg = -1; int run_forground = 0; int errorcount = 0; struct pidfile *pidfile = NULL; UCHAR *pucFrame; eMBException eException; UCHAR ucFuncType; /* Parse cmd-line options */ while ( (c = getopt_long (argc, argv, "hVd:s:p:r:t:c:a:f", long_options, &option_index)) != EOF ) { switch (c) { case 'h': fprintf(stderr, "%s", helptext); exit(EXIT_SUCCESS); case 'V': exit(EXIT_SUCCESS); case 'd': ttydev = strndup(optarg, MAXLEN); break; case 's': baud = atoi(optarg); break; case 'p': parity_s = strndup(optarg, MAXLEN); break; case 'f': // run in forground run_forground = 1; break; case '?': /* getopt_long already printed an error message. */ default: fprintf(stderr, "%s", helptext); exit(EXIT_SUCCESS); } } if(!run_forground){ fprintf(stderr, "Deamonizing...\n"); daemon(0, 0); } /* Setup signalhandler so that we shut down nicely on CTRL+C */ signal(SIGINT, int_handler); pidfile = pidfile_create(DEFAULT_PIDFILE, PMODE_RETURN, 0); mq_id = create_ipc(); /* Allocate space for an ADU frame */ pucFrame = eMBAllocateFrame(&usLen); while(outer_loop) { if(running == 1) printf("Restarting modbus layer\n"); else { printf("\n\n\n\n Restarting modbus layer\n\n\n\n"); running = 1; errorcount = 0; } /* Parse user inputs... */ if(strcmp(parity_s, "even") == 0) parity = MB_PAR_EVEN; else if(strcmp(parity_s, "odd") == 0) parity = MB_PAR_ODD; else parity = MB_PAR_NONE; PRINT_DBG(1, "init modbus at tty: %s parity %d baud %d", ttydev, parity, baud); /* mode, port, baud, parity */ eMBMasterInit(MB_RTU, ttydev, baud, parity); while(running) { /* Check message queue */ if((received = msgrcv(mq_id, &mymsg, sizeof(mymsg.text), 1, IPC_NOWAIT)) > 0) { /* Address */ address = parse_address(mymsg.text); /* Starting register */ reg_start = parse_reg_start(mymsg.text); /* Register type */ regt = parse_reg_type(mymsg.text); /* Register action */ reg_action_param = 0; reg_action = parse_reg_action(mymsg.text, ®_action_param); /* Optional: number of registers */ no_reg = parse_no_reg(mymsg.text); #ifdef DBG if(dbglev>=1){ printf("Got: %s\n", mymsg.text); printf("Parsing command:\n"); printf("Address: 0x%02x\n", address); printf("Register: %d\n", reg_start); printf("Register type: %d\n", regt); printf("Register action: %d Arg: %d\n", reg_action, reg_action_param); printf("Register count: %d\n", no_reg); } #endif switch(regt) { case MB_TYPE_COILS: switch(reg_action) { case ACTION_READ: err = build_eMBMasterReadCoils (pucFrame, reg_start, reg_action_param, &usLen); break; case ACTION_WRITE: err = build_eMBMasterWriteCoils (pucFrame, reg_start, reg_action_param ? 0xff : 0x0, &usLen); break; case ACTION_WRITEMULTIPLE: err = build_eMBMasterWriteMultipleCoils (pucFrame, reg_start, no_reg, reg_action_param ? 0xff : 0x0, &usLen); break; } break; case MB_TYPE_INPUT: err = build_eMBMasterReadInput (pucFrame, reg_start, reg_action_param, &usLen); break; case MB_TYPE_HOLDING: switch(reg_action) { case ACTION_READ: err = build_eMBMasterReadHolding (pucFrame, reg_start, reg_action_param, &usLen); break; case ACTION_WRITE: err = build_eMBMasterWriteSingleHolding (pucFrame, reg_start, reg_action_param, &usLen); break; } break; } #ifdef DBG if(dbglev){ int n; printf("Dumping built frame:\n"); for(n=0; n<10; n++) printf("%02x ",pucFrame[n]); printf("\n"); } #endif /* ? */ eMBEnable(); memset(result, 0, sizeof(result)); if(err == MB_EX_NONE) { /* Set the address of the device in question */ eMBSetSlaveAddress(address); /* Send the frame */ if( (err = eMBSendFrame(pucFrame, usLen)) == MB_ENOERR) { printf(" ---- done processing frame ----\n"); eException = MB_EX_ILLEGAL_FUNCTION; ucFuncType = pucFrame[MB_PDU_FUNC_OFF]; #ifdef DBG if(dbglev){ printf("%s():%d - after send...\n", __FUNCTION__, __LINE__); { int n; printf("Dumping received frame:\n"); for(n=0; n<10; n++) printf("%02x ",pucFrame[n]); printf("\n"); } } #endif if(ucFuncType & 0x80) { UCHAR ucExceptType = pucFrame[MB_PDU_FUNC_OFF+1]; /* We encountered some sort of error */ switch(ucExceptType) { case MB_EX_ILLEGAL_FUNCTION: fprintf(stderr, "Error! Illegal function!\n"); break; case MB_EX_ILLEGAL_DATA_ADDRESS: fprintf(stderr, "Error! Illegal data address!\n"); break; case MB_EX_ILLEGAL_DATA_VALUE: fprintf(stderr, "Error! Illegal data value!\n"); break; case MB_EX_SLAVE_DEVICE_FAILURE: fprintf(stderr, "Error! Slave device failure!\n"); break; default: fprintf(stderr, "Unknown error (%d)!\n", eException); break; } } else { switch(ucFuncType) { case MB_FUNC_READ_COILS: eException = parse_eMBMasterReadCoils(pucFrame, &usLen, (void *)result); #ifdef DBG if(dbglev) printf("Reply: %04x\n", result[0]); #endif break; case MB_FUNC_WRITE_SINGLE_COIL: eException = parse_eMBMasterWriteCoils(pucFrame, &usLen, (void *)result); #ifdef DBG if(dbglev) printf("Reply: %04x\n", result[0]); #endif break; case MB_FUNC_READ_INPUT_REGISTER: eException = parse_eMBMasterReadInput(pucFrame, &usLen, (void *)result); #ifdef DBG if(dbglev) printf("Reply (%d): %04x\n", eException, result[0]); #endif break; case MB_FUNC_READ_HOLDING_REGISTER: eException = parse_eMBMasterReadHolding(pucFrame, &usLen, (void *)result); #ifdef DBG printf("Reply: %04x %04x %d %d\n", result[0],result[1], result_int, reg_action_param); #endif break; case MB_FUNC_WRITE_REGISTER: eException = parse_eMBMasterWriteSingleHolding(pucFrame, &usLen, (void *)result); #ifdef DBG printf("Reply: %04x\n", result[0]); #endif break; case MB_FUNC_WRITE_MULTIPLE_COILS: usLen = 5; eException = parse_eMBMasterWriteMultipleCoils(pucFrame, &usLen, (void *)result); if(eException == MB_EX_NONE) printf("Write multiple coils SUCCESS!\n"); else printf("Write multiple coils FAIL!\n"); break; default: printf("Unknown function type : %x\n", ucFuncType); printf("%d : %s()\n", __LINE__, __FUNCTION__); { int n; for(n=0; n<10; n++) printf("%02x ",pucFrame[n]); printf("\n"); } break; } switch(ucFuncType) { case MB_FUNC_READ_HOLDING_REGISTER: case MB_FUNC_READ_INPUT_REGISTER: if(reg_action_param == 2){ printf("!!!!\n"); result_int = (result[0]<<16) | result[1]; }else { result_int = result[0]; } break; default: result_int = result[0]; break; } if(eException == MB_EX_NONE) { snprintf(mymsg.text, sizeof(mymsg.text), "%ld:REG:%d:RESULT:%d", time(NULL), reg_start, result_int); } else { snprintf(mymsg.text, sizeof(mymsg.text), "ERROR:Parsing frame"); } #ifdef DBG printf("%s():%d - reply: %s\n", __FUNCTION__, __LINE__, mymsg.text); #endif goto out; } } else { printf("Error sending frame. (%d)\n", err); snprintf(mymsg.text, sizeof(mymsg.text), "ERROR:Sending frame"); if(errorcount > 10) running = 0; else errorcount++; } } else { printf("Error in frame arguments.\n"); snprintf(mymsg.text, sizeof(mymsg.text), "ERROR:Wrong argument"); } out: /* Set the reply */ mymsg.type = 2; #ifdef DBG printf("%s():%d - reply: %s\n", __FUNCTION__, __LINE__, mymsg.text); #endif msgsnd(mq_id, &mymsg, sizeof(mymsg.text), IPC_NOWAIT); eMBDisable(); } else { //printf("No messages. Sleeping (%d - %s)\n", received, received < 0 ? strerror(errno) : ""); } usleep(1000); } // free(pucFrame); eMBClose(); } destroy_ipc(PROJ_ID); pidfile_delete(pidfile); return 0; }
/** * Main entry point for Program Utility. * * Process option flags and execute commands. * * @param argc * @param argv * @return */ int main( int argc, char *argv[] ) { int iExitCode = EXIT_SUCCESS; UCHAR ucMBAddr = 1; ULONG ulOptFlags = 0; UCHAR ucBank = 0; UCHAR ucStartThread = FALSE; CHAR *pucVersion; UCHAR ucStatus; int c; int timeout; char *infile = NULL; char *outfile = NULL; char *endptr; opterr = 0; ucPort = 2; /* Default to first USB serial dongle */ printf("Secure Bootloader Program Utility\n\n"); /* * Process command line options */ while ((c = getopt(argc, argv, "a:b:ce:fklp:s:uvDV")) != -1) { switch (c) { case 'a': ulOptFlags |= FLAG_ADD_HEADER; pucVersion = optarg; break; case 'b': ucBank = strtoul(optarg, NULL, 0); break; case 'c': ulOptFlags |= FLAG_CHECK_HEADER; break; case 'e': ulOptFlags |= FLAG_ENCRYPT; pBlowfishKeyString = optarg; break; case 'f': ulOptFlags |= FLAG_LOCK_FILE; ucBank = BANK_F; ucStartThread = TRUE; break; case 'k': ulOptFlags |= FLAG_CREATE_KEYFILE; break; case 'l': ulOptFlags |= FLAG_LOCK_FILE; ucBank = BANK_BOOT; ucStartThread = TRUE; break; case 'p': ucPort = strtoul(optarg, &endptr, 0); /* If argument is not a pure number, it must be a string */ if (endptr) { ucPort = 255; devString = optarg; } break; case 's': ulOptFlags |= FLAG_SIGN; pRSAKeyFile = optarg; break; case 'u': ulOptFlags |= FLAG_UPLOAD; ucStartThread = TRUE; break; case 'v': ulOptFlags |= FLAG_GET_VERSION; ucStartThread = TRUE; break; case 'D': debugflags = 1; break; case 'V': ulOptFlags |= FLAG_VALIDATE; ucStartThread = TRUE; break; case '?': if (optopt == 'v') fprintf(stderr, "Option -%c requires an argument.\n", optopt); else if (isprint(optopt)) fprintf(stderr, "Unknown option `-%c'.\n", optopt); else fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt); return 1; default: abort(); break; } } if (optind < argc) { infile = argv[optind++]; } if (optind < argc) { outfile = argv[optind++]; } if (argc < 2) { print_usage(); } if ((ulOptFlags & FLAG_ADD_HEADER) && (ulOptFlags & FLAG_CREATE_KEYFILE)) { printf("Error: cannot specify both -a and -k options\n"); abort(); } if ((ulOptFlags & FLAG_CREATE_KEYFILE) && (infile == 0)) { /* Request to upload keyfile */ ucStartThread = TRUE; } /* * Enable signal handlers */ if( !bSetSignal( SIGQUIT, vSigShutdown ) || !bSetSignal( SIGINT, vSigShutdown ) || !bSetSignal( SIGTERM, vSigShutdown ) ) { fprintf( stderr, "%s: can't install signal handlers: %s!\n", PROG, strerror( errno ) ); iExitCode = EXIT_FAILURE; } else if (ucStartThread) { DEBUG_PUTSTRING("Starting MobBus thread"); if( eMBInit( MB_RTU, 0x0A, ucPort, 115200, MB_PAR_EVEN ) != MB_ENOERR ) { fprintf( stderr, "%s: can't initialize modbus stack!\n", PROG ); iExitCode = EXIT_FAILURE; } else { /* Register Callbacks */ (void)eMBRegisterCB(MB_FUNC_BOOT_GETHEADER, cmd_getheader_callback); (void)eMBRegisterCB(MB_FUNC_BOOT_PREPAREFLASH, cmd_prepareflash_callback); (void)eMBRegisterCB(MB_FUNC_BOOT_UPLOADBLOCK, cmd_uploadblock_callback); (void)eMBRegisterCB(MB_FUNC_BOOT_VALIDATEIMAGE, cmd_validatesig_callback); (void)eMBRegisterCB(MB_FUNC_BOOT_SETKEYS, cmd_setkeys_callback); (void)eMBRegisterCB(MB_FUNC_BOOT_LOCK, cmd_lockfile_callback); (void)eMBRegisterIllegalFuncCB(cmd_illegalfunc_callback); (void)eMBRegisterTimeoutCB( cmd_timeout_callback ); /* Start polling thread */ vSetPollingThreadState(STOPPED); if (bCreatePollingThread() != TRUE) { printf("Can't start protocol stack! Already running?\n"); } //vMBPortTimersEnable( ); } } if (iExitCode == EXIT_SUCCESS) { vSetPollingThreadState(RUNNING); /* Process commands and options */ if (ulOptFlags & FLAG_GET_VERSION) { timeout = 10; ucStatus = cmd_getheader(ucMBAddr, ucBank); while ((ucStatus == BOOT_TIMEOUT) && (--timeout)) { ucStatus = cmd_getheader(ucMBAddr, ucBank); } if ((ucStatus != BOOT_OK) && (ucStatus != BOOT_BANKEMPTY)) { fprintf(stderr, "Get Version Failed: %s", cmd_errorString(ucStatus)); } } else if (ulOptFlags & FLAG_UPLOAD) { if (infile) { util_upload(ucMBAddr, infile, ucBank); } else { fprintf(stderr, "Upload: missing filename\n"); } } else if (ulOptFlags & FLAG_ADD_HEADER) { if (infile && outfile) { util_addheader(infile, outfile, pucVersion, pRSAKeyFile, pBlowfishKeyString); } else { fprintf(stderr, "Add Header: missing filenames\n"); } } else if (ulOptFlags & FLAG_CREATE_KEYFILE) { util_createkeyfile(ucMBAddr, infile, pRSAKeyFile, pBlowfishKeyString); } else if (ulOptFlags & FLAG_LOCK_FILE) { timeout = 10; ucStatus = cmd_lockfile(ucMBAddr, ucBank); while ((ucStatus == BOOT_TIMEOUT) && (--timeout)) { ucStatus = cmd_lockfile(ucMBAddr, ucBank); } if (ucStatus != BOOT_OK) { fprintf(stderr, "Lock Failed: %s", cmd_errorString(ucStatus)); } else { printf("Lock Successful\n"); } } if (ulOptFlags & FLAG_CHECK_HEADER) { if (infile) { util_checkheader(infile); } else { fprintf(stderr, "Check Header: missing filename\n"); } } if (ulOptFlags & FLAG_VALIDATE) { cmd_validatesig(ucMBAddr); } /* Release hardware resources. */ if (ucStartThread) { ( void )eMBClose( ); } iExitCode = EXIT_SUCCESS; } return iExitCode; }
/* ----------------------- Start implementation -----------------------------*/ int _tmain( int argc, _TCHAR * argv[] ) { int iExitCode; TCHAR cCh; BOOL bDoExit; for (int Num = REG_INPUT_NREGS; Num >= 0; Num--) { usRegInputBuf[Num] = Num; } for (int Num = INPUT_STATUS_NREGS; Num >= 0; Num--) { ucInputStatusBuf[Num] = 1; } ucInputStatusBuf[0] = 255; for (int Num = 0; Num < REG_HOLDING_NREGS; Num++) { usRegHoldingBuf[Num] = Num; } for (int Num = 0; Num < INPUT_COIL_NREGS; Num++) { ucInputCoilBuf[Num] = 0; } ucInputCoilBuf[0] = 255; if( eMBTCPInit( MB_TCP_PORT_USE_DEFAULT ) != MB_ENOERR ) { _ftprintf( stderr, _T( "%s: can't initialize modbus stack!\r\n" ), PROG ); iExitCode = EXIT_FAILURE; } else { /* Create synchronization primitives and set the current state * of the thread to STOPPED. */ InitializeCriticalSection( &hPollLock ); eSetPollingThreadState( STOPPED ); /* CLI interface. */ _tprintf( _T( "Type 'q' for quit or 'h' for help!\r\n" ) ); bDoExit = FALSE; do { _tprintf( _T( "> " ) ); cCh = _gettchar( ); switch ( cCh ) { case _TCHAR( 'q' ): bDoExit = TRUE; break; case _TCHAR( 'd' ): eSetPollingThreadState( SHUTDOWN ); break; case _TCHAR( 'e' ): if( bCreatePollingThread( ) != TRUE ) { _tprintf( _T( "Can't start protocol stack! Already running?\r\n" ) ); } break; case _TCHAR( 's' ): switch ( eGetPollingThreadState( ) ) { case RUNNING: _tprintf( _T( "Protocol stack is running.\r\n" ) ); break; case STOPPED: _tprintf( _T( "Protocol stack is stopped.\r\n" ) ); break; case SHUTDOWN: _tprintf( _T( "Protocol stack is shuting down.\r\n" ) ); break; } break; case _TCHAR( 'h' ): _tprintf( _T( "FreeModbus demo application help:\r\n" ) ); _tprintf( _T( " 'd' ... disable protocol stack.\r\n" ) ); _tprintf( _T( " 'e' ... enabled the protocol stack\r\n" ) ); _tprintf( _T( " 's' ... show current status\r\n" ) ); _tprintf( _T( " 'q' ... quit applicationr\r\n" ) ); _tprintf( _T( " 'h' ... this information\r\n" ) ); _tprintf( _T( "\r\n" ) ); _tprintf( _T( "Copyright 2006 Christian Walter <*****@*****.**>\r\n" ) ); break; default: if( cCh != _TCHAR('\n') ) { _tprintf( _T( "illegal command '%c'!\r\n" ), cCh ); } break; } /* eat up everything untill return character. */ while( cCh != '\n' ) { cCh = _gettchar( ); } } while( !bDoExit ); /* Release hardware resources. */ ( void )eMBClose( ); iExitCode = EXIT_SUCCESS; } return iExitCode; }
static inline int modbus_initialize(void) { eMBErrorCode mberr; int status; /* Verify that we are in the stopped state */ if (g_modbus.threadstate != STOPPED) { fprintf(stderr, "modbus_main: " "ERROR: Bad state: %d\n", g_modbus.threadstate); return EINVAL; } /* Initialize the ModBus demo data structures */ status = pthread_mutex_init(&g_modbus.lock, NULL); if (status != 0) { fprintf(stderr, "modbus_main: " "ERROR: pthread_mutex_init failed: %d\n", status); return status; } status = ENODEV; /* Initialize the FreeModBus library. * * MB_RTU = RTU mode * 0x0a = Slave address * CONFIG_EXAMPLES_MODBUS_PORT = port, default=0 (i.e., /dev/ttyS0) * CONFIG_EXAMPLES_MODBUS_BAUD = baud, default=B38400 * CONFIG_EXAMPLES_MODBUS_PARITY = parity, default=MB_PAR_EVEN */ mberr = eMBInit(MB_RTU, 0x0a, CONFIG_EXAMPLES_MODBUS_PORT, CONFIG_EXAMPLES_MODBUS_BAUD, CONFIG_EXAMPLES_MODBUS_PARITY); if (mberr != MB_ENOERR) { fprintf(stderr, "modbus_main: " "ERROR: eMBInit failed: %d\n", mberr); goto errout_with_mutex; } /* Set the slave ID * * 0x34 = Slave ID * true = Is running (run indicator status = 0xff) * g_slaveid = Additional values to be returned with the slave ID * 3 = Length of additional values (in bytes) */ mberr = eMBSetSlaveID(0x34, true, g_slaveid, 3); if (mberr != MB_ENOERR) { fprintf(stderr, "modbus_main: " "ERROR: eMBSetSlaveID failed: %d\n", mberr); goto errout_with_modbus; } /* Enable FreeModBus */ mberr = eMBEnable(); if (mberr != MB_ENOERR) { fprintf(stderr, "modbus_main: " "ERROR: eMBEnable failed: %d\n", mberr); goto errout_with_modbus; } /* Successfully initialized */ g_modbus.threadstate = RUNNING; return OK; errout_with_modbus: /* Release hardware resources. */ (void)eMBClose(); errout_with_mutex: /* Free/uninitialize data structures */ (void)pthread_mutex_destroy(&g_modbus.lock); g_modbus.threadstate = STOPPED; return status; }
int main( int argc, char *argv[] ) { int c; int option_index = 0; char *ttydev = DEFAULT_TTY; char *parity_s = DEFAULT_PAR; int parity; int baud = DEFAULT_BAUD; int reg_start = DEFAULT_REGISTER_START; int address = DEFAULT_ADDRESS; char *reg_type = NULL; int regt = -1; char *reg_action = NULL; USHORT usLen; UCHAR *pucFrame; eMBErrorCode err = MB_ENOERR; /* Parse cmd-line options */ while ( (c = getopt_long (argc, argv, "hVd:s:p:r:t:c:a:", long_options, &option_index)) != EOF ) { switch (c) { case 'h': fprintf(stderr, "%s", helptext); exit(EXIT_SUCCESS); case 'V': exit(EXIT_SUCCESS); case 'd': ttydev = strndup(optarg, MAXLEN); break; case 's': baud = atoi(optarg); break; case 'p': parity_s = strndup(optarg, MAXLEN); break; case 'r': reg_start = (int)strtod(optarg, NULL); break; case 't': reg_type = strndup(optarg, MAXLEN); break; case 'c': reg_action = strndup(optarg, MAXLEN); break; case 'a': address = (int)strtod(optarg, NULL); break; case '?': /* getopt_long already printed an error message. */ default: fprintf(stderr, "%s", helptext); exit(EXIT_SUCCESS); } } if(argc <= 1) { fprintf(stderr, "%s", helptext); exit(EXIT_FAILURE); } /* Allocate space for an ADU frame */ pucFrame = eMBAllocateFrame(&usLen); /* Parse user inputs... */ if(strcmp(parity_s, "even") == 0) parity = MB_PAR_EVEN; else if(strcmp(parity_s, "odd") == 0) parity = MB_PAR_ODD; else parity = MB_PAR_NONE; if(reg_start < 0 || reg_start > 0xffff) { fprintf(stderr, "Error! Modbus register out of range. Must be within (0x0-0xffff)\n"); exit(EXIT_FAILURE); } if(reg_type) { if(strcmp(reg_type, "coils" ) == 0) { regt = MB_TYPE_COILS; } else if(strcmp(reg_type, "input" ) == 0) { regt = MB_TYPE_INPUT; } else if(strcmp(reg_type, "holding" ) == 0) { regt = MB_TYPE_HOLDING; } else if(strcmp(reg_type, "slaveid" ) == 0) { regt = MB_TYPE_SLAVEID; build_eMBMasterGetSlaveID (pucFrame, &usLen); } else { fprintf(stderr, "Error! Unknown register type (%s). Known types are: coils\n", reg_type); exit(EXIT_FAILURE); } } else { fprintf(stderr, "Error! No register type (-t) specified\n"); exit(EXIT_FAILURE); } if(reg_action) { if(regt == MB_TYPE_COILS) { if(strncmp(reg_action, "read", 4) == 0) { int val; if(sscanf(reg_action, "%*s %i", &val) != 1) { fprintf(stderr, "Error! No number of coils specified.\n"); exit(EXIT_FAILURE); } if(val%8 == 0) { build_eMBMasterReadCoils (pucFrame, reg_start, val, &usLen); } else { fprintf(stderr, "Error! Invalid coil value (%d). Must be a multiple of 8.\n", val); exit(EXIT_FAILURE); } } else if(strncmp(reg_action, "writesingle", 11) == 0) { char buf[4]; if(sscanf(reg_action, "%*s %3[FNO]", buf) != 1) { fprintf(stderr, "Error! No coil value specified (ON/OFF).\n"); exit(EXIT_FAILURE); } if(strcmp(buf, "ON") == 0) build_eMBMasterWriteCoils (pucFrame, reg_start, 0xff, &usLen); else build_eMBMasterWriteCoils (pucFrame, reg_start, 0x0, &usLen); } else if(strncmp(reg_action, "writemultiple", 13) == 0) { int no; char buf[4]; if( sscanf(reg_action, "%*s %i %3[FNO]", &no, buf) != 2) { fprintf(stderr, "Error! Invalid value specified.\n"); exit(EXIT_FAILURE); } if(strcmp(buf, "ON") == 0) build_eMBMasterWriteMultipleCoils (pucFrame, reg_start, no, 0xff, &usLen); else build_eMBMasterWriteMultipleCoils (pucFrame, reg_start, no, 0x0, &usLen); } else { fprintf(stderr, "Error! Unknown command type (%s).\n", reg_action); exit(EXIT_FAILURE); } } else if(regt == MB_TYPE_INPUT) { if(strncmp(reg_action, "read", 4) == 0) { int val; if(sscanf(reg_action, "%*s %i", &val) != 1) { fprintf(stderr, "Error! No number of registers specified.\n"); exit(EXIT_FAILURE); } if(build_eMBMasterReadInput (pucFrame, reg_start, val, &usLen) != MB_ENOERR) { fprintf(stderr, "Error! Wrong register count. Must be between 1 and 125 (0x7d)\n"); exit(EXIT_FAILURE); } } } else if(regt == MB_TYPE_HOLDING) { if(strncmp(reg_action, "read", 4) == 0) { int val; if(sscanf(reg_action, "%*s %i", &val) != 1) { fprintf(stderr, "Error! No number of registers specified.\n"); exit(EXIT_FAILURE); } if(build_eMBMasterReadHolding (pucFrame, reg_start, val, &usLen) != MB_ENOERR) { fprintf(stderr, "Error! Wrong register count. Must be between 1 and 125 (0x7d)\n"); exit(EXIT_FAILURE); } printf("%s():%d - build_eMBMasterReadHolding(pucFramem, %d, %d, %d)\n", __FUNCTION__, __LINE__, reg_start, val, usLen); } else if(strncmp(reg_action, "writesingle", 11) == 0) { int val; if( sscanf(reg_action, "%*s %i", &val) != 1) { fprintf(stderr, "Error! Invalid value specified.\n"); exit(EXIT_FAILURE); } if(build_eMBMasterWriteSingleHolding (pucFrame, reg_start, val, &usLen) != MB_ENOERR) { fprintf(stderr, "Error!\n"); exit(EXIT_FAILURE); } } } } else { fprintf(stderr, "Error! No command (-c) specified.\n"); exit(EXIT_FAILURE); } /* mode, port, baud, parity */ eMBMasterInit(MB_RTU, ttydev, baud, parity); /* ? */ eMBEnable(); /* Set the address of the device in question */ eMBSetSlaveAddress(address); /* Send the frame */ if( (err = eMBSendFrame(pucFrame, usLen)) != MB_ENOERR) { printf("Error sending frame (%d).\n", err); exit(EXIT_FAILURE); } eMBException eException; eException = MB_EX_ILLEGAL_FUNCTION; UCHAR ucFuncType = pucFrame[MB_PDU_FUNC_OFF]; USHORT retval[255]; if(ucFuncType & 0x80) { UCHAR ucExceptType = pucFrame[MB_PDU_FUNC_OFF+1]; /* We encountered some sort of error */ switch(ucExceptType) { case MB_EX_ILLEGAL_FUNCTION: fprintf(stderr, "Error! Illegal function!\n"); break; case MB_EX_ILLEGAL_DATA_ADDRESS: fprintf(stderr, "Error! Illegal data address!\n"); break; case MB_EX_ILLEGAL_DATA_VALUE: fprintf(stderr, "Error! Illegal data value!\n"); break; case MB_EX_SLAVE_DEVICE_FAILURE: fprintf(stderr, "Error! Slave device failure!\n"); break; default: fprintf(stderr, "Unknown error (%d)!\n", eException); break; } } else { switch(ucFuncType) { case MB_FUNC_READ_COILS: eException = parse_eMBMasterReadCoils(pucFrame, &usLen, (void *)retval); printf("Reply: %04x\n", retval[0]); break; case MB_FUNC_WRITE_SINGLE_COIL: eException = parse_eMBMasterWriteCoils(pucFrame, &usLen, (void *)retval); printf("Reply: %04x\n", retval[0]); break; case MB_FUNC_READ_INPUT_REGISTER: eException = parse_eMBMasterReadInput(pucFrame, &usLen, (void *)retval); printf("Reply (%d): %04x\n", eException, retval[0]); break; case MB_FUNC_READ_HOLDING_REGISTER: eException = parse_eMBMasterReadHolding(pucFrame, &usLen, (void *)retval); printf("Reply: %04x\n", retval[0]); break; case MB_FUNC_WRITE_REGISTER: eException = parse_eMBMasterWriteSingleHolding(pucFrame, &usLen, (void *)retval); printf("Reply: %04x\n", retval[0]); break; case MB_FUNC_WRITE_MULTIPLE_COILS: usLen = 5; eException = parse_eMBMasterWriteMultipleCoils(pucFrame, &usLen, (void *)retval); if(eException == MB_EX_NONE) printf("Write multiple coils SUCCESS!\n"); else printf("Write multiple coils FAIL!\n"); break; default: printf("Unknown function type : %x\n", ucFuncType); printf("%d : %s()\n", __LINE__, __FUNCTION__); { int n; for(n=0; n<10; n++) printf("%02x ",pucFrame[n]); printf("\n"); } break; } } #ifdef DBG printf("%d : %s()\n", __LINE__, __FUNCTION__); { int j; for(j=0; j<usLen; j++) printf("%02x ", pucFrame[j]); printf("\n"); } #endif eMBClose(); return 0; }