TL866/FirmwareDumper/main.c
2018-08-14 18:12:21 +03:00

863 lines
29 KiB
C

/*
* File: main.c
* Author: Radioman
*
* Created on 09 aprilie 2013, 07:20
*/
#include <USB/usb.h>
#include <USB/usb_function_generic.h>
#include "HardwareProfile.h"
#include "config_bits.h"
#include <delays.h>
#include <string.h>
#include <stdlib.h>
//TL866 Ports settings
#define INIT_LATA (0b00010000)
#define INIT_LATB (0b00000010)
#define INIT_LATC (0b00000000)
#define INIT_LATD (0b00000000)
#define INIT_LATE (0b00000000)
#define INIT_LATF (0b00000000)
#define INIT_LATG (0b00010000)
#define INIT_LATH (0b00000000)
#define INIT_LATJ (0b00000000)
#define INIT_TRISA (0b00000000)
#define INIT_TRISB (0b00000001)
#define INIT_TRISC (0b00000000)
#define INIT_TRISD (0b00000000)
#define INIT_TRISE (0b00000000)
#define INIT_TRISF (0b00000000)
#define INIT_TRISG (0b00000000)
#define INIT_TRISH (0b00000000)
#define INIT_TRISJ (0b00000000)
#define LE0 (LATHbits.LATH0)//vpp0
#define LE1 (LATHbits.LATH1)//vpp1
#define LE2 (LATAbits.LATA2)//vcc0
#define LE3 (LATAbits.LATA0)//vcc1
#define LE4 (LATAbits.LATA5)//vcc2
#define LE5 (LATAbits.LATA3)//gnd0
#define LE6 (LATHbits.LATH4)//gnd2
#define LE7 (LATAbits.LATA1)//gnd3
#define OE_VPP (LATGbits.LATG4)//OE_VPP
#define OE_VCC (LATAbits.LATA4)//OE_VCC
#define SR_DAT (LATHbits.LATH2)//shift register data line
#define SR_CLK (LATHbits.LATH3)//shift register clock line (register shift on 1)
#define LED_PIN (LATCbits.LATC0)
#define LED_ON 1
#define LED_OFF 0
#define INPUT_PIN 1
#define OUTPUT_PIN 0
#define FLAG_FALSE 0
#define FLAG_TRUE 1
#define VERSION_A 1
#define VERSION_CS 2
#define READ_VERSION 0x00
#define READ_FLASH 0x01
#define WRITE_BOOTLOADER 0x02
#define WRITE_CONFIG 0x03
#define WRITE_INFO 0x04
#define GET_INFO 0x05
#define GET_PORT_INP 0x80
#define GET_PORT_LAT 0x81
#define GET_PORT_TRIS 0x82
#define SET_PORT_TRIS 0x83
#define SET_PORT_LAT 0x84
#define SET_SHIFTREG 0x85
#define RESET 0xFF
typedef union {
unsigned char _byte[USBGEN_EP_SIZE];
struct {
unsigned char CMD;
unsigned char len;
rom far char *pAdr;
unsigned char data[USBGEN_EP_SIZE - 5];
};
} DATA_PACKET;
extern void _startup(void);
void high_ISR(void);
void low_ISR(void);
/**********************************************REMAPPED VECTORS********************************************************/
#define REMAPPED_RESET_VECTOR_ADDRESS 0x1800
#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x1808
#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x1818
#pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESS
void _reset(void) {
_asm goto _startup _endasm
}
#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS
void Remapped_High_ISR(void) {
_asm goto high_ISR _endasm
}
#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS
void Remapped_Low_ISR(void) {
_asm goto low_ISR _endasm
}
#pragma code HIGH_INTERRUPT_VECTOR = 0x08
void High_ISR(void) {
_asm goto REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS _endasm
}
#pragma code LOW_INTERRUPT_VECTOR = 0x18
void Low_ISR(void) {
_asm goto REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS _endasm
}
#pragma code
/*************************************END REMAPPED VECTORS********************************************************/
#define DEVICE_TYPE_LOCATION 0x11B4 //This ROM location will tell us the device type
#define DEVICE_COPY_PROTECT 0x1FFF9 //Copy protect config byte location
//ROM constants
#pragma romdata _signature = 0x1FBFC
const rom unsigned char sigbytes[] = {0x55, 0xAA, 0xA5, 0x5A};
#pragma romdata
far rom unsigned char devcode[] = {'C', 'o', 'd', 'e', 'd', 'u', 'm', 'p'};
far rom unsigned char serial[] = {
'0', '0', '0', '0', '0', '0', '0', '0',
'0', '0', '0', '0', '0', '0', '0', '0',
'0', '0', '0', '0', '0', '0', '0', '0'
};
far rom unsigned char A_Table[] = {
0xA4, 0x1E, 0x42, 0x8C, 0x3C, 0x76, 0x14, 0xC7, 0xB8, 0xB5, 0x81, 0x4A, 0x13, 0x37, 0x7C, 0x0A,
0xFE, 0x3B, 0x63, 0xC1, 0xD5, 0xFD, 0x8C, 0x39, 0xD1, 0x1F, 0x22, 0xC7, 0x7F, 0x4D, 0x2F, 0x15,
0x71, 0x21, 0xF9, 0x25, 0x33, 0x44, 0x92, 0x93, 0x80, 0xD7, 0xAB, 0x1B, 0xB6, 0x11, 0xA9, 0x5A,
0x88, 0x29, 0xFB, 0xD9, 0xF3, 0x76, 0xAA, 0x47, 0x73, 0xD5, 0x31, 0x06, 0x76, 0x4B, 0x90, 0xEA,
0x11, 0xEB, 0x9C, 0x3D, 0xF2, 0xFA, 0x99, 0x06, 0x96, 0x52, 0x0A, 0x8A, 0xBC, 0x04, 0xC8, 0x14,
0x19, 0x41, 0x52, 0xF2, 0x4D, 0x7B, 0x64, 0xC0, 0x16, 0xC7, 0xCB, 0xE9, 0xC3, 0x86, 0x77, 0x6A,
0xEC, 0x44, 0xD2, 0xD9, 0x61, 0xE0, 0x50, 0xA6, 0x60, 0xED, 0x47, 0xA2, 0x0B, 0x59, 0x02, 0xBD,
0x18, 0x4C, 0x11, 0x14, 0xCB, 0x53, 0xE2, 0x2B, 0x21, 0xBE, 0x96, 0x76, 0x4F, 0x47, 0x0D, 0x1F,
0x6A, 0xF4, 0x43, 0x03, 0x68, 0x3E, 0xE0, 0xFE, 0x47, 0x72, 0x0A, 0x68, 0x8C, 0x58, 0x7E, 0xDF,
0xEF, 0x13, 0xDF, 0x47, 0x55, 0x48, 0x4D, 0x10, 0xFE, 0x82, 0x3A, 0xB7, 0x00, 0xD5, 0x79, 0x90,
0xF4, 0xC2, 0x98, 0xC2, 0xEF, 0x5B, 0x70, 0x93, 0xB4, 0xA7, 0xFA, 0xE6, 0x27, 0x48, 0x65, 0x01,
0x05, 0x5B, 0x65, 0x94, 0xD3, 0xA0, 0xCD, 0xF7, 0x14, 0xDB, 0x60, 0xB4, 0xBF, 0x7A, 0xE4, 0x45,
0xF0, 0x77, 0x79, 0x1F, 0xDE, 0x80, 0x29, 0xEF, 0x0D, 0x56, 0xC0, 0x23, 0xC5, 0x73, 0xDE, 0xAC,
0xC2, 0xEF, 0x4A, 0x02, 0x2D, 0xA4, 0x89, 0x69, 0xCB, 0x91, 0xB0, 0x74, 0x75, 0x7C, 0x76, 0xC7,
0xC8, 0xDB, 0x8D, 0x20, 0x1D, 0xF5, 0x33, 0x99, 0xBB, 0x45, 0x04, 0x27, 0x4C, 0x1F, 0x12, 0x67,
0x8E, 0x96, 0x37, 0x9A, 0x4B, 0x9C, 0xAA, 0xED, 0x8B, 0x6B, 0xD1, 0xFF, 0x08, 0x24, 0x56, 0x9D
};
far rom unsigned char CS_Table[] = {
0x0B, 0x08, 0x07, 0x18, 0xEC, 0xC7, 0xDF, 0x8C, 0xD6, 0x76, 0xCE, 0x10, 0x9F, 0x61, 0x7C, 0xF5,
0x61, 0x09, 0xFB, 0x59, 0xD0, 0x24, 0xB4, 0x4F, 0xCA, 0xE4, 0xA1, 0x3A, 0x30, 0x7C, 0xBD, 0x7A,
0xF5, 0xE1, 0xB9, 0x4B, 0x74, 0xCD, 0xF1, 0xE9, 0x07, 0x0A, 0x9E, 0xF9, 0xD5, 0xED, 0x4D, 0x24,
0xEB, 0x21, 0x90, 0x05, 0x8F, 0xA5, 0xF3, 0x45, 0xD0, 0x18, 0x31, 0x04, 0x62, 0x35, 0xA8, 0x7B,
0xA9, 0x9A, 0x0B, 0xE0, 0x14, 0xCD, 0x57, 0x8A, 0xAC, 0x80, 0x08, 0x56, 0xED, 0x14, 0x8C, 0x49,
0xD4, 0x5D, 0xF8, 0x77, 0x39, 0xA5, 0xFA, 0x23, 0x5F, 0xF3, 0x0E, 0x27, 0xCA, 0x8D, 0xF5, 0x97,
0x50, 0xBB, 0x64, 0xA1, 0x73, 0xCE, 0xF9, 0xB7, 0xEE, 0x61, 0x72, 0xF1, 0x8E, 0xDF, 0x21, 0xAC,
0x43, 0x45, 0x9B, 0x78, 0x77, 0x29, 0xB1, 0x31, 0x9E, 0xFC, 0xA1, 0x6B, 0x0F, 0x8C, 0x8D, 0x13,
0x12, 0xCC, 0x2B, 0x54, 0x3A, 0xD8, 0xBF, 0xB8, 0xF5, 0x34, 0x46, 0x90, 0x61, 0x54, 0xF4, 0x95,
0x61, 0x62, 0xE1, 0xCF, 0xF1, 0x3B, 0x00, 0xB6, 0xB6, 0xBB, 0x50, 0x98, 0xD9, 0x3A, 0x56, 0x3A,
0x16, 0x56, 0xCA, 0xC2, 0x10, 0xF3, 0x91, 0xD4, 0xE8, 0x81, 0xEB, 0xFC, 0x0D, 0x7E, 0xEE, 0x4C,
0x56, 0x3B, 0x33, 0x46, 0x4E, 0xE2, 0xCF, 0xFC, 0xCF, 0xB8, 0x84, 0x75, 0xD2, 0xA0, 0x39, 0x53,
0x85, 0xE1, 0xA8, 0xB3, 0x9E, 0x28, 0x57, 0x55, 0xEF, 0xD1, 0xC9, 0xFD, 0x3B, 0x62, 0xF5, 0x18,
0x49, 0x58, 0xF7, 0xA3, 0x36, 0x27, 0x06, 0x49, 0x0F, 0x7C, 0xA6, 0xCB, 0xA0, 0xC5, 0x1E, 0xA5,
0x86, 0xF3, 0x2D, 0xEF, 0x8C, 0x7E, 0xF9, 0x81, 0x34, 0xAA, 0x48, 0x5A, 0x93, 0x0A, 0xF2, 0x43,
0x62, 0x42, 0x97, 0xAF, 0x53, 0x10, 0x8D, 0xE6, 0xA1, 0x8E, 0x1C, 0x62, 0xEB, 0xB1, 0xEE, 0x79
};
far rom unsigned char config_bytes[] = {
0xA8, 0xF3, 0x05, 0xFF, 0xF8, 0xF6, 0xFF, 0xFF
};
//RAM buffers
#pragma udata big_buffer
unsigned char buffer[0x400]; //1Kbyte data buffer
#pragma udata USB_VARIABLES=0x500
DATA_PACKET rxdatapacket; //USB receive buffer
unsigned char txdatapacket[USBGEN_EP_SIZE]; //USB transmit buffer
#pragma udata CONTEXT_SWITCH=0x700
unsigned long int reset_switch; //Here is the RAM context switch location
#pragma udata
//Used function prototypes
unsigned short crc16(unsigned char *data, unsigned short len);
void decrypt_serial(unsigned char version);
void encrypt_serial(unsigned char version);
void FlashErase(unsigned long address);
void WriteBlock(unsigned long address, unsigned char* buffer);
void WriteBuffer(unsigned long address);
void WriteBootloader(unsigned char version);
void WriteConfig(unsigned char version);
void WriteInfo(unsigned char *info_ptr);
void load_shiftregister(unsigned char value);
void config_io();
void ReadProgMem(void);
void ProcessIo(void);
//Global variables
const far rom unsigned short* crc16Table = (const far rom void*) 0x1FD50; //Pointer to crc16 table in ROM
const far rom unsigned short* infoTable = (const far rom void*) 0x1FD00; //Pointer to encrypted info area (80bytes) in ROM
USB_HANDLE USBOutHandle;
USB_HANDLE USBInHandle;
volatile WORD led_cnt;
unsigned char info[80];
#pragma interruptlow high_ISR
void high_ISR(void) {
#if defined(USB_INTERRUPT)
// Perform USB device tasks
USBDeviceTasks();
#endif
}
#pragma interruptlow low_ISR
void low_ISR(void) {
}
void DeviceReset(void) {
UCONbits.USBEN = 0;
Delay10KTCYx(255);
Delay10KTCYx(255);
Reset();
}
// crc16 CCITT
unsigned short crc16(unsigned char *data, unsigned short len) {
unsigned short crc = 0;
while (len--)
crc = ((crc >> 8) ^ crc16Table[(crc ^ *data++) & 0xFF]);
return crc;
}
//decrypt info array
void decrypt_serial(unsigned char version) {
int i;
unsigned char index;
const far rom unsigned char* xorTableptr = (version == VERSION_A ? &A_Table[0] : &CS_Table[0]);
//Step 1, xoring each element from table with a random value from xortable. Starting index is 0x0A. Index is incremented modulo 256
index = 0x0A;
for (i = 0; i < sizeof (info); i++) {
info[i] ^= xorTableptr[index++];
}
//Step 2 right rotate the whole array by 3 bits.
index = info[sizeof (info) - 1] << 5;
for (i = sizeof (info) - 1; i > 0; i--) {
info[i] = info[i] >> 3 & 0x1F | info[i - 1] << 5;
}
info[0] = info[0] >> 3 & 0x1F | index;
//Step 3, descrambling data; we put each element in the right position. At the end we have the decrypted serial and devcode ;)
for (i = 0; i < sizeof (info) / 2; i += 4) {
index = info[i];
info[i] = info[sizeof (info) - i - 1];
info[sizeof (info) - i - 1] = index;
}
}
//encrypt the info array, ready to be inserted in TL866 firmware.
void encrypt_serial(unsigned char version) {
int i;
unsigned char index;
unsigned short crc;
const far rom unsigned char* xorTableptr = (version == VERSION_A ? A_Table : CS_Table);
//Fill the info array[32-77] with random values.
for (i = 32; i < 78; i++) {
info[i] = (unsigned char) rand() % 0x100;
}
info[34] = 0;
for (i = 5; i < 34; i++)
info[34] += info[i];
crc = crc16(info, sizeof (info) - 2);
info[sizeof (info) - 1] = crc >> 8;
info[sizeof (info) - 2] = crc & 0xFF;
/*Data scrambling. We swap the first byte with the last, the fourth from the beginning with the fourth from the end and so on.
So we have the following 10 swaps:(0-79),(4-75),(8-71),(12-67),(16-63),(20-59),(24-55),(28-51),(32-47),(36-43).
*/
for (i = 0; i < sizeof (info) / 2; i += 4) {
index = info[i];
info[i] = info[sizeof (info) - i - 1];
info[sizeof (info) - i - 1] = index;
//printf("(%d-%d),",i,s-i-1);
}
/*
* Step 2, Left rotate the whole array by 3 bits.
*/
index = info[0] >> 5;
for (i = 0; i < sizeof (info) - 1; i++) {
info[i] = info[i] << 3 & 0xF8 | info[i + 1] >> 5;
}
info[sizeof (info) - 1] = info[sizeof (info) - 1] << 3 & 0xF8 | index;
//Last step, xoring each info table value with a random number from xortable. The start index in this table is 0x0A. Index is incremented modulo 256
index = 0x0A;
for (i = 0; i < sizeof (info); i++) {
info[i] ^= xorTableptr[index++];
}
}
//Erase flash page
void FlashErase(unsigned long address) {
TBLPTR = address;
EECON1 = 0b00010100;
INTCONbits.GIE = 0;
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1bits.WR = 1;
EECON1bits.WREN = 0;
INTCONbits.GIE = 1;
}
//Write a 64 byte block of data
void WriteBlock(unsigned long address, unsigned char* buffer) {
unsigned char i;
TBLPTR = address;
EECON1 = 0b00000100;
for (i = 0; i < 64; i++) {
TABLAT = buffer[i];
_asm tblwtpostinc _endasm
}
TBLPTR = address;
INTCONbits.GIE = 0;
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1bits.WR = 1;
EECON1bits.WREN = 0;
INTCONbits.GIE = 1;
}
//Write 1Kbyte buffer to flash
void WriteBuffer(unsigned long address) {
unsigned char i;
unsigned char *buffer_ptr = &buffer[0];
for (i = 0; i < 16; i++) {
WriteBlock(address, buffer_ptr);
buffer_ptr += 64;
address += 64;
}
}
//Rewrite bootloader
void WriteBootloader(unsigned char version) {
unsigned char i;
unsigned long addr = 0;
WriteConfig(version);
for (i = 0; i < 6; i++) {
memcpypgm2ram(buffer, (const far rom void*) addr, 0x400); //copy 1024bytes from flash to buffer
if (i == 4) {
buffer[0x1B4] = version;
}
FlashErase(addr); //erase data block
WriteBuffer(addr); //write data block
addr += 0x400; //next data block
}
}
//Rewrite config area
void WriteConfig(unsigned char version) {
unsigned char t;
unsigned long addr = 0x1FC00;
const far rom unsigned char* xorTableptr = (version == VERSION_A ? &A_Table[0] : &CS_Table[0]);
memcpypgm2ram(buffer, (const far rom void*) addr, 0x400); //copy 1024bytes from flash to buffer
memcpypgm2ram(&t, (const far rom void*) DEVICE_TYPE_LOCATION, 1);
memcpypgm2ram(&info[0], infoTable, 80);
decrypt_serial(t);
encrypt_serial(version);
memcpy(buffer + 0x100, (void*) &info[0], 80); //copy the info array to buffer
memcpypgm2ram(buffer, xorTableptr, 0x100); //copy xortable to buffer
FlashErase(addr); //erase data block
WriteBuffer(addr); //write data block
}
//Rewrite Info
void WriteInfo(unsigned char *info_ptr) {
unsigned char t;
unsigned long addr = 0x1FC00;
memcpypgm2ram(&t, (const far rom void*) DEVICE_TYPE_LOCATION, 1);
memcpypgm2ram(buffer, (const far rom void*) addr, 0x400); //copy 1024bytes from flash to buffer
memcpy(&info[0], (void*) info_ptr, 32); //copy device and serial code received over the usb to info array
encrypt_serial(t); //encrypt the info array with (t) version of the key
memcpy(buffer + 0x100, (void*) &info[0], 80); //copy the info array to buffer
FlashErase(addr); //erase data block
WriteBuffer(addr); //write data block
}
/* Test routine */
void load_shiftregister(unsigned char value) {
unsigned char i;
for (i = 0; i <= 7; i++) {
SR_DAT = (value & 0x80) ? 1 : 0;
value <<= 1;
SR_CLK = 1;
Delay10TCYx(2);
SR_CLK = 0;
Delay10TCYx(2);
}
}
void config_io() {
OSCTUNEbits.PLLEN = 1; //Enable the PLL and wait 2+ms until the PLL locks before enabling USB module
Delay10KTCYx(20);
WDTCONbits.ADSHR = 1; // Select alternate SFR location to access ANCONx registers
ANCON0 = 0xFF; // Default all pins to digital
ANCON1 = 0xFF; // Default all pins to digital
WDTCONbits.ADSHR = 0; // Select normal SFR locations
USBOutHandle = 0;
USBInHandle = 0;
USBDeviceInit();
LATA = INIT_LATA;
LATB = INIT_LATB;
LATC = INIT_LATC;
LATD = INIT_LATD;
LATE = INIT_LATE;
LATF = INIT_LATF;
LATG = INIT_LATG;
LATH = INIT_LATH;
LATJ = INIT_LATJ;
TRISA = INIT_TRISA;
TRISB = INIT_TRISB;
TRISC = INIT_TRISC;
TRISD = INIT_TRISD;
TRISE = INIT_TRISE;
TRISF = INIT_TRISF;
TRISG = INIT_TRISG;
TRISH = INIT_TRISH;
TRISJ = INIT_TRISJ;
//Init IO expander
load_shiftregister(0);
LE0 = 1; //vpp0
LE1 = 1; //vpp1
LE5 = 1; //gnd0
LE6 = 1; //gnd1
LE7 = 1; //gnd2
Delay10TCYx(2);
LE0 = 0; //vpp0
LE1 = 0; //vpp1
LE5 = 0; //gnd0
LE6 = 0; //gnd1
LE7 = 0; //gnd2
Delay10TCYx(2);
load_shiftregister(0xFF);
LE2 = 1; //vcc0
LE3 = 1; //vcc1
LE4 = 1; //vcc2
Delay10TCYx(2);
LE2 = 0; //vcc0
LE3 = 0; //vcc1
LE4 = 0; //vcc2
Delay10TCYx(2);
OE_VPP = 1;
OE_VCC = 1;
LED_PIN = 0;
}
void ReadProgMem(void) {
memcpypgm2ram(&txdatapacket[0], (const far rom void*) rxdatapacket.pAdr, rxdatapacket.len);
}
// Process USB commands
void ProcessIo(void) {
static unsigned char count = 0;
if (USBSuspendControl == 1) {
return;
}
if (USBDeviceState < CONFIGURED_STATE) {
if (--led_cnt == 0) {
LED_PIN ^= 1;
}
return;
}
if (led_cnt != 0) {
LED_PIN = 1;
led_cnt--;
} else
LED_PIN = 0;
if (count) {
if (!USBHandleBusy(USBInHandle)) {
USBInHandle = USBGenWrite(USBGEN_EP_NUM, (BYTE*) & txdatapacket, count);
count = 0;
}
return;
}
if (!USBHandleBusy(USBOutHandle)) {
led_cnt = 5000U;
count = 0;
switch (rxdatapacket.CMD) {
case RESET: // reset device
reset_switch = 0x55AA55AA;
DeviceReset();
break;
case READ_VERSION://get device state
txdatapacket[0] = 0; //echo
txdatapacket[1] = 1; //normal mode
txdatapacket[2] = 33; //Length of devcode+serial+firmware version (LSB)
txdatapacket[3] = 0; //Length of devcode+serial+firmware version (MSB)
txdatapacket[4] = 0; //minor version
txdatapacket[5] = 0; //major version
txdatapacket[39] = 1; //Hardware version
memcpypgm2ram(&txdatapacket[6], (const far rom void*) DEVICE_TYPE_LOCATION, 1);
memcpypgm2ram(&txdatapacket[7], (const far rom void*) devcode, 8);
memcpypgm2ram(&txdatapacket[15], (const far rom void*) serial, 24);
count = 40;
break;
case READ_FLASH:
ReadProgMem();
count = rxdatapacket.len;
break;
case WRITE_BOOTLOADER:
WriteBootloader(rxdatapacket._byte[1]);
txdatapacket[0] = WRITE_BOOTLOADER;
count = 1;
break;
case WRITE_CONFIG:
memcpypgm2ram(buffer, (const far rom void*) 0x1FC00, 0x400); //copy 1024bytes from flash in buffer
memcpypgm2ram(&buffer[0x3F8], (const far rom void*) config_bytes, 8); //Overwrite config bytes with default one
if (!rxdatapacket._byte[1])//check for copy protect bit
{
buffer[0x3F9] |= 0x4; //Clear copy protect bit
}
FlashErase(0x1FC00); //erase data block
WriteBuffer(0x1FC00); //write data block
txdatapacket[0] = WRITE_CONFIG;
count = 1;
break;
case WRITE_INFO:
WriteInfo(&rxdatapacket._byte[1]);
//DeviceReset();
txdatapacket[0] = WRITE_INFO;
count = 1;
break;
case GET_INFO:
memcpypgm2ram(&txdatapacket[32], (const far rom void*) DEVICE_TYPE_LOCATION, 1); //get the bootloader version
memcpypgm2ram(&txdatapacket[33], (const far rom void*) DEVICE_COPY_PROTECT, 1); //get the copy protect byte
memcpypgm2ram(&info[0], infoTable, 80); //copy the encrypted info array
decrypt_serial(txdatapacket[32]); //decrypt the info array
memcpy(txdatapacket, (void*) info, 32);
txdatapacket[33] &= 0x4;
count = 34;
break;
case GET_PORT_INP: // Get Port INP
count = 1;
switch (rxdatapacket._byte[1]) {
case 0:
txdatapacket[0] = PORTA;
break;
case 1:
txdatapacket[0] = PORTB;
break;
case 2:
txdatapacket[0] = PORTC;
break;
case 3:
txdatapacket[0] = PORTD;
break;
case 4:
txdatapacket[0] = PORTE;
break;
case 5:
txdatapacket[0] = PORTF;
break;
case 6:
txdatapacket[0] = PORTG;
break;
case 7:
txdatapacket[0] = PORTH;
break;
case 8:
txdatapacket[0] = PORTJ;
break;
default:
count = 0;
break;
}
break;
case GET_PORT_LAT: // Get Port LAT
count = 1;
switch (rxdatapacket._byte[1]) {
case 0:
txdatapacket[0] = LATA;
break;
case 1:
txdatapacket[0] = LATB;
break;
case 2:
txdatapacket[0] = LATC;
break;
case 3:
txdatapacket[0] = LATD;
break;
case 4:
txdatapacket[0] = LATE;
break;
case 5:
txdatapacket[0] = LATF;
break;
case 6:
txdatapacket[0] = LATG;
break;
case 7:
txdatapacket[0] = LATH;
break;
case 8:
txdatapacket[0] = LATJ;
break;
default:
count = 0;
break;
}
break;
case GET_PORT_TRIS: // Get Port TRIS
count = 1;
switch (rxdatapacket._byte[1]) {
case 0:
txdatapacket[0] = TRISA;
break;
case 1:
txdatapacket[0] = TRISB;
break;
case 2:
txdatapacket[0] = TRISC;
break;
case 3:
txdatapacket[0] = TRISD;
break;
case 4:
txdatapacket[0] = TRISE;
break;
case 5:
txdatapacket[0] = TRISF;
break;
case 6:
txdatapacket[0] = TRISG;
break;
case 7:
txdatapacket[0] = TRISH;
break;
case 8:
txdatapacket[0] = TRISJ;
break;
default:
count = 0;
break;
}
break;
case SET_PORT_TRIS://Set ports Tris value
switch (rxdatapacket._byte[1]) {
case 0:
if (rxdatapacket._byte[3])
TRISA |= (1U << rxdatapacket._byte[2]);
else
TRISA &= ~(1U << rxdatapacket._byte[2]);
break;
case 1:
if (rxdatapacket._byte[3])
TRISB |= (1U << rxdatapacket._byte[2]);
else
TRISB &= ~(1U << rxdatapacket._byte[2]);
break;
case 2:
if (rxdatapacket._byte[3])
TRISC |= (1U << rxdatapacket._byte[2]);
else
TRISC &= ~(1U << rxdatapacket._byte[2]);
break;
case 3:
if (rxdatapacket._byte[3])
TRISD |= (1U << rxdatapacket._byte[2]);
else
TRISD &= ~(1U << rxdatapacket._byte[2]);
break;
case 4:
if (rxdatapacket._byte[3])
TRISE |= (1U << rxdatapacket._byte[2]);
else
TRISE &= ~(1U << rxdatapacket._byte[2]);
break;
case 5:
if (rxdatapacket._byte[3])
TRISF |= (1U << rxdatapacket._byte[2]);
else
TRISF &= ~(1U << rxdatapacket._byte[2]);
break;
case 6:
if (rxdatapacket._byte[3])
TRISG |= (1U << rxdatapacket._byte[2]);
else
TRISG &= ~(1U << rxdatapacket._byte[2]);
break;
case 7:
if (rxdatapacket._byte[3])
TRISH |= (1U << rxdatapacket._byte[2]);
else
TRISH &= ~(1U << rxdatapacket._byte[2]);
break;
case 8:
if (rxdatapacket._byte[3])
TRISJ |= (1U << rxdatapacket._byte[2]);
else
TRISJ &= ~(1U << rxdatapacket._byte[2]);
break;
default:
break;
}
break;
case SET_PORT_LAT://Set ports Lat value
switch (rxdatapacket._byte[1]) {
case 0:
if (rxdatapacket._byte[3])
LATA |= (1U << rxdatapacket._byte[2]);
else
LATA &= ~(1U << rxdatapacket._byte[2]);
break;
case 1:
if (rxdatapacket._byte[3])
LATB |= (1U << rxdatapacket._byte[2]);
else
LATB &= ~(1U << rxdatapacket._byte[2]);
break;
case 2:
if (rxdatapacket._byte[3])
LATC |= (1U << rxdatapacket._byte[2]);
else
LATC &= ~(1U << rxdatapacket._byte[2]);
break;
case 3:
if (rxdatapacket._byte[3])
LATD |= (1U << rxdatapacket._byte[2]);
else
LATD &= ~(1U << rxdatapacket._byte[2]);
break;
case 4:
if (rxdatapacket._byte[3])
LATE |= (1U << rxdatapacket._byte[2]);
else
LATE &= ~(1U << rxdatapacket._byte[2]);
break;
case 5:
if (rxdatapacket._byte[3])
LATF |= (1U << rxdatapacket._byte[2]);
else
LATF &= ~(1U << rxdatapacket._byte[2]);
break;
case 6:
if (rxdatapacket._byte[3])
LATG |= (1U << rxdatapacket._byte[2]);
else
LATG &= ~(1U << rxdatapacket._byte[2]);
break;
case 7:
if (rxdatapacket._byte[3])
LATH |= (1U << rxdatapacket._byte[2]);
else
LATH &= ~(1U << rxdatapacket._byte[2]);
break;
case 8:
if (rxdatapacket._byte[3])
LATJ |= (1U << rxdatapacket._byte[2]);
else
LATJ &= ~(1U << rxdatapacket._byte[2]);
break;
default:
break;
}
break;
case SET_SHIFTREG:
load_shiftregister(rxdatapacket._byte[1]);
break;
default: // Unknown command received
break;
}
//rearm Out Endpoint
USBOutHandle = USBGenRead(USBGEN_EP_NUM, (BYTE*) & rxdatapacket, USBGEN_EP_SIZE);
}
}
// USB callback function handler
BOOL USER_USB_CALLBACK_EVENT_HANDLER(int event, void *pdata, WORD size) {
switch (event) {
case EVENT_CONFIGURED:
//Enable the application endpoints
USBEnableEndpoint(USBGEN_EP_NUM, USB_OUT_ENABLED | USB_IN_ENABLED | USB_HANDSHAKE_ENABLED | USB_DISALLOW_SETUP);
USBOutHandle = USBGenRead(USBGEN_EP_NUM, (BYTE*) & rxdatapacket, USBGEN_EP_SIZE);
break;
default:
break;
}
return TRUE;
}
void main() {
USBOutHandle = 0;
USBInHandle = 0;
led_cnt = 1;
config_io();
srand(0); //initialize the random number generator
#if defined (USB_INTERRUPT)
USBDeviceAttach();
#endif
while (1) {
#if defined(USB_POLLING)
USBDeviceTasks();
#endif
ProcessIo();
}
}