/****************************************************************************
 File        : mphidflash.h
 Description : Common header file for all mphidflash sources.

 History     : 2009-02-19  Phillip Burgess
                 * Initial implementation
               2009-04-16  Phillip Burgess
                 * Bug fix for non-Intel and 64-bit platforms.
               2009-12-26  Thomas Fischl, Dominik Fisch (www.FundF.net)
                 * Renamed 'ubw32' to 'mphidflash'
               2010-12-28  Petr Olivka
                 * program and verify only data for defined memory areas
                 * send only even length of data to PIC
               
 License     : Copyright (C) 2009 Phillip Burgess
               Copyright (C) 2009 Thomas Fischl, Dominik Fisch (www.FundF.net)
               Copyright (C) 2010 Petr Olivka

               This file is part of 'mphidflash' program.

               'mphidflash' 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
               3 of the License, or (at your option) any later version.

               'mphidflash' 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 'mphidflash' source code.  If not,
               see <http://www.gnu.org/licenses/>.

 ****************************************************************************/

#ifndef _MPHIDFLASH_H_
#define _MPHIDFLASH_H_

/* On Intel architectures, can make some crass endianism optimizations */
#if defined(_WIN64)||defined(_WIN32)
#define bufWrite32(src,pos,val) *(unsigned int *)&src[pos] = val
#define bufRead32(pos)          *(unsigned int *)&usbBuf[pos]
#else
#define bufWrite32(src,pos,val) src[pos    ] =  val        & 0xff; \
                                src[pos + 1] = (val >>  8) & 0xff; \
                                src[pos + 2] = (val >> 16) & 0xff; \
                                src[pos + 3] = (val >> 24)
#define bufRead32(pos)         ( usbBuf[pos    ]        | \
                                (usbBuf[pos + 1] <<  8) | \
                                (usbBuf[pos + 2] << 16) | \
                                (usbBuf[pos + 3] << 24) )
#endif /* i386 || __x86_64__ */

/* Values derived from Microchip HID Bootloader source */

//Bootloader Command From Host - Switch() State Variable Choices
/* Bootloader commands */
#define QUERY_DEVICE                0x02    //Command that the host uses to learn about the device (what regions can be programmed, and what type of memory is the region)
#define UNLOCK_CONFIG               0x03    //Note, this command is used for both locking and unlocking the config bits (see the "//Unlock Configs Command Definitions" below)
#define ERASE_DEVICE                0x04    //Host sends this command to start an erase operation.  Firmware controls which pages should be erased.
#define PROGRAM_DEVICE              0x05    //If host is going to send a full RequestDataBlockSize to be programmed, it uses this command.
#define PROGRAM_COMPLETE            0x06    //If host send less than a RequestDataBlockSize to be programmed, or if it wished to program whatever was left in the buffer, it uses this command.
#define GET_DATA                    0x07    //The host sends this command in order to read out memory from the device.  Used during verify (and read/export hex operations)
#define RESET_DEVICE                0x08    //Resets the microcontroller, so it can update the config bits (if they were programmed, and so as to leave the bootloader (and potentially go back into the main application)
#define SIGN_FLASH                  0x09    //The host PC application should send this command after the verify operation has completed successfully.  If checksums are used instead of a true verify (due to ALLOW_GET_DATA_COMMAND being commented), then the host PC application should send SIGN_FLASH command after is has verified the checksums are as exected. The firmware will then program the SIGNATURE_WORD into flash at the SIGNATURE_ADDRESS.
#define QUERY_EXTENDED_INFO         0x0C    //Used by host PC app to get additional info about the device, beyond the basic NVM layout provided by the query device command

//Unlock Configs Command Definitions
/* Sub-commands for the ERASE_DEVICE command */
#define UNLOCKCONFIG                0x00    //Sub-command for the ERASE_DEVICE command
#define LOCKCONFIG                  0x01    //Sub-command for the ERASE_DEVICE command

//Query Device Response "Types"
#define MEMORY_REGION_PROGRAM_MEM   0x01    //When the host sends a QUERY_DEVICE command, need to respond by populating a list of valid memory regions that exist in the device (and should be programmed)
#define MEMORY_REGION_EEDATA        0x02
#define MEMORY_REGION_CONFIG        0x03
#define MEMORY_REGION_USERID        0x04
#define MEMORY_REGION_END           0xFF    //Sort of serves as a "null terminator" like number, which denotes the end of the memory region list has been reached.
#define BOOTLOADER_V1_01_OR_NEWER_FLAG   0xA5   //Tacked on in the VersionFlag byte, to indicate when using newer version of bootloader with extended query info available


/* Response types for QUERY_DEVICE command */
#define	TypeProgramMemory 0x01
#define TypeEEPROM        0x02
#define TypeConfigWords   0x03
#define	TypeEndOfTypeList 0xFF


/* Device family */ 		
#define DEVICE_FAMILY_PIC18 0x01 		
#define DEVICE_FAMILY_PIC24 0x02 		
#define DEVICE_FAMILY_PIC32 0x03

/* Error codes returned by various functions */

typedef enum
{
	ERR_NONE = 0,        /* Success (non-error) */
	ERR_CMD_ARG,
	ERR_CMD_UNKNOWN,
	ERR_DEVICE_NOT_FOUND,
	ERR_USB_INIT1,
	ERR_USB_INIT2,
	ERR_USB_OPEN,
	ERR_USB_WRITE,
	ERR_USB_READ,
	ERR_HEX_OPEN,
	ERR_HEX_STAT,
	ERR_HEX_MMAP,
	ERR_HEX_SYNTAX,
	ERR_HEX_CHECKSUM,
	ERR_HEX_RECORD,
	ERR_VERIFY,
	ERR_EOL              /* End-of-list, not actual error code */
} ErrorCode;


extern ErrorCode
	hexOpen(char *),
	hexWrite(char),
	usbOpen(unsigned short,unsigned short),
	usbWrite(char,char);
extern void
	hexClose(void),
	usbClose(void),
	hexSetBytesPerAddress(unsigned char);

#pragma pack( push )
#pragma pack( 1 )

typedef struct {
  unsigned char Command;
  unsigned char PacketDataFieldSize;
  unsigned char DeviceFamily;
  struct {
    unsigned char Type;
    unsigned int Address;
    unsigned int Length;
    } mem[ 6 ];
  unsigned char memBlocks;
  unsigned char _fill [ 6 ];
  } sQuery;

extern sQuery devQuery;

typedef unsigned short uint16_t;
typedef unsigned int uint32_t;

typedef  struct
 {
  unsigned char command;
  unsigned char minorVer;
  unsigned char majorVer;
  uint16_t applicationVersion;
  uint32_t signatureAddress;
  uint16_t signatureValue;
  uint32_t erasePageSize;
  unsigned char config1LMask;
  unsigned char config1HMask;
  unsigned char config2LMask;
  unsigned char config2HMask;
  unsigned char config3LMask;
  unsigned char config3HMask;
  unsigned char config4LMask;
  unsigned char config4HMask;
  unsigned char config5LMask;
  unsigned char config5HMask;
  unsigned char config6LMask;
  unsigned char config6HMask;
  unsigned char config7LMask;
  unsigned char config7HMask;
  unsigned char pad[64-29];
 }ExtendedQueryInfo;

#pragma pack( pop )

#endif /* _MPHIDFLASH_H_ */
