You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
4.7 KiB
171 lines
4.7 KiB
/*
|
|
* This code is based on seveal VUSB-Examples the
|
|
* HID was taken from the CapsLocker code from macetech
|
|
* http://macetech.com/blog/?q=node/46
|
|
*
|
|
*/
|
|
#include "main.h"
|
|
|
|
#define MSG "what do ya want for nothing?"
|
|
|
|
#include <avr/io.h>
|
|
#include <avr/wdt.h>
|
|
#include <avr/eeprom.h>
|
|
#include <avr/interrupt.h>
|
|
#include <avr/pgmspace.h>
|
|
#include <util/delay.h>
|
|
#include <stdlib.h>
|
|
|
|
uint8_t reportBuffer[2]; /* buffer for HID reports */
|
|
|
|
static uint8_t next_key=0, prev_key=0xFF;
|
|
static uint8_t sec[SECLEN]=SECRET;
|
|
|
|
uint32_t get_cnt(){
|
|
void* p=(void*)eeprom_read_word(CNTPOS_PTR);
|
|
return eeprom_read_dword(p);
|
|
}
|
|
|
|
uint8_t inc_cnt(){
|
|
uint32_t cnt;
|
|
void* p=(void*)eeprom_read_word(CNTPOS_PTR);
|
|
cnt=eeprom_read_dword(p);
|
|
if(cnt==UINT32_MAX){
|
|
eeprom_write_word(CNTPOS_PTR,ERROR);
|
|
return 0;
|
|
}
|
|
eeprom_write_dword(p,cnt+1);
|
|
|
|
retry:
|
|
if(eeprom_read_dword(p)!=cnt+1){
|
|
eeprom_write_dword(p,cnt+1);
|
|
if(eeprom_read_dword(p)!=cnt+1){
|
|
/*Probabbly the EEPROM position is bad, try an other*/
|
|
p+=4;
|
|
if(p+4>(void*)EEPROM_SIZE){
|
|
eeprom_write_word(CNTPOS_PTR,ERROR);
|
|
return 0;
|
|
}
|
|
eeprom_write_word(CNTPOS_PTR,(uint16_t)p);
|
|
|
|
/* I know some people don't like goto because of dijkstra's
|
|
legendary article "goto considered harmfull". The truth is he
|
|
didn't want us to stop using goto at all, but to think if it
|
|
is appropriate. The alternative here would be a loop around
|
|
this whole block and some well-placed "break" and "continue"
|
|
kbd_event_statements - I think that would be even worse than the goto*/
|
|
|
|
goto retry;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void buildReport(uint8_t mod, uint8_t key){
|
|
reportBuffer[0] = mod;
|
|
reportBuffer[1] = key;
|
|
}
|
|
|
|
void main_fsm(){
|
|
static uint8_t device_state=0;
|
|
static uint8_t prev_btn=0;
|
|
switch(device_state){
|
|
case DEV_STATE_RESET:
|
|
{
|
|
uint32_t cnt;
|
|
if( eeprom_read_word(CNTPOS_PTR)==ERROR ){
|
|
writeToBuffer(USB_KEY_E);
|
|
writeToBuffer(USB_KEY_R);
|
|
writeToBuffer(USB_KEY_R);
|
|
writeToBuffer(USB_KEY_O);
|
|
writeToBuffer(USB_KEY_R);
|
|
}else{
|
|
cnt = get_cnt();
|
|
buffer_unum(get_otp_from_cnt(cnt,8,sec,SECLEN));
|
|
}
|
|
device_state=DEV_STATE_SENT;
|
|
break;
|
|
}
|
|
case DEV_STATE_SENT:
|
|
if( prev_btn!=0 && ((PIN_BTN)&(1<<PBTN))==0 ){
|
|
writeToBuffer(USB_KEY_ENTER);
|
|
inc_cnt();
|
|
device_state=DEV_STATE_CONFIRMED;
|
|
_delay_ms(100);
|
|
}
|
|
break;
|
|
case DEV_STATE_CONFIRMED:
|
|
default:
|
|
if( prev_btn!=0 && ((PIN_BTN)&(1<<PBTN))==0 ){
|
|
device_state=DEV_STATE_RESET;
|
|
_delay_ms(100);
|
|
}
|
|
break;
|
|
}
|
|
prev_btn=(PIN_BTN)&(1<<PBTN);
|
|
}
|
|
|
|
|
|
int main(void){
|
|
#ifdef CALIB
|
|
uint8_t calibrationValue;
|
|
#endif
|
|
|
|
#ifdef CALIB
|
|
/* oszillator calibration */
|
|
calibrationValue = eeprom_read_byte(0); /* calibration value from last time */
|
|
if(calibrationValue != 0xff){
|
|
OSCCAL = calibrationValue;
|
|
}
|
|
#endif //CALLIB
|
|
|
|
usbDeviceDisconnect();
|
|
/* just leave some time for a disconnect/connect sequence mustn't be that exact */
|
|
/* TODO only do this if watchdog was activated*/
|
|
_delay_ms(200);
|
|
usbDeviceConnect();
|
|
|
|
wdt_enable(WDTO_500MS);
|
|
|
|
writeToBuffer(USB_KEY_NOP);
|
|
|
|
/*Set button to input*/
|
|
DDR_BTN &= ~(1<<PBTN);
|
|
/*internal pull-up on*/
|
|
PORT_BTN |= 1<<PBTN;
|
|
|
|
usbInit();
|
|
sei();
|
|
for(;;){
|
|
wdt_reset();
|
|
usbPoll();
|
|
|
|
/* Main FSM*/
|
|
main_fsm();
|
|
|
|
/* Send Keystrokes, if asked to */
|
|
if(usbInterruptIsReady()){
|
|
if(!buff_empty || next_key!=0){
|
|
if(next_key==0){
|
|
next_key=readBuffer();
|
|
}
|
|
if(next_key==prev_key){
|
|
/*we must send a NOP in between otherwise it will be
|
|
interpreted as only one keystroke*/
|
|
buildReport(0x00, USB_KEY_NOP);
|
|
/*set the prev key to something different*/
|
|
prev_key=!next_key;
|
|
}else{
|
|
buildReport(0x00, next_key);
|
|
prev_key=next_key;
|
|
next_key=0;
|
|
}
|
|
}else{
|
|
buildReport(0x00, USB_KEY_NOP);
|
|
}
|
|
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|