added proper bitstring encoding
This commit is contained in:
+26
-2
@@ -544,6 +544,30 @@ bool decode_is_closing_tag_number(uint8_t * apdu, uint8_t tag_number)
|
||||
return (closing_tag && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
static uint8_t byte_reverse_bits(uint8_t in_byte)
|
||||
{
|
||||
uint8_t out_byte = 0;
|
||||
|
||||
if (in_byte & BIT0)
|
||||
out_byte |= BIT7;
|
||||
if (in_byte & BIT1)
|
||||
out_byte |= BIT6;
|
||||
if (in_byte & BIT2)
|
||||
out_byte |= BIT5;
|
||||
if (in_byte & BIT3)
|
||||
out_byte |= BIT4;
|
||||
if (in_byte & BIT4)
|
||||
out_byte |= BIT3;
|
||||
if (in_byte & BIT5)
|
||||
out_byte |= BIT2;
|
||||
if (in_byte & BIT6)
|
||||
out_byte |= BIT1;
|
||||
if (in_byte & BIT7)
|
||||
out_byte |= BIT0;
|
||||
|
||||
return out_byte;
|
||||
}
|
||||
|
||||
// from clause 20.2.10 Encoding of a Bit String Value
|
||||
// returns the number of apdu bytes consumed
|
||||
int decode_bitstring(uint8_t * apdu, uint32_t len_value,
|
||||
@@ -565,7 +589,7 @@ int decode_bitstring(uint8_t * apdu, uint32_t len_value,
|
||||
len = 1;
|
||||
for (i = 0; i < bytes_used; i++)
|
||||
{
|
||||
bit_string->value[i] = apdu[len++];
|
||||
bit_string->value[i] = byte_reverse_bits(apdu[len++]);
|
||||
}
|
||||
unused_bits = apdu[0] & 0x07;
|
||||
bit_string->bits_used = bytes_used * 8;
|
||||
@@ -615,7 +639,7 @@ int encode_bitstring(uint8_t * apdu, BACNET_BIT_STRING *bit_string)
|
||||
apdu[len++] = 8 - remaining_used_bits;
|
||||
for (i = 0; i < used_bytes; i++)
|
||||
{
|
||||
apdu[len++] = bit_string->value[i];
|
||||
apdu[len++] = byte_reverse_bits(bit_string->value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,14 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// bit strings
|
||||
#define MAX_BITSTRING_BYTES 15
|
||||
typedef struct BACnet_Bit_String
|
||||
{
|
||||
uint8_t bits_used;
|
||||
uint8_t value[MAX_BITSTRING_BYTES];
|
||||
} BACNET_BIT_STRING;
|
||||
|
||||
// from clause 20.2.1 General Rules for Encoding BACnet Tags
|
||||
// returns the number of apdu bytes consumed
|
||||
int encode_tag(uint8_t * apdu, uint8_t tag_number, bool context_specific,
|
||||
@@ -58,6 +66,18 @@ bool decode_is_closing_tag_number(uint8_t * apdu, uint8_t tag_number);
|
||||
// returns true if the tag is context specific and matches
|
||||
bool decode_is_context_tag(uint8_t * apdu, uint8_t tag_number);
|
||||
|
||||
// from clause 20.2.10 Encoding of a Bit String Value
|
||||
void bitstring_init(BACNET_BIT_STRING *bit_string);
|
||||
void bitstring_set_bit(BACNET_BIT_STRING *bit_string, uint8_t bit, bool value);
|
||||
bool bitstring_bit(BACNET_BIT_STRING *bit_string, uint8_t bit);
|
||||
uint8_t bitstring_bits_used(BACNET_BIT_STRING *bit_string);
|
||||
// returns the number of apdu bytes consumed
|
||||
int decode_bitstring(uint8_t * apdu, uint32_t len_value,
|
||||
BACNET_BIT_STRING *bit_string);
|
||||
// returns the number of apdu bytes consumed
|
||||
int encode_bitstring(uint8_t * apdu, BACNET_BIT_STRING *bit_string);
|
||||
int encode_tagged_bitstring(uint8_t * apdu, BACNET_BIT_STRING *bit_string);
|
||||
|
||||
// from clause 20.2.6 Encoding of a Real Number Value
|
||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
// returns the number of apdu bytes consumed
|
||||
|
||||
+56
-1
@@ -555,7 +555,7 @@ typedef enum
|
||||
OBJECT_COMMAND = 7,
|
||||
OBJECT_DEVICE = 8,
|
||||
OBJECT_EVENT_ENROLLMENT = 9,
|
||||
OBJECT_FILE_O = 10,
|
||||
OBJECT_FILE_ = 10,
|
||||
OBJECT_GROUP = 11,
|
||||
OBJECT_LOOP = 12,
|
||||
OBJECT_MULTI_STATE_INPUT = 13,
|
||||
@@ -703,6 +703,61 @@ typedef enum {
|
||||
MAX_BACNET_UNCONFIRMED_SERVICE = 10
|
||||
} BACNET_UNCONFIRMED_SERVICE;
|
||||
|
||||
// Bit String Enumerations
|
||||
typedef enum
|
||||
{
|
||||
// Alarm and Event Services
|
||||
SERVICE_SUPPORTED_ACKNOWLEDGE_ALARM = 0,
|
||||
SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION = 1,
|
||||
SERVICE_SUPPORTED_CONFIRMED_EVENT_NOTIFICATION = 2,
|
||||
SERVICE_SUPPORTED_GET_ALARM_SUMMARY = 3,
|
||||
SERVICE_SUPPORTED_GET_ENROLLMENT_SUMMARY = 4,
|
||||
SERVICE_SUPPORTED_GET_EVENT_INFORMATION = 39,
|
||||
SERVICE_SUPPORTED_SUBSCRIBE_COV = 5,
|
||||
SERVICE_SUPPORTED_SUBSCRIBE_COV_PROPERTY = 38,
|
||||
SERVICE_SUPPORTED_LIFE_SAFETY_OPERATION = 37,
|
||||
// File Access Services
|
||||
SERVICE_SUPPORTED_ATOMIC_READ_FILE = 6,
|
||||
SERVICE_SUPPORTED_ATOMIC_WRITE_FILE = 7,
|
||||
// Object Access Services
|
||||
SERVICE_SUPPORTED_ADD_LIST_ELEMENT = 8,
|
||||
SERVICE_SUPPORTED_REMOVE_LIST_ELEMENT = 9,
|
||||
SERVICE_SUPPORTED_CREATE_OBJECT = 10,
|
||||
SERVICE_SUPPORTED_DELETE_OBJECT = 11,
|
||||
SERVICE_SUPPORTED_READ_PROPERTY = 12,
|
||||
SERVICE_SUPPORTED_READ_PROPERTY_CONDITIONAL = 13,
|
||||
SERVICE_SUPPORTED_READ_PROPERTY_MULTIPLE = 14,
|
||||
SERVICE_SUPPORTED_READ_RANGE = 35,
|
||||
SERVICE_SUPPORTED_WRITE_PROPERTY = 15,
|
||||
SERVICE_SUPPORTED_WRITE_PROPERTY_MULTIPLE = 16,
|
||||
// Remote Device Management Services
|
||||
SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL = 17,
|
||||
SERVICE_SUPPORTED_PRIVATE_TRANSFER = 18,
|
||||
SERVICE_SUPPORTED_TEXT_MESSAGE = 19,
|
||||
SERVICE_SUPPORTED_REINITIALIZE_DEVICE = 20,
|
||||
// Virtual Terminal Services
|
||||
SERVICE_SUPPORTED_VT_OPEN = 21,
|
||||
SERVICE_SUPPORTED_VT_CLOSE = 22,
|
||||
SERVICE_SUPPORTED_VT_DATA = 23,
|
||||
// Security Services
|
||||
SERVICE_SUPPORTED_AUTHENTICATE = 24,
|
||||
SERVICE_SUPPORTED_REQUEST_KEY = 25,
|
||||
SERVICE_SUPPORTED_I_AM = 26,
|
||||
SERVICE_SUPPORTED_I_HAVE = 27,
|
||||
SERVICE_SUPPORTED_UNCONFIRMED_COV_NOTIFICATION = 28,
|
||||
SERVICE_SUPPORTED_UNCONFIRMED_EVENT_NOTIFICATION = 29,
|
||||
SERVICE_SUPPORTED_UNCONFIRMED_PRIVATE_TRANSFER = 30,
|
||||
SERVICE_SUPPORTED_UNCONFIRMED_TEXT_MESSAGE = 31,
|
||||
SERVICE_SUPPORTED_TIME_SYNCHRONIZATION = 32,
|
||||
SERVICE_SUPPORTED_UTC_TIME_SYNCHRONIZATION = 36,
|
||||
SERVICE_SUPPORTED_WHO_HAS = 33,
|
||||
SERVICE_SUPPORTED_WHO_IS = 34,
|
||||
// Other services to be added as they are defined.
|
||||
// All values in this production are reserved
|
||||
// for definition by ASHRAE.
|
||||
MAX_BACNET_SERVICES_SUPPORTED = 40
|
||||
} BACNET_SERVICES_SUPPORTED;
|
||||
|
||||
typedef enum {
|
||||
ACKNOWLEDGMENT_FILTER_ALL = 0,
|
||||
ACKNOWLEDGMENT_FILTER_ACKED = 1,
|
||||
|
||||
+19
-25
@@ -188,9 +188,6 @@ 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
|
||||
@@ -233,7 +230,8 @@ int Device_Encode_Property_APDU(
|
||||
int32_t array_index)
|
||||
{
|
||||
int apdu_len = 0; // return value
|
||||
|
||||
BACNET_BIT_STRING bit_string;
|
||||
|
||||
switch (property)
|
||||
{
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
@@ -292,30 +290,26 @@ int Device_Encode_Property_APDU(
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0], Device_Protocol_Version());
|
||||
break;
|
||||
// BACnet Legacy Support - necessary?
|
||||
//case PROP_PROTOCOL_CONFORMANCE_CLASS:
|
||||
// apdu_len = encode_tagged_unsigned(&apdu[0], 1);
|
||||
// break;
|
||||
// BACnet Legacy Support
|
||||
case PROP_PROTOCOL_CONFORMANCE_CLASS:
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0], 1);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
// FIXME: needs an encoding function for bitstring
|
||||
apdu[0] = 0x85; /* what is following? (this is a bitstring) */
|
||||
apdu[1] = 0x06; /* length extension to 6 bytes */
|
||||
apdu[2] = 0x05; /* 5 unused bits in the final byte */
|
||||
apdu[3] = 0x00; /* none of the first 8 bits are set */
|
||||
apdu[4] = 0x09; /* bits 3,0 are set */
|
||||
apdu[5] = 0x00; /* none of the 3rd set of bits are set */
|
||||
apdu[6] = 0x20; /* bit 5 is set */
|
||||
apdu[7] = 0x20; /* bit 5 is set */
|
||||
apdu_len = 8; /* bytes in this apdu */
|
||||
bitstring_init(&bit_string);
|
||||
// when APDU does automatic reject when service is NULL, then add this
|
||||
//for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++)
|
||||
//{
|
||||
// bitstring_set_bit(&bit_string, i, apdu_service_supported(i));
|
||||
//}
|
||||
bitstring_set_bit(&bit_string, SERVICE_SUPPORTED_WHO_IS, true);
|
||||
bitstring_set_bit(&bit_string, SERVICE_SUPPORTED_I_AM, true);
|
||||
bitstring_set_bit(&bit_string, SERVICE_SUPPORTED_READ_PROPERTY, true);
|
||||
apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
|
||||
// FIXME: needs an encoding function for bitstring
|
||||
apdu[0] = 0x84; /* what is following? (this is a bitstring) */
|
||||
apdu[1] = 0x06; /* 6 unused bits in the final byte */
|
||||
apdu[2] = 0xFF; /* All of the first 8 bits are set */
|
||||
apdu[3] = 0xFF; /* All of the second 8 bits are set */
|
||||
apdu[4] = 0xC0; /* All of the valid bits are set */
|
||||
apdu_len = 5; /* bytes in this apdu */
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
|
||||
apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_OBJECT_LIST:
|
||||
// FIXME: hook into real object list, not just device
|
||||
|
||||
Reference in New Issue
Block a user