/*====================================================================*
 *
 *   Copyright (c) 2013 Qualcomm Atheros, Inc.
 *
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted (subject to the limitations
 *   in the disclaimer below) provided that the following conditions
 *   are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *
 *   * Neither the name of Qualcomm Atheros nor the names of
 *     its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written
 *     permission.
 *
 *   NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
 *   GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
 *   COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 *   PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 *   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 *   OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *--------------------------------------------------------------------*/

/*====================================================================*
 *
 *   slac.h -
 *
 *   this file contains defintions for the HomePlug Green PHY SLAC
 *   protocol;
 *
 *--------------------------------------------------------------------*/

#ifndef SLAC_HEADER
#define SLAC_HEADER

/*====================================================================*
 *   system header files;
 *--------------------------------------------------------------------*/

#include <stdint.h>

/*====================================================================*
 *   custom header files;
 *--------------------------------------------------------------------*/

#include "../tools/types.h"
#include "../tools/endian.h"
#include "../ether/ether.h"
#include "../mme/mme.h"

/*====================================================================*
 *   constants;
 *--------------------------------------------------------------------*/

#define SLAC_DEBUG 1

/*
 * The following two constants control whether or not the PEV or EVSE
 * change AVLN on SLAC protocol cycle; The recommended setting is PEV
 * changes with each pass and the EVSE does not;
 */

#define SLAC_AVLN_PEV 1
#define SLAC_AVLN_EVSE 0

#define SLAC_APPLICATION_PEV_EVSE 0x00

#define SLAC_SECURITY_NONE 0x00
#define SLAC_SECURITY_PUBLIC_KEY 0x01

#define SLAC_RUNID_LEN 8
#define SLAC_UNIQUE_ID_LEN 17
#define SLAC_RND_LEN 16
#define SLAC_NID_LEN 7
#define SLAC_NMK_LEN 16

#define SLAC_MSOUNDS 10
#define SLAC_TIMETOSOUND 6
#define SLAC_TIMEOUT 1000
#define SLAC_APPLICATION_TYPE 0
#define SLAC_SECURITY_TYPE 0
#define SLAC_RESPONSE_TYPE 0
#define SLAC_MSOUND_TARGET "FF:FF:FF:FF:FF:FF"
#define SLAC_FORWARD_STATION "00:00:00:00:00:00"
#define SLAC_GROUPS 58

#define SLAC_LIMIT 40
#define SLAC_PAUSE 20
#define SLAC_SETTLETIME 10
#define SLAC_CHARGETIME 2
#define SLAC_FLAGS 0

#define SLAC_SILENCE   (1 << 0)
#define SLAC_VERBOSE   (1 << 1)
#define SLAC_SESSION   (1 << 2)
#define SLAC_COMPARE   (1 << 3)
#define SLAC_SOUNDONLY (1 << 4)

#define SLAC_CM_SETKEY_KEYTYPE 0x01
#define SLAC_CM_SETKEY_PID 0x04
#define SLAC_CM_SETKEY_PRN 0x00
#define SLAC_CM_SETKEY_PMN 0x00
#define SLAC_CM_SETKEY_CCO 0x00
#define SLAC_CM_SETKEY_EKS 0x01

/*====================================================================*
 *   messages;
 *--------------------------------------------------------------------*/

#ifndef __GNUC__
#pragma pack (push,1)
#endif

typedef struct __packed session

{
	struct session * next;
	struct session * prev;
	byte RunID [SLAC_RUNID_LEN];
	byte APPLICATION_TYPE;
	byte SECURITY_TYPE;
	byte RESP_TYPE;
	byte NUM_SOUNDS;
	byte TIME_OUT;
	byte AAG [SLAC_GROUPS];
	byte NumGroups;
	byte MSOUND_TARGET [ETHER_ADDR_LEN];
	byte FORWARDING_STA [ETHER_ADDR_LEN];
	byte PEV_ID [SLAC_UNIQUE_ID_LEN];
	byte PEV_MAC [ETHER_ADDR_LEN];
	byte EVSE_ID [SLAC_UNIQUE_ID_LEN];
	byte EVSE_MAC [ETHER_ADDR_LEN];
	byte RND [SLAC_UNIQUE_ID_LEN];
	byte NMK [SLAC_NMK_LEN];
	byte NID [SLAC_NID_LEN];
	byte original_nmk [SLAC_NMK_LEN];
	byte original_nid [SLAC_NID_LEN];
	unsigned state;
	unsigned sounds;
	unsigned limit;
	unsigned pause;
	unsigned chargetime;
	unsigned settletime;
	unsigned counter;
	unsigned flags;
	signed exit;
}

session;
typedef struct __packed cm_sta_identity_request

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
}

cm_sta_identity_request;
typedef struct __packed cm_sta_identity_confirm

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t GREEN_PHY_CAPABILITY;
	uint8_t POWER_SAVE_CAPABILITY;
	uint8_t GREEN_PHY_PREFERRED_ALLOCATION_CAPABILITY;
	uint8_t REPEATING_AND_ROUTING_CAPABILITY;
	uint8_t HOMEPLUG_AV_VERSION;
	uint8_t EFL;
	uint8_t EF [1];
}

cm_sta_identity_confirm;
typedef struct __packed cm_slac_param_request

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t APPLICATION_TYPE;
	uint8_t SECURITY_TYPE;
	uint8_t RunID [SLAC_RUNID_LEN];
	uint8_t CipherSuiteSetSize;
	uint16_t CipherSuite [1];
}

cm_slac_param_request;
typedef struct __packed cm_slac_param_confirm

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t MSOUND_TARGET [ETHER_ADDR_LEN];
	uint8_t NUM_SOUNDS;
	uint8_t TIME_OUT;
	uint8_t RESP_TYPE;
	uint8_t FORWARDING_STA [ETHER_ADDR_LEN];
	uint8_t APPLICATION_TYPE;
	uint8_t SECURITY_TYPE;
	uint8_t RunID [SLAC_RUNID_LEN];
	uint16_t CipherSuite;
}

cm_slac_param_confirm;
typedef struct __packed cm_start_atten_char_indicate

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t APPLICATION_TYPE;
	uint8_t SECURITY_TYPE;
	struct __packed
	{
		uint8_t NUM_SOUNDS;
		uint8_t TIME_OUT;
		uint8_t RESP_TYPE;
		uint8_t FORWARDING_STA [ETHER_ADDR_LEN];
		uint8_t RunID [SLAC_RUNID_LEN];
	}
	ACVarField;
}

cm_start_atten_char_indicate;
typedef struct __packed cm_start_atten_char_response

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
}

cm_start_atten_char_response;
typedef struct __packed cm_atten_char_indicate

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t APPLICATION_TYPE;
	uint8_t SECURITY_TYPE;
	struct __packed
	{
		uint8_t SOURCE_ADDRESS [ETHER_ADDR_LEN];
		uint8_t RunID [SLAC_RUNID_LEN];
		uint8_t SOURCE_ID [SLAC_UNIQUE_ID_LEN];
		uint8_t RESP_ID [SLAC_UNIQUE_ID_LEN];
		uint8_t NUM_SOUNDS;
		struct __packed
		{
			uint8_t NumGroups;
			uint8_t AAG [255];
		}
		ATTEN_PROFILE;
	}
	ACVarField;
}

cm_atten_char_indicate;
typedef struct __packed cm_atten_char_response

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t APPLICATION_TYPE;
	uint8_t SECURITY_TYPE;
	struct __packed
	{
		uint8_t SOURCE_ADDRESS [ETHER_ADDR_LEN];
		uint8_t RunID [SLAC_RUNID_LEN];
		uint8_t SOURCE_ID [SLAC_UNIQUE_ID_LEN];
		uint8_t RESP_ID [SLAC_UNIQUE_ID_LEN];
		uint8_t Result;
	}
	ACVarField;
}

cm_atten_char_response;
typedef struct __packed cm_mnbc_sound_indicate

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t APPLICATION_TYPE;
	uint8_t SECURITY_TYPE;
	struct __packed
	{
		uint8_t SenderID [SLAC_UNIQUE_ID_LEN];
		uint8_t CNT;
		uint8_t RunID [SLAC_RUNID_LEN];
		uint8_t RND [SLAC_UNIQUE_ID_LEN];
	}
	MSVarField;
}

cm_mnbc_sound_indcate;
typedef struct __packed cm_validate_request

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t SignalType;
	struct __packed
	{
		uint8_t Timer;
		uint8_t Result;
	}
	VRVarField;
}

cm_validate_request;
typedef struct __packed cm_validate_confirm

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t SignalType;
	struct __packed
	{
		uint8_t ToggleNum;
		uint8_t Result;
	}
	VCVarField;
}

cm_validate_confirm;
typedef struct __packed cm_slac_match_request

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t APPLICATION_TYPE;
	uint8_t SECURITY_TYPE;
	uint16_t MVFLength;
	struct __packed
	{
		uint8_t PEV_ID [SLAC_UNIQUE_ID_LEN];
		uint8_t PEV_MAC [ETHER_ADDR_LEN];
		uint8_t EVSE_ID [SLAC_UNIQUE_ID_LEN];
		uint8_t EVSE_MAC [ETHER_ADDR_LEN];
		uint8_t RunID [SLAC_RUNID_LEN];
		uint8_t RSVD [8];
	}
	MatchVarField;
}

cm_slac_match_request;
typedef struct __packed cm_slac_match_confirm

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t APPLICATION_TYPE;
	uint8_t SECURITY_TYPE;
	uint16_t MVFLength;
	struct __packed
	{
		uint8_t PEV_ID [SLAC_UNIQUE_ID_LEN];
		uint8_t PEV_MAC [ETHER_ADDR_LEN];
		uint8_t EVSE_ID [SLAC_UNIQUE_ID_LEN];
		uint8_t EVSE_MAC [ETHER_ADDR_LEN];
		uint8_t RunID [SLAC_RUNID_LEN];
		uint8_t RSVD1 [8];
		uint8_t NID [SLAC_NID_LEN];
		uint8_t RSVD2;
		uint8_t NMK [SLAC_NMK_LEN];
	}
	MatchVarField;
}

cm_slac_match_confirm;
typedef struct __packed cm_atten_profile_indicate

{
	struct ethernet_hdr ethernet;
	struct homeplug_fmi homeplug;
	uint8_t PEV_MAC [ETHER_ADDR_LEN];
	uint8_t NumGroups;
	uint8_t RSVD;
	uint8_t AAG [255];
}

cm_atten_profile_indicate;

#ifndef __GNUC__
#pragma pack (pop)
#endif

/*====================================================================*
 *   functions;
 *--------------------------------------------------------------------*/

signed pev_cm_slac_param (struct session *, struct channel *, struct message *);
signed pev_cm_start_atten_char (struct session *, struct channel *, struct message *);
signed pev_cm_atten_char (struct session *, struct channel *, struct message *);
signed pev_cm_mnbc_sound (struct session *, struct channel *, struct message *);
signed pev_cm_slac_match (struct session *, struct channel *, struct message *);
signed pev_cm_set_key (struct session *, struct channel *, struct message *);
signed evse_cm_slac_param (struct session *, struct channel *, struct message *);
signed evse_cm_start_atten_char (struct session *, struct channel *, struct message *);
signed evse_cm_atten_char (struct session *, struct channel *, struct message *);
signed evse_cm_mnbc_sound (struct session *, struct channel *, struct message *);
signed evse_cm_slac_match (struct session *, struct channel *, struct message *);
signed evse_cm_set_key (struct session *, struct channel *, struct message *);
signed slac_connect (struct session *);
void slac_session (struct session *);
void slac_structs ();
signed slac_debug (struct session * session, signed status, char const * string, char const * format, ...);

/*====================================================================*
 *
 *--------------------------------------------------------------------*/

#endif



