This commit is contained in:
skarg
2005-03-18 22:09:23 +00:00
parent 7d768beefc
commit 2350fe26a3
4 changed files with 580 additions and 0 deletions
+203
View File
@@ -0,0 +1,203 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2005 Steve Karg
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.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#include <stdbool.h>
#include <stdint.h>
#include <assert.h>
#include "bacdef.h"
#include "bacenum.h"
#include "config.h" // the custom stuff
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
static char *Vendor_Name = "ASHRAE";
static uint16_t Vendor_Identifier = 0;
static char *Model_Name = "GNU";
static char *Firmware_Revision = "1.0";
static char *Application_Software_Version = "1.0";
//static char *Location = "USA";
static char *Description = "server";
//static uint8_t Protocol_Version = 1; - constant, not settable
//static uint8_t Protocol_Revision = 4; - constant, not settable
//Protocol_Services_Supported
//Protocol_Object_Types_Supported
//Object_List
//static uint16_t Max_APDU_Length_Accepted = MAX_APDU; - constant
//static BACNET_SEGMENTATION Segmentation_Supported = SEGMENTATION_NONE;
//static uint8_t Max_Segments_Accepted = 0;
//VT_Classes_Supported
//Active_VT_Sessions
//Local_Time - rely on OS, if there is one
//Local_Date - rely on OS, if there is one
//UTC_Offset - rely on OS, if there is one
//Daylight_Savings_Status - rely on OS, if there is one
//APDU_Segment_Timeout
static uint16_t APDU_Timeout = 3000;
static uint8_t Number_Of_APDU_Retries = 3;
//List_Of_Session_Keys
//Time_Synchronization_Recipients
//Max_Master - rely on MS/TP subsystem, if there is one
//Max_Info_Frames - rely on MS/TP subsystem, if there is one
//Device_Address_Binding - required, but relies on binding cache
static uint8_t Database_Revision = 0;
//Configuration_Files
//Last_Restore_Time
//Backup_Failure_Timeout
//Active_COV_Subscriptions
//Slave_Proxy_Enable
//Manual_Slave_Address_Binding
//Auto_Slave_Discovery
//Slave_Address_Binding
//Profile_Name
// methods to manipulate the data
// FIXME: add APDU encode methods for each?
BACNET_DEVICE_STATUS Device_System_Status(void)
{
return System_Status;
}
void Device_Set_System_Status(BACNET_DEVICE_STATUS status)
{
// FIXME: bounds check?
System_Status = status;
}
const char *Device_Vendor_Name(void)
{
return Vendor_Name;
}
void Device_Set_Vendor_Name(const char *name)
{
Vendor_Name = name;
}
uint16_t Device_Vendor_Identifier(void)
{
return Vendor_Identifier;
}
void Device_Set_Vendor_Identifier(uint16_t vendor_id)
{
Vendor_Identifier = vendor_id;
}
const char *Device_Model_Name(void)
{
return Model_Name;
}
void Device_Set_Model_Name(const char *name)
{
Model_Name = name;
}
const char *Device_Firmware_Revision(void)
{
return Firmware_Revision;
}
void Device_Set_Firmware_Revision(const char *name)
{
Firmware_Revision = name;
}
const char *Device_Application_Software_Version(void)
{
return Application_Software_Version;
}
void Device_Application_Software_Version(const char *name)
{
Application_Software_Version = name;
}
const char *Device_Description(void)
{
return Description;
}
void Device_Description(const char *name)
{
Description = name;
}
uint8_t Device_Protocol_Version(void)
{
return 1;
}
uint8_t Device_Protocol_Revision(void)
{
return 4;
}
uint16_t Device_Max_APDU_Length_Accepted(void)
{
return MAX_APDU;
}
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
{
return SEGMENTATION_NONE;
}
//FIXME: This need some bit string encodings...
//Protocol_Services_Supported
//Protocol_Object_Types_Supported
//FIXME: Probably return one at a time, or be supported by
// an object module, or encode the APDU here.
//Object_List
uint16_t Device_APDU_Timeout(void)
{
return APDU_Timeout;
}
void Device_Set_APDU_Timeout(uint16_t timeout)
{
APDU_Timeout = timeout;
}
uint8_t Device_Number_Of_APDU_Retries(void)
{
return Number_Of_APDU_Retries;
}
void Device_Set_Number_Of_APDU_Retries(uint8_t retries)
{
Number_Of_APDU_Retries = retries;
}
+77
View File
@@ -0,0 +1,77 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2005 Steve Karg
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.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#ifndef DEVICE_H
#define DEVICE_H
#include <stdbool.h>
#include <stdint.h>
#include <assert.h>
#include "bacdef.h"
#include "bacenum.h"
BACNET_DEVICE_STATUS Device_System_Status(void);
void Device_Set_System_Status(BACNET_DEVICE_STATUS status);
const char *Device_Vendor_Name(void);
void Device_Set_Vendor_Name(const char *name);
uint16_t Device_Vendor_Identifier(void);
void Device_Set_Vendor_Identifier(uint16_t vendor_id);
const char *Device_Model_Name(void);
void Device_Set_Model_Name(const char *name);
const char *Device_Firmware_Revision(void);
void Device_Set_Firmware_Revision(const char *name);
const char *Device_Application_Software_Version(void);
void Device_Application_Software_Version(const char *name);
const char *Device_Description(void);
void Device_Description(const char *name);
uint8_t Device_Protocol_Version(void);
uint8_t Device_Protocol_Revision(void);
uint16_t Device_Max_APDU_Length_Accepted(void);
BACNET_SEGMENTATION Device_Segmentation_Supported(void);
uint16_t Device_APDU_Timeout(void);
void Device_Set_APDU_Timeout(uint16_t timeout);
uint8_t Device_Number_Of_APDU_Retries(void);
void Device_Set_Number_Of_APDU_Retries(uint8_t retries);
#endif
+204
View File
@@ -0,0 +1,204 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2005 Steve Karg
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.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <assert.h>
#include "bits.h"
#include "apdu.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "tsm.h"
#include "config.h"
#include "device.h"
// Transaction State Machine
// Really only needed for segmented messages
// and a little for sending confirmed messages
// If we are only a server and only initiate broadcasts,
// then we don't need a TSM layer.
// FIXME: not coded for segmentation
static BACNET_TSM_DATA TSM_List[MAX_TSM_TRANSACTIONS] = {0};
// returns MAX_TSM_TRANSACTIONS if not found
uint8_t tsm_find_invokeID_index(uint8_t invokeID)
{
unsigned i = 0; // counter
uint8_t index = MAX_TSM_TRANSACTIONS; // return value
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++)
{
if ((TSM_List[i].state != TSM_STATE_IDLE) &&
(TSM_List[i].InvokeID == invokeID))
{
index = i;
break;
}
}
return index;
}
bool tsm_transaction_available(void)
{
bool status = false; // return value
unsigned i = 0; // counter
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++)
{
if (TSM_List[i].state == TSM_STATE_IDLE)
{
// one is available!
status = true;
break;
}
}
return status;
}
uint8_t tsm_transaction_idle_count(void)
{
uint8_t count = 0; // return value
unsigned i = 0; // counter
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++)
{
if (TSM_List[i].state == TSM_STATE_IDLE)
{
// one is available!
count++;
}
}
return count;
}
uint8_t tsm_next_free_invokeID(void)
{
static uint8_t current_invokeID = 1; // incremented...
uint8_t index = 0;
uint8_t invokeID = 0;
bool found = false;
while (!found)
{
index = tsm_find_invokeID_index(current_invokeID);
if (index == MAX_TSM_TRANSACTIONS)
{
found = true;
invokeID = current_invokeID;
}
current_invokeID++;
// skip zero - we treat that internally as invalid or no free
if (current_invokeID == 0)
current_invokeID++;
}
return invokeID;
}
// returns 0 if there are no free transactions
uint8_t tsm_request_confirmed_unsegmented_transaction(
BACNET_ADDRESS *src,
BACNET_ADDRESS *dest,
uint8_t *pdu,
uint16_t pdu_len);
{
uint8_t invokeID = 0;
unsigned i = 0, j = 0;
// see if there is a free transaction
for (i = 0; i < MAX_TSM_TRANSACTIONS; i++)
{
if (TSM_List[i].state == TSM_STATE_IDLE)
{
// see if the current invoke id is free
invokeID = tsm_next_free_invokeID();
if (invokeID)
{
// assign the transaction
TSM_List[i].state = TSM_STATE_AWAIT_CONFIRMATION;
TSM_List[i].RetryCount = Device_Number_Of_APDU_Retries();
// start the timer
TSM_List[i].RequestTimer = Device_APDU_Timeout();
// copy the data
for (j = 0; j < pdu_len; j++)
{
TSM_List[i].pdu[j] = pdu[j];
}
}
break;
}
}
return invokeID;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
void testTSM(Test * pTest)
{
}
#ifdef TEST_TSM
int main(void)
{
Test *pTest;
bool rc;
pTest = ct_create("BACnet TSM", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testTSM);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif /* TEST_TSM */
#endif /* TEST */
+96
View File
@@ -0,0 +1,96 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2005 Steve Karg
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.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#ifndef TSM_H
#define TSM_H
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
typedef enum
{
TSM_STATE_IDLE,
TSM_STATE_AWAIT_CONFIRMATION,
TSM_STATE_AWAIT_RESPONSE,
TSM_STATE_SEGMENTED_REQUEST,
TSM_STATE_SEGMENTED_CONFIRMATION,
} BACNET_TSM_STATE;
// 5.4.1 Variables And Parameters
// The following variables are defined for each instance of
// Transaction State Machine:
typedef struct BACnet_TSM_Data
{
// used to count APDU retries
uint8_t RetryCount;
// used to count segment retries
//uint8_t SegmentRetryCount;
// used to control APDU retries and the acceptance of server replies
//bool SentAllSegments;
// stores the sequence number of the last segment received in order
//uint8_t LastSequenceNumber;
// stores the sequence number of the first segment of
// a sequence of segments that fill a window
//uint8_t InitialSequenceNumber;
// stores the current window size
//uint8_t ActualWindowSize;
// stores the window size proposed by the segment sender
//uint8_t ProposedWindowSize;
// used to perform timeout on PDU segments
//uint8_t SegmentTimer;
// used to perform timeout on Confirmed Requests
uint8_t RequestTimer;
// unique id
uint8_t InvokeID;
// state that the TSM is in
BACNET_TSM_STATE state;
// the address it was sent from
BACNET_ADDRESS src;
// the address we sent it to
BACNET_ADDRESS dest;
// copy of the PDU, should we need to send it again
uint8_t pdu[MAX_MPDU];
} BACNET_TSM_DATA;
bool tsm_transaction_available(void);
uint8_t tsm_transaction_idle_count(void);
uint8_t tsm_request_confirmed_unsegmented_transaction(
BACNET_ADDRESS *src,
BACNET_ADDRESS *dest,
uint8_t *pdu,
uint16_t pdu_len);
#endif