Example #1
0
void dlmstp_init(
    void)
{
    uint8_t data;

    /* initialize buffer */
    Receive_Buffer.ready = false;
    Receive_Buffer.pdu_len = 0;
    /* initialize hardware */
    RS485_Initialize();
    MSTP_Port.InputBuffer = &Receive_Buffer.pdu[0];
    MSTP_Init(&MSTP_Port);
}
Example #2
0
/* simple test to packetize the data and print it */
int main(
    int argc,
    char *argv[])
{
    volatile struct mstp_port_struct_t *mstp_port;
    long my_baud = 38400;
    uint32_t packet_count = 0;

    MSTP_Port.InputBuffer = &RxBuffer[0];
    MSTP_Port.InputBufferSize = sizeof(RxBuffer);
    MSTP_Port.OutputBuffer = &TxBuffer[0];
    MSTP_Port.OutputBufferSize = sizeof(TxBuffer);
    MSTP_Port.This_Station = 127;
    MSTP_Port.Nmax_info_frames = 1;
    MSTP_Port.Nmax_master = 127;
    MSTP_Port.SilenceTimer = Timer_Silence;
    MSTP_Port.SilenceTimerReset = Timer_Silence_Reset;
    /* mimic our pointer in the state machine */
    mstp_port = &MSTP_Port;
    MSTP_Init(mstp_port);
    packet_statistics_clear();
    /* initialize our interface */
    if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
        printf("mstpcap --scan <filename>\r\n"
            "perform statistic analysis on MS/TP capture file.\r\n");
        printf("\r\n");
        printf("mstpcap [interface] [baud] [named pipe]\r\n"
            "Captures MS/TP packets from a serial interface\r\n"
            "and save them to a file. Saves packets in a\r\n"
            "filename mstp_20090123091200.cap that has data and time.\r\n"
            "After receiving 65535 packets, a new file is created.\r\n" "\r\n"
            "Command line options:\r\n" "[interface] - serial interface.\r\n"
            "    defaults to COM4 on  Windows, and /dev/ttyUSB0 on linux.\r\n"
            "[baud] - baud rate.  9600, 19200, 38400, 57600, 115200\r\n"
            "    defaults to 38400.\r\n"
            "[named pipe] - use \\\\.\\pipe\\wireshark as the name\r\n"
            "    and set that name as the interface name in Wireshark\r\n");
        return 0;
    }
    if ((argc > 1) && (strcmp(argv[1], "--version") == 0)) {
        printf("mstpcap %s\r\n", BACNET_VERSION_TEXT);
        printf("Copyright (C) 2011 by Steve Karg\r\n"
            "This is free software; see the source for copying conditions.\r\n"
            "There is NO warranty; not even for MERCHANTABILITY or\r\n"
            "FITNESS FOR A PARTICULAR PURPOSE.\r\n");
        return 0;
    }
    if ((argc > 1) && (strcmp(argv[1], "--scan") == 0)) {
        if (argc > 2) {
            printf("Scanning %s\r\n", argv[2]);
            /* perform statistics on the file */
            if (test_global_header(argv[2])) {
                while (read_received_packet(mstp_port)) {
                    packet_count++;
                    fprintf(stderr, "\r%u packets", (unsigned) packet_count);
                }
                if (packet_count) {
                    packet_statistics_print();
                }
            } else {
                fprintf(stderr, "File header does not match.\n");
            }
            return 1;
        }
    }
    if (argc > 1) {
        RS485_Set_Interface(argv[1]);
    } else {
        #if defined(_WIN32)
        print_com_ports();
        return 0;
        #endif
    }
    if (argc > 2) {
        my_baud = strtol(argv[2], NULL, 0);
        RS485_Set_Baud_Rate(my_baud);
    }
    atexit(cleanup);
    RS485_Initialize();
    timer_init();
    fprintf(stdout, "mstpcap: Using %s for capture at %ld bps.\n",
        RS485_Interface(), (long) RS485_Get_Baud_Rate());
#if defined(_WIN32)
    SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT);
    SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlCHandler, TRUE);
#else
    signal_init();
#endif
    if (argc > 3) {
        named_pipe_create(argv[3]);
    }
    filename_create_new();
    /* run forever */
    for (;;) {
        RS485_Check_UART_Data(mstp_port);
        MSTP_Receive_Frame_FSM(mstp_port);
        /* process the data portion of the frame */
        if (mstp_port->ReceivedValidFrame) {
            write_received_packet(mstp_port);
            mstp_port->ReceivedValidFrame = false;
            packet_count++;
        } else if (mstp_port->ReceivedValidFrameNotForUs) {
            write_received_packet(mstp_port);
            mstp_port->ReceivedValidFrameNotForUs = false;
            packet_count++;
        } else if (mstp_port->ReceivedInvalidFrame) {
            write_received_packet(mstp_port);
            Invalid_Frame_Count++;
            mstp_port->ReceivedInvalidFrame = false;
            packet_count++;
        }
        if (!(packet_count % 100)) {
            fprintf(stdout, "\r%hu packets, %hu invalid frames", packet_count,
                Invalid_Frame_Count);
        }
        if (packet_count >= 65535) {
            packet_statistics_print();
            packet_statistics_clear();
            filename_create_new();
            packet_count = 0;
        }
    }
}
Example #3
0
/* simple test to packetize the data and print it */
int main(
    int argc,
    char *argv[])
{
    volatile struct mstp_port_struct_t *mstp_port;
    long my_baud = 38400;
    uint32_t packet_count = 0;
#if defined(_WIN32)
    unsigned long hThread = 0;
    uint32_t arg_value = 0;
#else
    int rc = 0;
    pthread_t hThread;
#endif
    int sockfd = -1;
    char *my_interface = "eth0";

    /* mimic our pointer in the state machine */
    mstp_port = &MSTP_Port;
    if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
        printf("mstsnap [serial] [baud] [network]\r\n"
            "Captures MS/TP packets from a serial interface\r\n"
            "and sends them to a network interface using SNAP \r\n"
            "protocol packets (mimics Cimetrics U+4 packet).\r\n" "\r\n"
            "Command line options:\r\n" "[serial] - serial interface.\r\n"
            "    defaults to /dev/ttyUSB0.\r\n"
            "[baud] - baud rate.  9600, 19200, 38400, 57600, 115200\r\n"
            "    defaults to 38400.\r\n" "[network] - network interface.\r\n"
            "    defaults to eth0.\r\n" "");
        return 0;
    }
    /* initialize our interface */
    if (argc > 1) {
        RS485_Set_Interface(argv[1]);
    }
    if (argc > 2) {
        my_baud = strtol(argv[2], NULL, 0);
    }
    if (argc > 3) {
        my_interface = argv[3];
    }
    sockfd = network_init(my_interface, ETH_P_ALL);
    if (sockfd == -1) {
        return 1;
    }
    RS485_Set_Baud_Rate(my_baud);
    RS485_Initialize();
    MSTP_Port.InputBuffer = &RxBuffer[0];
    MSTP_Port.InputBufferSize = sizeof(RxBuffer);
    MSTP_Port.OutputBuffer = &TxBuffer[0];
    MSTP_Port.OutputBufferSize = sizeof(TxBuffer);
    MSTP_Port.This_Station = 127;
    MSTP_Port.Nmax_info_frames = 1;
    MSTP_Port.Nmax_master = 127;
    MSTP_Port.SilenceTimer = Timer_Silence;
    MSTP_Port.SilenceTimerReset = Timer_Silence_Reset;
    MSTP_Init(mstp_port);
    mstp_port->Lurking = true;
    fprintf(stdout, "mstpcap: Using %s for capture at %ld bps.\n",
        RS485_Interface(), (long) RS485_Get_Baud_Rate());
#if defined(_WIN32)
    hThread = _beginthread(milliseconds_task, 4096, &arg_value);
    if (hThread == 0) {
        fprintf(stderr, "Failed to start timer task\n");
    }
    (void) SetThreadPriority(GetCurrentThread(),
        THREAD_PRIORITY_TIME_CRITICAL);
#else
    /* start our MilliSec task */
    rc = pthread_create(&hThread, NULL, milliseconds_task, NULL);
    signal_init();
#endif
    atexit(cleanup);
    /* run forever */
    for (;;) {
        RS485_Check_UART_Data(mstp_port);
        MSTP_Receive_Frame_FSM(mstp_port);
        /* process the data portion of the frame */
        if (mstp_port->ReceivedValidFrame) {
            mstp_port->ReceivedValidFrame = false;
            snap_received_packet(mstp_port, sockfd);
            packet_count++;
        } else if (mstp_port->ReceivedInvalidFrame) {
            mstp_port->ReceivedInvalidFrame = false;
            fprintf(stderr, "ReceivedInvalidFrame\n");
            snap_received_packet(mstp_port, sockfd);
            packet_count++;
        }
        if (!(packet_count % 100)) {
            fprintf(stdout, "\r%hu packets", packet_count);
        }
    }

    return 0;
}
Example #4
0
/* simple test to packetize the data and print it */
int main(
    int argc,
    char *argv[])
{
    volatile struct mstp_port_struct_t *mstp_port;
    long my_baud = 38400;
    uint32_t packet_count = 0;
    int sockfd = -1;
    char *my_interface = "eth0";

    /* mimic our pointer in the state machine */
    mstp_port = &MSTP_Port;
    if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
        printf("mstsnap [serial] [baud] [network]\r\n"
            "Captures MS/TP packets from a serial interface\r\n"
            "and sends them to a network interface using SNAP \r\n"
            "protocol packets (mimics Cimetrics U+4 packet).\r\n" "\r\n"
            "Command line options:\r\n" "[serial] - serial interface.\r\n"
            "    defaults to /dev/ttyUSB0.\r\n"
            "[baud] - baud rate.  9600, 19200, 38400, 57600, 115200\r\n"
            "    defaults to 38400.\r\n" "[network] - network interface.\r\n"
            "    defaults to eth0.\r\n" "");
        return 0;
    }
    /* initialize our interface */
    if (argc > 1) {
        RS485_Set_Interface(argv[1]);
    }
    if (argc > 2) {
        my_baud = strtol(argv[2], NULL, 0);
    }
    if (argc > 3) {
        my_interface = argv[3];
    }
    sockfd = network_init(my_interface, ETH_P_ALL);
    if (sockfd == -1) {
        return 1;
    }
    RS485_Set_Baud_Rate(my_baud);
    RS485_Initialize();
    MSTP_Port.InputBuffer = &RxBuffer[0];
    MSTP_Port.InputBufferSize = sizeof(RxBuffer);
    MSTP_Port.OutputBuffer = &TxBuffer[0];
    MSTP_Port.OutputBufferSize = sizeof(TxBuffer);
    MSTP_Port.This_Station = 127;
    MSTP_Port.Nmax_info_frames = 1;
    MSTP_Port.Nmax_master = 127;
    MSTP_Port.SilenceTimer = Timer_Silence;
    MSTP_Port.SilenceTimerReset = Timer_Silence_Reset;
    MSTP_Init(mstp_port);
    fprintf(stdout, "mstpcap: Using %s for capture at %ld bps.\n",
        RS485_Interface(), (long) RS485_Get_Baud_Rate());
    atexit(cleanup);
#if defined(_WIN32)
    SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT);
    SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlCHandler, TRUE);
#else
    signal_init();
#endif
    /* run forever */
    for (;;) {
        RS485_Check_UART_Data(mstp_port);
        MSTP_Receive_Frame_FSM(mstp_port);
        /* process the data portion of the frame */
        if (mstp_port->ReceivedValidFrame) {
            mstp_port->ReceivedValidFrame = false;
            snap_received_packet(mstp_port, sockfd);
            packet_count++;
        } else if (mstp_port->ReceivedInvalidFrame) {
            mstp_port->ReceivedInvalidFrame = false;
            fprintf(stderr, "ReceivedInvalidFrame\n");
            snap_received_packet(mstp_port, sockfd);
            packet_count++;
        }
        if (!(packet_count % 100)) {
            fprintf(stdout, "\r%hu packets", packet_count);
        }
    }

    return 0;
}
Example #5
0
/* simple test to packetize the data and print it */
int main(
    int argc,
    char *argv[])
{
    volatile struct mstp_port_struct_t *mstp_port;
    long my_baud = 38400;
    uint32_t packet_count = 0;
    int argi = 0;
    char *filename = NULL;

    MSTP_Port.InputBuffer = &RxBuffer[0];
    MSTP_Port.InputBufferSize = sizeof(RxBuffer);
    MSTP_Port.OutputBuffer = &TxBuffer[0];
    MSTP_Port.OutputBufferSize = sizeof(TxBuffer);
    MSTP_Port.This_Station = 127;
    MSTP_Port.Nmax_info_frames = 1;
    MSTP_Port.Nmax_master = 127;
    MSTP_Port.SilenceTimer = Timer_Silence;
    MSTP_Port.SilenceTimerReset = Timer_Silence_Reset;
    /* mimic our pointer in the state machine */
    mstp_port = &MSTP_Port;
    MSTP_Init(mstp_port);
    packet_statistics_clear();
    /* decode any command line parameters */
    filename = filename_remove_path(argv[0]);
    for (argi = 1; argi < argc; argi++) {
        if (strcmp(argv[argi], "--help") == 0) {
            print_usage(filename);
            print_help(filename);
            return 0;
        }
        if (strcmp(argv[argi], "--version") == 0) {
            printf("mstpcap %s\n", BACNET_VERSION_TEXT);
            printf("Copyright (C) 2011 by Steve Karg\n"
                "This is free software; see the source for copying conditions.\n"
                "There is NO warranty; not even for MERCHANTABILITY or\n"
                "FITNESS FOR A PARTICULAR PURPOSE.\n");
            return 0;
        }
        if (strcmp(argv[argi], "--scan") == 0) {
            argi++;
            if (argi >= argc) {
                printf("An file name must be provided.\n");
                return 1;
            }
            printf("Scanning %s\n", argv[argi]);
            /* perform statistics on the file */
            if (test_global_header(argv[argi])) {
                while (read_received_packet(mstp_port)) {
                    packet_count++;
                    fprintf(stderr, "\r%u packets",
                        (unsigned) packet_count);
                }
                if (packet_count) {
                    packet_statistics_print();
                }
            } else {
                fprintf(stderr, "File header does not match.\n");
            }
        }
        if (strcmp(argv[argi], "--extcap-interfaces") == 0) {
            RS485_Print_Ports();
            return 0;
        }
        if (strcmp(argv[argi], "--extcap-dlts") == 0) {
            argi++;
            if (argi >= argc) {
                printf("An interface must be provided.\n");
                return 0;
            }
            printf("dlt {number=%u}{name=BACnet MS/TP}"
                "{display=BACnet MS/TP}\n",
                DLT_BACNET_MS_TP);
            Exit_Requested = true;
        }
        if (strcmp(argv[argi], "--extcap-config") == 0) {
            printf("arg {number=0}{call=--baud}{display=Baud Rate}"
                "{tooltip=Serial port baud rate in bits per second}"
                "{type=selector}\n");
            printf("value {arg=0}{value=9600}{display=9600}{default=false}\n");
            printf("value {arg=0}{value=19200}{display=19200}{default=false}\n");
            printf("value {arg=0}{value=38400}{display=38400}{default=true}\n");
            printf("value {arg=0}{value=57600}{display=57600}{default=false}\n");
            printf("value {arg=0}{value=76800}{display=76800}{default=false}\n");
            printf("value {arg=0}{value=115200}{display=115200}{default=false}\n");
            return 0;
        }
        if (strcmp(argv[argi], "--capture") == 0) {
            /* do nothing - fall through and start running! */
        }
        if (strcmp(argv[argi], "--extcap-interface") == 0) {
            argi++;
            if (argi >= argc) {
                printf("An interface must be provided or "
                    "the selection must be displayed.\n");
                return 0;
            }
            RS485_Set_Interface(argv[argi]);
        }
        if (strcmp(argv[argi], "--baud") == 0) {
            argi++;
            if (argi >= argc) {
                printf("A baud rate must be provided.\n");
                return 0;
            }
            my_baud = strtol(argv[argi], NULL, 0);
            RS485_Set_Baud_Rate(my_baud);
        }
        if (strcmp(argv[argi], "--fifo") == 0) {
            argi++;
            if (argi >= argc) {
                printf("A named pipe must be provided.\n");
                return 0;
            }
            named_pipe_create(argv[argi]);
        }
    }
    if (Exit_Requested) {
        return 0;
    }
    if (argc <= 1) {
        RS485_Print_Ports();
        return 0;
    }
    atexit(cleanup);
    RS485_Initialize();
    timer_init();
    fprintf(stdout, "mstpcap: Using %s for capture at %ld bps.\n",
        RS485_Interface(), (long) RS485_Get_Baud_Rate());
#if defined(_WIN32)
    SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT);
    SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlCHandler, TRUE);
#else
    signal_init();
#endif
    filename_create_new();
    /* run forever */
    for (;;) {
        RS485_Check_UART_Data(mstp_port);
        MSTP_Receive_Frame_FSM(mstp_port);
        /* process the data portion of the frame */
        if (mstp_port->ReceivedValidFrame) {
            write_received_packet(mstp_port);
            mstp_port->ReceivedValidFrame = false;
            packet_count++;
        } else if (mstp_port->ReceivedValidFrameNotForUs) {
            write_received_packet(mstp_port);
            mstp_port->ReceivedValidFrameNotForUs = false;
            packet_count++;
        } else if (mstp_port->ReceivedInvalidFrame) {
            write_received_packet(mstp_port);
            Invalid_Frame_Count++;
            mstp_port->ReceivedInvalidFrame = false;
            packet_count++;
        }
        if (!(packet_count % 100)) {
            fprintf(stdout, "\r%hu packets, %hu invalid frames", packet_count,
                Invalid_Frame_Count);
        }
        if (packet_count >= 65535) {
            packet_statistics_print();
            packet_statistics_clear();
            filename_create_new();
            packet_count = 0;
        }
        if (Exit_Requested) {
            break;
        }
    }
    /* tell signal interrupts we are done */
    Exit_Requested = false;

    return 0;
}
Example #6
0
bool dlmstp_init(
    char *ifname)
{
    unsigned long hThread = 0;
    int rv = 0;

    /* initialize packet queue */
    Receive_Packet.ready = false;
    Receive_Packet.pdu_len = 0;
    rv = pthread_cond_init(&Receive_Packet_Flag, NULL);
    if (rv == -1) {
        fprintf(stderr,
            "MS/TP Interface: %s\n cannot allocate PThread Condition.\n",
            ifname);
        exit(1);
    }
    rv = pthread_cond_init(&Received_Frame_Flag, NULL);
    if (rv == -1) {
        fprintf(stderr,
            "MS/TP Interface: %s\n cannot allocate PThread Condition.\n",
            ifname);
        exit(1);
    }
    rv = pthread_mutex_init(&Receive_Packet_Mutex, NULL);
    if (rv == -1) {
        fprintf(stderr,
            "MS/TP Interface: %s\n cannot allocate PThread Mutex.\n", ifname);
        exit(1);
    }
    rv = pthread_mutex_init(&Received_Frame_Mutex, NULL);
    if (rv == -1) {
        fprintf(stderr,
            "MS/TP Interface: %s\n cannot allocate PThread Mutex.\n", ifname);
        exit(1);
    }
    /* initialize hardware */
    if (ifname) {
        RS485_Set_Interface(ifname);
#if PRINT_ENABLED
        fprintf(stderr, "MS/TP Interface: %s\n", ifname);
#endif
    }
    RS485_Initialize();
    MSTP_Port.InputBuffer = &RxBuffer[0];
    MSTP_Port.InputBufferSize = sizeof(RxBuffer);
    MSTP_Port.OutputBuffer = &TxBuffer[0];
    MSTP_Port.OutputBufferSize = sizeof(TxBuffer);
    MSTP_Port.SilenceTimer = Timer_Silence;
    MSTP_Port.SilenceTimerReset = Timer_Silence_Reset;
    MSTP_Init(&MSTP_Port);
#if 0
    uint8_t data;

    /* FIXME: implement your data storage */
    data = 64;  /* I2C_Read_Byte(
                   EEPROM_DEVICE_ADDRESS,
                   EEPROM_MSTP_MAC_ADDR); */
    if (data <= 127)
        MSTP_Port.This_Station = data;
    else
        dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
    /* FIXME: implement your data storage */
    data = 127; /* I2C_Read_Byte(
                   EEPROM_DEVICE_ADDRESS,
                   EEPROM_MSTP_MAX_MASTER_ADDR); */
    if ((data <= 127) && (data >= MSTP_Port.This_Station))
        MSTP_Port.Nmax_master = data;
    else
        dlmstp_set_max_master(DEFAULT_MAX_MASTER);
    /* FIXME: implement your data storage */
    data = 1;
    /* I2C_Read_Byte(
       EEPROM_DEVICE_ADDRESS,
       EEPROM_MSTP_MAX_INFO_FRAMES_ADDR); */
    if (data >= 1)
        MSTP_Port.Nmax_info_frames = data;
    else
        dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
#endif
#if PRINT_ENABLED
    fprintf(stderr, "MS/TP MAC: %02X\n", MSTP_Port.This_Station);
    fprintf(stderr, "MS/TP Max_Master: %02X\n", MSTP_Port.Nmax_master);
    fprintf(stderr, "MS/TP Max_Info_Frames: %u\n", MSTP_Port.Nmax_info_frames);
#endif
    /* start the threads */
    rv = pthread_create(&hThread, NULL, dlmstp_milliseconds_task, NULL);
    if (rv != 0) {
        fprintf(stderr, "Failed to start timer task\n");
    }
    rv = pthread_create(&hThread, NULL, dlmstp_receive_fsm_task, NULL);
    if (rv != 0) {
        fprintf(stderr, "Failed to start recive FSM task\n");
    }
    rv = pthread_create(&hThread, NULL, dlmstp_master_fsm_task, NULL);
    if (rv != 0) {
        fprintf(stderr, "Failed to start Master Node FSM task\n");
    }

    return true;
}
Example #7
0
bool dlmstp_init(
    char *ifname)
{
    unsigned long hThread = 0;
    uint32_t arg_value = 0;
    TIMECAPS tc;

    /* initialize packet queue */
    Receive_Packet.ready = false;
    Receive_Packet.pdu_len = 0;
    Receive_Packet_Flag = CreateSemaphore(NULL, 0, 1, "dlmstpReceivePacket");
    if (Receive_Packet_Flag == NULL)
        exit(1);
    Received_Frame_Flag = CreateSemaphore(NULL, 0, 1, "dlsmtpReceiveFrame");
    if (Received_Frame_Flag == NULL) {
        CloseHandle(Receive_Packet_Flag);
        exit(1);
    }
    /* initialize hardware */
    /* initialize hardware */
    if (ifname) {
        RS485_Set_Interface(ifname);
#if PRINT_ENABLED
        fprintf(stderr, "MS/TP Interface: %s\n", ifname);
#endif
    }
    RS485_Initialize();
    MSTP_Port.InputBuffer = &RxBuffer[0];
    MSTP_Port.InputBufferSize = sizeof(RxBuffer);
    MSTP_Port.OutputBuffer = &TxBuffer[0];
    MSTP_Port.OutputBufferSize = sizeof(TxBuffer);
    MSTP_Port.SilenceTimer = Timer_Silence;
    MSTP_Port.SilenceTimerReset = Timer_Silence_Reset;
    MSTP_Init(&MSTP_Port);
#if 0
    uint8_t data;

    /* FIXME: implement your data storage */
    data = 64;  /* I2C_Read_Byte(
                   EEPROM_DEVICE_ADDRESS,
                   EEPROM_MSTP_MAC_ADDR); */
    if (data <= 127)
        MSTP_Port.This_Station = data;
    else
        dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
    /* FIXME: implement your data storage */
    data = 127; /* I2C_Read_Byte(
                   EEPROM_DEVICE_ADDRESS,
                   EEPROM_MSTP_MAX_MASTER_ADDR); */
    if ((data <= 127) && (data >= MSTP_Port.This_Station))
        MSTP_Port.Nmax_master = data;
    else
        dlmstp_set_max_master(DEFAULT_MAX_MASTER);
    /* FIXME: implement your data storage */
    data = 1;
    /* I2C_Read_Byte(
       EEPROM_DEVICE_ADDRESS,
       EEPROM_MSTP_MAX_INFO_FRAMES_ADDR); */
    if (data >= 1)
        MSTP_Port.Nmax_info_frames = data;
    else
        dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
#endif
#if PRINT_ENABLED
    fprintf(stderr, "MS/TP MAC: %02X\n", MSTP_Port.This_Station);
    fprintf(stderr, "MS/TP Max_Master: %02X\n", MSTP_Port.Nmax_master);
    fprintf(stderr, "MS/TP Max_Info_Frames: %u\n", MSTP_Port.Nmax_info_frames);
#endif
    /* set timer resolution */
    if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
        fprintf(stderr, "Failed to set timer resolution\n");
    }
    TimeBeginPeriod =
        min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax);
    timeBeginPeriod(TimeBeginPeriod);

    /* start the threads */
    hThread = _beginthread(dlmstp_receive_fsm_task, 4096, &arg_value);
    if (hThread == 0) {
        fprintf(stderr, "Failed to start recive FSM task\n");
    }
    hThread = _beginthread(dlmstp_master_fsm_task, 4096, &arg_value);
    if (hThread == 0) {
        fprintf(stderr, "Failed to start Master Node FSM task\n");
    }

    return true;
}