Initial checkin.
This commit is contained in:
commit
d853bc95d9
|
@ -0,0 +1,13 @@
|
|||
*.hex
|
||||
*.bin
|
||||
*.eep
|
||||
*.o
|
||||
*.elf
|
||||
*.map
|
||||
*.lss
|
||||
*.lst
|
||||
*.d
|
||||
*.sym
|
||||
.idea
|
||||
|
||||
LUFA/
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2014 flabbergast at sdfeu dott org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,81 @@
|
|||
# sha204_playground
|
||||
|
||||
Firmware for ATMEL chips to communicate with ATSHA204 chip interactively
|
||||
over Serial. Sources are supplied in two forms:
|
||||
|
||||
- As AVR-GCC project utilizing the [LUFA] library (for USB capable
|
||||
ATMEL chips, tested on atmega32U4 and atxmega128a3u).
|
||||
- As an [Arduino] sketch.
|
||||
|
||||
Along with this, a python script `talk_to_sha204.py` is provided to
|
||||
access some of the functionality of the ATSHA204 chip, talking to
|
||||
it via the firmware above (in a binary mode), a-la [hashlet].
|
||||
|
||||
## Usage / Installation
|
||||
|
||||
Please see the READMEs in the individual subdirectories for some info on
|
||||
how to use them.
|
||||
|
||||
## Pictures
|
||||
|
||||
The original impetus to write this stuff for me was that I had a couple
|
||||
of ATSHA204 breakout boards from [Sparkfun] and I wanted to play with
|
||||
them outside Arduino, using just avr-gcc and [LUFA], on some USB sticks
|
||||
with ATMEL chips. Here are pics with two of them:
|
||||
|
||||
![A pic of atmega32U4 USB stick with ATSHA204](https://dl.dropboxusercontent.com/u/638633/scriptogram/sha204_m32u4_stick.jpg "atmega32u4 USB stick with ATSHA204")
|
||||
|
||||
And matrixstorm's [AVR stick] with the same Sparkfun's ATSHA breakout:
|
||||
|
||||
![A pic of AVR stick with ATSHA204](https://dl.dropboxusercontent.com/u/638633/scriptogram/sha204_avrstick.jpg "AVR stick with ATSHA204")
|
||||
|
||||
|
||||
## Idle thoughts / ramblings
|
||||
|
||||
So, what can be ATSHA204 used for? Well, it performs hashing (SHA256)
|
||||
and it can securely store "keys" (32 bytes long blocks of data).
|
||||
|
||||
The important point (for me) is that to verify that a "signature" (hash,
|
||||
MAC) was generated on a particular ATSHA requires knowing all the
|
||||
"secrets" that were used to generate the signature. This works fine for
|
||||
Client/Server-like situations: "Client" ATSHA generates a signature for,
|
||||
say, a file, (e.g. on a local computer), which is then sent to "Server"
|
||||
for verification. However the "Server" has to know the "secret keys" on
|
||||
ATSHA that were used in the signature computation; so either the
|
||||
"Server" has a copy of the keys stored in ATSHA, or there's another
|
||||
ATSHA on the "Server" with the keys.
|
||||
|
||||
This kind of thing can be used for instance to roll one's own
|
||||
authentication service a-la [YubiKey].
|
||||
|
||||
What I wanted to use it for is to securely store encryption keys
|
||||
locally, for a "two-factor key storage". This is also possible to do:
|
||||
user enters a password, this is passed to ATSHA which generates a hash
|
||||
of the user's password, together with one of its "secret keys". This
|
||||
hash is then used as an encryption key. So to obtain the
|
||||
encryption key, one has to know the password and have the ATSHA along.
|
||||
|
||||
## Notes
|
||||
|
||||
Please see the READMEs in the individual subdirectories for more info
|
||||
about the various parts of the project, as well as credits.
|
||||
|
||||
## TODO / Roadmap
|
||||
|
||||
- Make also binary-mode-only versions of the firmware (for smaller than
|
||||
32kB chips).
|
||||
|
||||
## License
|
||||
|
||||
My code is (c) flabbergast. MIT license (see LICENSE file). Portions
|
||||
of the code come from LUFA demos, this is licensed by LUFA's license.
|
||||
The original code from SHA204 library is licensed by Apache V2.0 license.
|
||||
|
||||
|
||||
[AVRstick]: http://matrixstorm.com/avr/avrstick/
|
||||
[LUFA]: http://www.fourwalledcubicle.com/LUFA.php
|
||||
[hashlet]: https://github.com/cryptotronix/hashlet
|
||||
[YubiKey]: https://www.yubico.com/products/yubikey-hardware/yubikey-2/
|
||||
[Arduino]: http://www.arduino.cc/
|
||||
[Sparkfun]: https://www.sparkfun.com/products/11551
|
||||
[AVR stick]: http://matrixstorm.com/avr/avrstick/
|
|
@ -0,0 +1,47 @@
|
|||
# sha204_playground firmware: Arduino version
|
||||
|
||||
## Installation / usage
|
||||
|
||||
Copy the `avr/SHA204` library to your Arduino IDE's `libraries` folder,
|
||||
and copy the sketch `sha204_playground_arduino` to your sketchbook.
|
||||
|
||||
Make the modifications to the library file
|
||||
`SHA204/SHA204SWI_hardware_config.h` to match your hardware setup (i.e.
|
||||
to which pin is your ATSHA204 connected to).
|
||||
|
||||
Compile and upload the sketch to your Arduino using IDE. Open the IDE's
|
||||
Serial Monitor to talk to the Arduino/ATSHA204.
|
||||
|
||||
Note that I've tested on Arduino IDE version 1.0.5.
|
||||
|
||||
## Problems
|
||||
|
||||
Arduino sets the size of the Serial buffer to 64. This seems to cause
|
||||
problems when the data sent to firmware is longer than that (which it is
|
||||
for instance with the `talk_to_sha204 check_mac` command). If things
|
||||
work, but you get a weird error with this command, increase the size of
|
||||
the Serial buffer. Unfortunately, this requires editing a file in the
|
||||
Arduino directory:
|
||||
`<ARDUINO_APP_DIR>/<MAYBE_SOME_MORE_DIRS/hardware/arduino/cores/arduino/HardwareSerial.cpp`,
|
||||
change `#define SERIAL_BUFFER_SIZE 64` to `#define SERIAL_BUFFER_SIZE
|
||||
100`.
|
||||
|
||||
## Communicating with the firmware
|
||||
|
||||
Probably the first thing to try is pressing `k` (to test waking the
|
||||
ATSHA up) and pressing `s` (to print the serial number of your device).
|
||||
|
||||
Alternatively (depending on the functionality required), you can use the
|
||||
`talk_to_sha204.py` script to talk to the ATSHA via this firmware.
|
||||
|
||||
### Binary mode
|
||||
|
||||
The firmware supports a "binary mode", for use with scripts. For a
|
||||
demonstration on how this is done, have a look at the python script
|
||||
`talk_to_sha204.py`.
|
||||
|
||||
## License
|
||||
|
||||
My code is (c) flabbergast. MIT license (see LICENSE file). Portions
|
||||
of the code come from LUFA demos, this is licensed by LUFA's license.
|
||||
The original code from SHA204 library is licensed by Apache V2.0 license.
|
|
@ -0,0 +1,810 @@
|
|||
/*
|
||||
* sha204_playground.ino
|
||||
* (c) 2014 flabbergast
|
||||
*
|
||||
* Firmware for USB capable ATMEL chips (tested on atmega32U4 and
|
||||
* atxmega128a3u) to communicate with ATSHA204 (single-wire
|
||||
* interface) interactively, over Serial.
|
||||
*
|
||||
* The code is quite ugly ... one reason being that it's just an Arduino adaptatation
|
||||
* of the original avr-gcc/LUFA code, so some of the things are unnecessarily complicated.
|
||||
* I like to keep it this way, so that it's easier to merge any patches/changes to the
|
||||
* original code.
|
||||
*/
|
||||
|
||||
#include "SHA204SWI.h"
|
||||
#include "SHA204Definitions.h" // for constants and such
|
||||
#include "SHA204ReturnCodes.h" // want messages for return codes
|
||||
|
||||
/*************************************************************************
|
||||
* ----------------------- Global variables -----------------------------*
|
||||
*************************************************************************/
|
||||
|
||||
// when this byte is received, switch to binary mode
|
||||
#define BINARY_MODE_CHAR 0xFD
|
||||
|
||||
#define MAX_BUFFER_SIZE 100
|
||||
volatile uint8_t idle = 0;
|
||||
volatile uint8_t hexprint_separator = ' ';
|
||||
|
||||
SHA204SWI sha204;
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* ----------------------- Helper functions -----------------------------*
|
||||
*************************************************************************/
|
||||
void hexprint(uint8_t *p, uint16_t length);
|
||||
void hexprint_noln(uint8_t *p, uint16_t length);
|
||||
void hexprint_byte(uint8_t b);
|
||||
void hexprint_byte_sep(uint8_t b);
|
||||
|
||||
uint8_t get_bytes_serial(uint8_t *output, uint16_t len);
|
||||
void print_help(void);
|
||||
void print_executing(void);
|
||||
void print_received_from_sha(uint8_t *rx_buffer);
|
||||
void print_execute_params(uint8_t opcode, uint8_t param1);
|
||||
void print_return_code(uint8_t code);
|
||||
|
||||
void process_config(uint8_t *config);
|
||||
void sleep_or_idle(SHA204SWI *sha204);
|
||||
uint8_t receive_serial_binary_transaction(uint8_t *buffer, uint8_t len);
|
||||
uint8_t binary_mode_transaction(uint8_t *data, uint8_t rxsize, uint8_t *rx_buffer, SHA204SWI *sha204);
|
||||
#define BINARY_TRANSACTION_OK 0
|
||||
#define BINARY_TRANSACTION_RECEIVE_ERROR 1
|
||||
#define BINARY_TRANSACTION_PARAM_ERROR 2
|
||||
#define BINARY_TRANSACTION_EXECUTE_ERROR 3
|
||||
|
||||
/* A hack so that I don't have to edit too much code from the original AVR code */
|
||||
// Declarations originally from LufaLayer.h
|
||||
uint16_t usb_serial_available(void); // number of getchars guaranteed to succeed immediately
|
||||
int16_t usb_serial_getchar(void); // negative values mean error in receiving (not connected or no input)
|
||||
void usb_serial_putchar(uint8_t ch);
|
||||
void usb_serial_write(const char* const buffer);
|
||||
void usb_serial_write_P(PGM_P data);;
|
||||
uint16_t usb_serial_readline(char *buffer, const uint16_t buffer_size, const bool obscure_input); // BLOCKING (takes care of _tasks)
|
||||
#define W(s) Serial.print(F(s))
|
||||
#define Wl(s) Serial.println(F(s))
|
||||
|
||||
/* Setup */
|
||||
void setup(void)
|
||||
{
|
||||
sha204.power_up();
|
||||
|
||||
/* Initialisation */
|
||||
Serial.begin(115200);
|
||||
|
||||
print_help();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
/* Variables */
|
||||
uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
|
||||
uint8_t tx_buffer[MAX_BUFFER_SIZE];
|
||||
uint8_t configuration_zone[88];
|
||||
uint8_t r;
|
||||
uint8_t param1;
|
||||
uint16_t param2;
|
||||
uint8_t data1[32];
|
||||
uint8_t data2[32];
|
||||
uint8_t data3[14];
|
||||
|
||||
// main serial processing
|
||||
if(usb_serial_available() > 0) {
|
||||
byte c = (byte)usb_serial_getchar();
|
||||
if(c==BINARY_MODE_CHAR) { // handle binary mode for one transaction
|
||||
r = receive_serial_binary_transaction(tx_buffer, MAX_BUFFER_SIZE); // blocking
|
||||
if(r == BINARY_TRANSACTION_OK)
|
||||
r = binary_mode_transaction(tx_buffer, SHA204_RSP_SIZE_MAX, rx_buffer, &sha204); // blocking
|
||||
// transmit the response
|
||||
usb_serial_putchar(r);
|
||||
if(r == BINARY_TRANSACTION_OK)
|
||||
for(r=0; r<rx_buffer[0]; r++)
|
||||
usb_serial_putchar(rx_buffer[r]);
|
||||
} else {
|
||||
if(idle)
|
||||
Wl("--- I ---");
|
||||
else
|
||||
Wl("--- S ---");
|
||||
switch(c) { // yes, code like this sucks
|
||||
case 's': // serial number
|
||||
Wl("Request serial number.");
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.serialNumber(rx_buffer);
|
||||
print_executing();
|
||||
print_return_code(r);
|
||||
Wl("Should get: 01 23 xx xx xx xx xx xx EE");
|
||||
W("Received SN: ");
|
||||
hexprint(rx_buffer, 9);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
break;
|
||||
case 'o': // config zone
|
||||
Wl("Request and display config zone contents.");
|
||||
print_executing();
|
||||
memset(configuration_zone,0,32);
|
||||
if(!(r=sha204.wakeup(rx_buffer))) { // read first 2 32-byte blocks manually
|
||||
if(!(r=sha204.read(tx_buffer,rx_buffer,SHA204_ZONE_CONFIG|READ_ZONE_MODE_32_BYTES,0))) {
|
||||
memcpy(configuration_zone,rx_buffer+1,32);
|
||||
if(!(r=sha204.read(tx_buffer,rx_buffer,SHA204_ZONE_CONFIG|READ_ZONE_MODE_32_BYTES,32))) {
|
||||
memcpy(configuration_zone+32, rx_buffer+1, 32);
|
||||
uint8_t addr = 64; // have to read the rest of the zone in 4-byte blocks
|
||||
while(addr < 88) {
|
||||
if((r=sha204.read(tx_buffer,rx_buffer,SHA204_ZONE_CONFIG,addr)))
|
||||
break;
|
||||
memcpy(configuration_zone+addr, rx_buffer+1, 4);
|
||||
addr+=4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
if(!r)
|
||||
process_config(configuration_zone);
|
||||
break;
|
||||
case 'c': // check_mac
|
||||
Wl("Calculate and compare MAC (CheckMAC command).");
|
||||
Wl("Enter mode (1 byte; default 0):");
|
||||
param1 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param1 = tx_buffer[0];
|
||||
Wl("Enter Slot ID (1 byte; default 0):");
|
||||
param2 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param2 = tx_buffer[0];
|
||||
Wl("Enter client challenge (32 bytes; default 0):");
|
||||
memset((void *)data1, 0, 32);
|
||||
get_bytes_serial(data1, 32);
|
||||
Wl("Enter client response (32 bytes; default 0):");
|
||||
memset((void *)data2, 0, 32);
|
||||
get_bytes_serial(data2, 32);
|
||||
Wl("Enter other data (13 bytes; default 0):");
|
||||
memset((void *)data3, 0, 13);
|
||||
get_bytes_serial(data3, 13);
|
||||
print_execute_params(SHA204_CHECKMAC,param1);
|
||||
hexprint_byte_sep((uint8_t)param2);
|
||||
W("data1 ");
|
||||
hexprint(data1, 32);
|
||||
W("data2 ");
|
||||
hexprint(data2, 32);
|
||||
W("data3 ");
|
||||
hexprint(data3, 13);
|
||||
print_executing();
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.check_mac(tx_buffer, rx_buffer, param1, param2, data1, data2, data3);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case 'd': // derive_key
|
||||
Wl("Combine current key with nonce and store in a key slot (DeriveKey command).");
|
||||
Wl("Enter random (1 byte: 00 or 04; default 0):");
|
||||
param1 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param1 = tx_buffer[0];
|
||||
Wl("Enter Target Slot ID (1 byte; default 0):");
|
||||
param2 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param2 = tx_buffer[0];
|
||||
Wl("Enter MAC for validation (0 or 32 bytes; default 0):");
|
||||
memset((void *)data1, 0, 32);
|
||||
get_bytes_serial(data1, 32);
|
||||
print_execute_params(SHA204_DERIVE_KEY,param1);
|
||||
hexprint_byte_sep((uint8_t)param2);
|
||||
W("data1 ");
|
||||
hexprint(data1, 32);
|
||||
print_executing();
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.derive_key(tx_buffer, rx_buffer, param1, param2, data1);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case 'v': // dev_rev
|
||||
Wl("Request device revision.");
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.dev_rev(tx_buffer, rx_buffer);
|
||||
print_executing();
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
break;
|
||||
case 'g': // gen_dig
|
||||
Wl("Compute SHA-256 from TempKey+stored value, store result in TempKey (GenDig command).");
|
||||
Wl("Enter zone (1 byte: 00/Config or 01/OTP or 02/Data; default 0):");
|
||||
param1 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param1 = tx_buffer[0];
|
||||
Wl("Enter Key ID / OTP slot ID (1 byte; default 0):");
|
||||
param2 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param2 = tx_buffer[0];
|
||||
Wl("Enter other data (4 bytes when CheckKey, otherwise ignored; default 0):");
|
||||
memset((void *)data1, 0, 4);
|
||||
get_bytes_serial(data1, 4);
|
||||
print_execute_params(SHA204_GENDIG,param1);
|
||||
hexprint_byte_sep((uint8_t)param2);
|
||||
W("data1 ");
|
||||
hexprint(data1, 4);
|
||||
print_executing();
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.gen_dig(tx_buffer, rx_buffer, param1, param2, data1);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case 'h': // HMAC
|
||||
Wl("Compute HMAC/SHA-256 digest from key + other info on device (HMAC command).");
|
||||
Wl("Enter mode (1 byte; default 0):");
|
||||
param1 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param1 = tx_buffer[0];
|
||||
Wl("Enter Slot ID (2 bytes; default 0):");
|
||||
param2 = 0;
|
||||
if(2 == get_bytes_serial(tx_buffer, 2))
|
||||
param2 = tx_buffer[0]*256 + tx_buffer[1];
|
||||
print_execute_params(SHA204_HMAC,param1);
|
||||
hexprint_byte_sep((uint8_t)(param2>>8));
|
||||
hexprint_byte((uint8_t)param2);
|
||||
W("\n\r");
|
||||
print_executing();
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.hmac(tx_buffer, rx_buffer, param1, param2);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case 'm': // mac
|
||||
Wl("Compute SHA-256 from key + challenge + other info on device (MAC command).");
|
||||
Wl("Enter mode (1 byte; default 0):");
|
||||
param1 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param1 = tx_buffer[0];
|
||||
Wl("Enter Slot ID (2 bytes; default 0):");
|
||||
param2 = 0;
|
||||
if(2 == get_bytes_serial(tx_buffer, 2))
|
||||
param2 = tx_buffer[0]*256 + tx_buffer[1];
|
||||
Wl("Enter challenge (32 bytes; default 0):");
|
||||
memset((void *)data1, 0, 32);
|
||||
get_bytes_serial(data1, 32);
|
||||
print_execute_params(SHA204_MAC,param1);
|
||||
hexprint_byte_sep((uint8_t)(param2>>8));
|
||||
hexprint_byte_sep((uint8_t)param2);
|
||||
W("data1 ");
|
||||
hexprint(data1, 32);
|
||||
print_executing();
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.mac(tx_buffer, rx_buffer, param1, param2, data1);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case 'n': // nonce
|
||||
Wl("Generate a nonce for subsequent use by other commands (Nonce command).");
|
||||
Wl("Enter mode (00 to 03; default 0):");
|
||||
param1 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param1 = tx_buffer[0];
|
||||
Wl("Enter input value (20 or 32 bytes (dep on mode); default all 0):");
|
||||
memset((void *)data1, 0, 32);
|
||||
get_bytes_serial(data1, 32);
|
||||
print_execute_params(SHA204_NONCE, param1);
|
||||
Wl("none");
|
||||
print_executing();
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.nonce(tx_buffer,rx_buffer,param1,data1);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case 'r': // random
|
||||
Wl("Generate a random sequence.");
|
||||
Wl("Enter mode (00 or 01; default 0):");
|
||||
param1 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param1 = tx_buffer[0];
|
||||
print_execute_params(SHA204_RANDOM,param1);
|
||||
Wl("none");
|
||||
print_executing();
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.random(tx_buffer,rx_buffer,param1);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case 'e': // read
|
||||
Wl("Read from device.");
|
||||
Wl("Enter zone (1 byte: 00/Config or 01/OTP or 02/Data, +0x80 to read 32 instead of 4 bytes; default 0):");
|
||||
param1 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param1 = tx_buffer[0];
|
||||
Wl("Enter Address (2 bytes; default 0):");
|
||||
param2 = 0;
|
||||
if(2 == get_bytes_serial(tx_buffer, 2))
|
||||
param2 = tx_buffer[0]*256 + tx_buffer[1];
|
||||
print_execute_params(SHA204_READ,param1);
|
||||
hexprint_byte_sep((uint8_t)(param2>>8));
|
||||
hexprint_byte((uint8_t)param2);
|
||||
W("\n\r");
|
||||
print_executing();
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.read(tx_buffer, rx_buffer, param1, param2);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case 'w': // write
|
||||
Wl("Write to device.");
|
||||
Wl("Enter zone (1 byte: 00/Config or 01/OTP or 02/Data,");
|
||||
Wl(" +0x80 to write 32 instead of 4 bytes, +0x40 to require encryption; default 0):");
|
||||
param1 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param1 = tx_buffer[0];
|
||||
Wl("Enter Address (2 bytes; default 0):");
|
||||
param2 = 0;
|
||||
if(2 == get_bytes_serial(tx_buffer, 2))
|
||||
param2 = tx_buffer[0]*256 + tx_buffer[1];
|
||||
Wl("Enter data (4 or 32 bytes; default 0):");
|
||||
memset((void *)data1, 0, 32);
|
||||
get_bytes_serial(data1, 32);
|
||||
Wl("Enter MAC to validate address and data (0 or 32 bytes; default 0):");
|
||||
memset((void *)data2, 0, 32);
|
||||
get_bytes_serial(data2, 32);
|
||||
print_execute_params(SHA204_WRITE,param1);
|
||||
hexprint_byte_sep((uint8_t)(param2>>8));
|
||||
hexprint_byte_sep((uint8_t)param2);
|
||||
W("data1 ");
|
||||
hexprint_noln(data1, 32);
|
||||
W("data2 ");
|
||||
hexprint(data2, 32);
|
||||
print_executing();
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.write(tx_buffer, rx_buffer, param1, param2, data1, data2);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case 'u': // update_extra
|
||||
Wl("Update 'UserExtra' bytes (84 and 85) in the Conf zone after locking.");
|
||||
Wl("Enter mode (1 byte: 00->update 84, 01->update 85; default 0):");
|
||||
param1 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param1 = tx_buffer[0];
|
||||
Wl("Enter new value (1 byte; default 0):");
|
||||
param2 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param2 = tx_buffer[0];
|
||||
print_execute_params(SHA204_UPDATE_EXTRA,param1);
|
||||
hexprint_byte((uint8_t)param2);
|
||||
W("\n\r");
|
||||
print_executing();
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.update_extra(tx_buffer, rx_buffer, param1, param2);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case 'k': // wake
|
||||
Wl("Test waking up.");
|
||||
print_executing();
|
||||
r = sha204.wakeup(rx_buffer);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
Wl("Should receive: 04 11 33 43");
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case 'L': // lock
|
||||
Wl("Lock a zone. This is a one time thing! Once you lock a zone, it CAN'T BE UNLOCKED. EVER!");
|
||||
Wl("Enter zone (1 byte: 00/Config or 01/OTP_or_Data, +0x80 for 'force' (CRC ignored); default 0):");
|
||||
param1 = 0;
|
||||
if(1 == get_bytes_serial(tx_buffer, 1))
|
||||
param1 = tx_buffer[0];
|
||||
Wl("Enter Summary / CRC-16 of the zone (2 bytes, should be 0 if 'force'; default 0):");
|
||||
param2 = 0;
|
||||
if(2 == get_bytes_serial(tx_buffer, 2))
|
||||
param2 = tx_buffer[0]*256 + tx_buffer[1];
|
||||
print_execute_params(SHA204_LOCK,param1);
|
||||
hexprint_byte_sep((uint8_t)(param2>>8));
|
||||
hexprint_byte((uint8_t)param2);
|
||||
W("\n\r");
|
||||
print_executing();
|
||||
sha204.wakeup(rx_buffer);
|
||||
r = sha204.lock(tx_buffer, rx_buffer, param1, param2);
|
||||
if(idle) { sha204.idle(); } else { sha204.sleep(); }
|
||||
print_return_code(r);
|
||||
print_received_from_sha(rx_buffer);
|
||||
break;
|
||||
case '\r': // enter
|
||||
case '?': // help
|
||||
print_help();
|
||||
break;
|
||||
case 'I': // switch idle and sleep
|
||||
W("Switching whether the ATSHA should be put to sleep or to idle mode after commands.\n\rCurrent setting: ");
|
||||
if(idle) {
|
||||
idle = 0;
|
||||
Wl("Sleep.");
|
||||
}
|
||||
else {
|
||||
idle = 1;
|
||||
Wl("Idle.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Helper functions implementation */
|
||||
|
||||
void hexprint_byte(uint8_t b) {
|
||||
uint8_t high, low;
|
||||
low = b & 0xF;
|
||||
high = b >> 4;
|
||||
usb_serial_putchar(high+'0'+7*(high/10));
|
||||
usb_serial_putchar(low+'0'+7*(low/10));
|
||||
}
|
||||
|
||||
void hexprint_byte_sep(uint8_t b) {
|
||||
hexprint_byte(b);
|
||||
usb_serial_putchar(hexprint_separator);
|
||||
}
|
||||
|
||||
void hexprint_noln(uint8_t *p, uint16_t length) {
|
||||
for(uint16_t i=0; i<length; i++) {
|
||||
hexprint_byte(p[i]);
|
||||
if(hexprint_separator!=0)
|
||||
usb_serial_putchar(hexprint_separator);
|
||||
}
|
||||
}
|
||||
|
||||
void hexprint(uint8_t *p, uint16_t length) {
|
||||
hexprint_noln(p, length);
|
||||
usb_serial_write_P(PSTR("\n\r"));
|
||||
}
|
||||
|
||||
void hexprint_4bits(uint8_t b) {
|
||||
usb_serial_putchar((b&0xF)+'0'+7*((b&0xF)/10));
|
||||
}
|
||||
|
||||
void hexprint_1bit(uint8_t b) {
|
||||
usb_serial_putchar((b&1)+'0');
|
||||
}
|
||||
|
||||
void print_help(void) {
|
||||
Wl("*** SHA204 playground [(c) 2014 flabbergast] ***\n\r");
|
||||
Wl("Raw commands: wa[k]e [c]heckMAC [d]erive_key dev_re[v]ision [g]en_dig [h]MAC");
|
||||
Wl(" [m]ac [n]once [r]andom r[e]ad [w]rite [u]date_extra");
|
||||
Wl("Processed commands: [s]erial c[o]nfig_zone");
|
||||
Wl("Playground config: [I]dle-or-sleep");
|
||||
Wl("'?' -> this help");
|
||||
Wl("Dangerous/one-time only! [L]ock\n\r");
|
||||
Wl("Additional comments:");
|
||||
Wl(" - Format of ATSHA204 command responses:");
|
||||
Wl(" <1byte:packet_size> <msg_byte> <msg_byte> ... <1byte:crc_1> <1byte:crc_2>");
|
||||
Wl(" - ATSHA204 is sent to sleep or to idle mode after every command, select via [I].");
|
||||
Wl(" - The 'sent packet' info does not always match what's actually exactly sent. It's provided");
|
||||
Wl(" mainly to check the entered parameters.");
|
||||
Wl(" - Input, when requested, is expected in (padded) HEX format, e.g. 'AB01' for two bytes: 171 1.\n\r");
|
||||
}
|
||||
|
||||
void print_executing(void) {
|
||||
W("Executing: ");
|
||||
}
|
||||
|
||||
void print_received_from_sha(uint8_t *rx_buffer) {
|
||||
W("Received from ATSHA204: ");
|
||||
hexprint(rx_buffer, rx_buffer[0]);
|
||||
}
|
||||
|
||||
void print_execute_params(uint8_t opcode, uint8_t param1) {
|
||||
W("Will run with: opcode ");
|
||||
hexprint_byte_sep(opcode);
|
||||
W("param1 ");
|
||||
hexprint_byte_sep(param1);
|
||||
W("param2 ");
|
||||
}
|
||||
|
||||
uint8_t get_bytes_serial(uint8_t *output, uint16_t len) {
|
||||
char buffer[2*MAX_BUFFER_SIZE];
|
||||
uint16_t input_length;
|
||||
uint16_t i;
|
||||
uint8_t low, high;
|
||||
|
||||
input_length = usb_serial_readline(buffer, 2*len+1, false);
|
||||
strupr(buffer);
|
||||
for(i=0; i<input_length; i+=2) {
|
||||
high = buffer[i] - '0';
|
||||
if(high > 9)
|
||||
high -= 7;
|
||||
low = buffer[i+1] - '0';
|
||||
if(low > 9)
|
||||
low -= 7;
|
||||
output[i/2] = (uint8_t)(low + (high << 4));
|
||||
}
|
||||
|
||||
return (input_length/2);
|
||||
}
|
||||
|
||||
/* Read and Interpret ATSHA204 configuration */
|
||||
void process_config(uint8_t *config) {
|
||||
// serial number
|
||||
W("Serial number: ");
|
||||
hexprint_noln(config+ADDRESS_SN03, 4);
|
||||
hexprint(config+ADDRESS_SN47, 5);
|
||||
// revision number
|
||||
W("Revision number: ");
|
||||
hexprint(config+ADDRESS_RevNum,4);
|
||||
// I2C setup
|
||||
if(config[ADDRESS_I2CEN]&1) {
|
||||
W("I2C enabled; Address: ");
|
||||
hexprint_byte(config[ADDRESS_I2CADD]>>1);
|
||||
W("\n\r");
|
||||
} else {
|
||||
W("SingleWire (I2C disabled); TTL input level: ");
|
||||
if(config[ADDRESS_I2CADD]&0b1000)
|
||||
Wl("Vcc");
|
||||
else
|
||||
Wl("fixed");
|
||||
}
|
||||
// OTP mode
|
||||
W("OTP mode: ");
|
||||
switch(config[ADDRESS_OTPMODE]) {
|
||||
case 0xAA:
|
||||
Wl("read-only");
|
||||
break;
|
||||
case 0x55:
|
||||
Wl("consumption");
|
||||
break;
|
||||
case 0x00:
|
||||
Wl("legacy");
|
||||
break;
|
||||
default:
|
||||
Wl("reserved value (problem!)");
|
||||
break;
|
||||
}
|
||||
// selector mode
|
||||
W("Selector: ");
|
||||
if(!config[ADDRESS_SELECTOR])
|
||||
Wl("can be updated with UpdateExtra.");
|
||||
else
|
||||
Wl("can be updated only if it is 0.");
|
||||
// User extra
|
||||
W("User Extra byte: ");
|
||||
hexprint_byte(config[84]);
|
||||
W("\n\r");
|
||||
// Selector
|
||||
W("Selector byte: ");
|
||||
hexprint_byte(config[85]);
|
||||
W("\n\r");
|
||||
// Lock data
|
||||
W("Data and OTP zones are ");
|
||||
if(config[86]==0x55)
|
||||
Wl("unlocked.");
|
||||
else
|
||||
Wl("locked!");
|
||||
// Lock config
|
||||
W("Config zone is ");
|
||||
if(config[87]==0x55)
|
||||
Wl("unlocked.");
|
||||
else
|
||||
Wl("locked!");
|
||||
// Slots
|
||||
uint8_t i;
|
||||
Wl("Configurations of slots: ");
|
||||
for(i=0; i<16; i++) {
|
||||
uint8_t addr = 20+(2*i);
|
||||
W("Slot:");
|
||||
hexprint_4bits(i);
|
||||
W(" ReadKey:");
|
||||
hexprint_4bits(config[addr]); // getting the 2 config bytes LSB first
|
||||
W(" CheckOnly:");
|
||||
hexprint_1bit(config[addr]>>4);
|
||||
W(" SingleUse:");
|
||||
hexprint_1bit(config[addr]>>5);
|
||||
W(" EncryptRead:");
|
||||
hexprint_1bit(config[addr]>>6);
|
||||
W(" IsSecret:");
|
||||
hexprint_1bit(config[addr]>>7);
|
||||
W("\n\r WriteKey:");
|
||||
hexprint_4bits(config[addr+1]);
|
||||
W(" WriteConfig:");
|
||||
hexprint_4bits(config[addr+1]>>4);
|
||||
W("\n\r");
|
||||
if(i<8) { // slots 0-7 have extra data
|
||||
W(" UseFlag:");
|
||||
hexprint_byte(config[52+(2*i)]);
|
||||
W(" UpdateCount:");
|
||||
hexprint_byte(config[53+(2*i)]);
|
||||
W("\n\r");
|
||||
}
|
||||
if(i==15) { // slot15 has limit on usage
|
||||
W(" LastKeyUse: ");
|
||||
hexprint(config+68, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t receive_serial_binary_transaction(uint8_t *buffer, uint8_t len) {
|
||||
delay(100); // give the transmitting side the chance to push the rest through
|
||||
if( usb_serial_available() == 0 ) {
|
||||
return BINARY_TRANSACTION_RECEIVE_ERROR;
|
||||
}
|
||||
uint8_t n_bytes = usb_serial_getchar();
|
||||
if( n_bytes >= len ) {
|
||||
return BINARY_TRANSACTION_RECEIVE_ERROR;
|
||||
}
|
||||
buffer[0] = n_bytes;
|
||||
for(uint8_t i=1; i<=n_bytes; i++) {
|
||||
if( usb_serial_available() == 0 ) {
|
||||
return BINARY_TRANSACTION_RECEIVE_ERROR;
|
||||
}
|
||||
buffer[i] = (uint8_t)usb_serial_getchar();
|
||||
delay(3);
|
||||
}
|
||||
return BINARY_TRANSACTION_OK;
|
||||
}
|
||||
|
||||
uint8_t binary_mode_transaction(uint8_t *data, uint8_t rxsize, uint8_t *rx_buffer, SHA204SWI *sha204) {
|
||||
uint8_t i = 0;
|
||||
uint8_t len;
|
||||
uint8_t idle;
|
||||
uint8_t opcode;
|
||||
uint8_t param1;
|
||||
uint16_t param2;
|
||||
uint8_t datalen1=0;
|
||||
uint8_t data1[32];
|
||||
uint8_t datalen2=0;
|
||||
uint8_t data2[32];
|
||||
uint8_t datalen3=0;
|
||||
uint8_t data3[14];
|
||||
// process the input packet
|
||||
len = data[0];
|
||||
idle = data[1];
|
||||
if(len<5)
|
||||
return BINARY_TRANSACTION_PARAM_ERROR;
|
||||
opcode = data[2];
|
||||
param1 = data[3];
|
||||
param2 = data[4] + 256*data[5];
|
||||
if(len>5) {
|
||||
if((datalen1=data[6]) > 32)
|
||||
return BINARY_TRANSACTION_PARAM_ERROR;
|
||||
for(i=0; i<datalen1; i++)
|
||||
data1[i] = data[7+i];
|
||||
}
|
||||
if(len>6+datalen1) {
|
||||
if((datalen2=data[7+datalen1]) > 32)
|
||||
return BINARY_TRANSACTION_PARAM_ERROR;
|
||||
for(i=0; i<datalen2; i++)
|
||||
data2[i] = data[8+datalen1+i];
|
||||
}
|
||||
if(len>7+datalen1+datalen2) {
|
||||
if((datalen3=data[8+datalen1+datalen2]) > 13)
|
||||
return BINARY_TRANSACTION_PARAM_ERROR;
|
||||
for(i=0; i<datalen3; i++)
|
||||
data3[i] = data[9+datalen1+datalen2+i];
|
||||
}
|
||||
// run the transaction
|
||||
sha204->wakeup(data);
|
||||
i = sha204->execute(opcode, param1, param2,
|
||||
datalen1, data1, datalen2, data2, datalen3, data3,
|
||||
len, data, rxsize, rx_buffer);
|
||||
if(idle)
|
||||
sha204->idle();
|
||||
else
|
||||
sha204->sleep();
|
||||
if(i != SHA204_SUCCESS)
|
||||
return BINARY_TRANSACTION_EXECUTE_ERROR;
|
||||
return BINARY_TRANSACTION_OK;
|
||||
}
|
||||
|
||||
/* Return code stuff */
|
||||
|
||||
const char retcode_success[] PROGMEM = "Success.";
|
||||
const char retcode_parse_error[] PROGMEM = "Parse error.";
|
||||
const char retcode_cmd_fail[] PROGMEM = "Command execution error.";
|
||||
const char retcode_status_crc[] PROGMEM = "CRC error.";
|
||||
const char retcode_status_unknown[] PROGMEM = "Unknown error.";
|
||||
const char retcode_func_fail[] PROGMEM = "Couldn't execute due to wrong condition/state.";
|
||||
const char retcode_gen_fail[] PROGMEM = "Unspecified error.";
|
||||
const char retcode_bad_param[] PROGMEM = "Bad parameter.";
|
||||
const char retcode_invalid_id[] PROGMEM = "Invalid device ID.";
|
||||
const char retcode_invalid_size[] PROGMEM = "Out of range error.";
|
||||
const char retcode_bad_crc[] PROGMEM = "Bad CRC received.";
|
||||
const char retcode_rx_fail[] PROGMEM = "Timeout while waiting for a response (got >0 bytes).";
|
||||
const char retcode_rx_no_response[] PROGMEM = "Timeout (not an error while busy).";
|
||||
const char retcode_resync_with_wakeup[] PROGMEM = "Resync OK after wakeup.";
|
||||
const char retcode_comm_fail[] PROGMEM = "Communication failed";
|
||||
const char retcode_timeout[] PROGMEM = "Timeout while waiting for a response (got no bytes).";
|
||||
const char retcode_unknown[] PROGMEM = "Unknown error message.";
|
||||
|
||||
void print_return_code(uint8_t code) {
|
||||
const char *p PROGMEM;
|
||||
switch(code) {
|
||||
case(SHA204_SUCCESS):
|
||||
p = retcode_success;
|
||||
break;
|
||||
case(SHA204_PARSE_ERROR):
|
||||
p = retcode_parse_error;
|
||||
break;
|
||||
case(SHA204_CMD_FAIL):
|
||||
p = retcode_cmd_fail;
|
||||
break;
|
||||
case(SHA204_STATUS_CRC):
|
||||
p = retcode_status_crc;
|
||||
break;
|
||||
case(SHA204_STATUS_UNKNOWN):
|
||||
p = retcode_status_unknown;
|
||||
break;
|
||||
case(SHA204_FUNC_FAIL):
|
||||
p = retcode_func_fail;
|
||||
break;
|
||||
case(SHA204_GEN_FAIL):
|
||||
p = retcode_gen_fail;
|
||||
break;
|
||||
case(SHA204_BAD_PARAM):
|
||||
p = retcode_bad_param;
|
||||
break;
|
||||
case(SHA204_INVALID_ID):
|
||||
p = retcode_invalid_id;
|
||||
break;
|
||||
case(SHA204_INVALID_SIZE):
|
||||
p = retcode_invalid_size;
|
||||
break;
|
||||
case(SHA204_BAD_CRC):
|
||||
p = retcode_bad_crc;
|
||||
break;
|
||||
case(SHA204_RX_FAIL):
|
||||
p = retcode_rx_fail;
|
||||
break;
|
||||
case(SHA204_RX_NO_RESPONSE):
|
||||
p = retcode_rx_no_response;
|
||||
break;
|
||||
case(SHA204_RESYNC_WITH_WAKEUP):
|
||||
p = retcode_resync_with_wakeup;
|
||||
break;
|
||||
case(SHA204_COMM_FAIL):
|
||||
p = retcode_comm_fail;
|
||||
break;
|
||||
case(SHA204_TIMEOUT):
|
||||
p = retcode_timeout;
|
||||
break;
|
||||
default:
|
||||
p = retcode_unknown;
|
||||
break;
|
||||
}
|
||||
usb_serial_write_P(p);
|
||||
Serial.write("\n\r");
|
||||
}
|
||||
|
||||
// implementation of "LufaLayer"
|
||||
uint16_t usb_serial_available(void) {
|
||||
return Serial.available();
|
||||
}
|
||||
|
||||
int16_t usb_serial_getchar(void) {
|
||||
return Serial.read();
|
||||
}
|
||||
|
||||
void usb_serial_putchar(uint8_t ch) {
|
||||
Serial.write(ch);
|
||||
}
|
||||
|
||||
void usb_serial_write_P(PGM_P data) {
|
||||
for (uint8_t c; (c = pgm_read_byte(data)); data++) Serial.write(c);
|
||||
}
|
||||
|
||||
void usb_serial_write(const char* const buffer) {
|
||||
Serial.write(buffer);
|
||||
}
|
||||
|
||||
uint16_t usb_serial_readline(char *buffer, const uint16_t buffer_size, const bool obscure_input)
|
||||
{
|
||||
while(Serial.available() == 0) ;
|
||||
Serial.setTimeout(100);
|
||||
uint16_t r = Serial.readBytes(buffer, buffer_size);
|
||||
Serial.setTimeout(1000);
|
||||
return(r);
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Board.h
|
||||
* (c) 2014 flabbergast
|
||||
* Custom Board definitions for use with LUFA, for AVR stick.
|
||||
*
|
||||
* Based on a template from LUFA library (license below).
|
||||
*/
|
||||
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2014.
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.lufa-lib.org
|
||||
*/
|
||||
/*
|
||||
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
The author disclaims all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
#ifndef __BOARD_USER_H__
|
||||
#define __BOARD_USER_H__
|
||||
/* Includes: */
|
||||
// TODO: Add any required includes here
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_BOARD_H)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
|
||||
#endif
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
#define BOARD_HAS_BUTTONS
|
||||
// #define BOARD_HAS_DATAFLASH
|
||||
// #define BOARD_HAS_JOYSTICK
|
||||
// #define BOARD_HAS_LEDS
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Buttons.h
|
||||
* (c) 2014 flabbergast
|
||||
* Custom Buttons definitions for use with LUFA, for AVR stick.
|
||||
*
|
||||
* Based on a template from LUFA library (license below).
|
||||
*/
|
||||
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2014.
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.lufa-lib.org
|
||||
*/
|
||||
/*
|
||||
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
The author disclaims all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
#ifndef __BUTTONS_USER_H__
|
||||
#define __BUTTONS_USER_H__
|
||||
/* Includes: */
|
||||
// TODO: Add any required includes here
|
||||
#include <avr/io.h>
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_BUTTONS_H)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
|
||||
#endif
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
#define BUTTONS_BUTTON1 _BV(7)
|
||||
/* Inline Functions: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
static inline void Buttons_Init(void)
|
||||
{
|
||||
PORTF.DIRCLR = BUTTONS_BUTTON1;
|
||||
PORTF.PIN7CTRL = PORT_OPC_PULLUP_gc; // pull-up on pin 7
|
||||
}
|
||||
static inline void Buttons_Disable(void)
|
||||
{
|
||||
PORTF.PIN7CTRL = 0; // don't know what's the default state of pull-up/down?
|
||||
PORTF.DIRCLR = BUTTONS_BUTTON1;
|
||||
}
|
||||
static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
|
||||
static inline uint8_t Buttons_GetStatus(void)
|
||||
{
|
||||
// TODO: Return current button status here, debounced if required
|
||||
return ((PORTF.IN & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
|
||||
}
|
||||
#endif
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* LEDs.h
|
||||
* (c) 2014 flabbergast
|
||||
* Custom LEDs definitions for use with LUFA, for AVR stick.
|
||||
*
|
||||
* Based on a template from LUFA library (license below).
|
||||
*/
|
||||
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2014.
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.lufa-lib.org
|
||||
*/
|
||||
/*
|
||||
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
The author disclaims all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
#ifndef __LEDS_USER_H__
|
||||
#define __LEDS_USER_H__
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_LEDS_H)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
|
||||
#endif
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
#define LEDS_LED1 (1 << 0)
|
||||
#define LEDS_LED2 (1 << 1)
|
||||
#define LEDS_LED3 (1 << 2)
|
||||
#define LEDS_LED4 (1 << 3)
|
||||
#define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
|
||||
#define LEDS_NO_LEDS 0
|
||||
/* Inline Functions: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
static inline void LEDs_Init(void)
|
||||
{
|
||||
PORTE.DIRSET = LEDS_ALL_LEDS;
|
||||
PORTE.OUTCLR = LEDS_ALL_LEDS;
|
||||
}
|
||||
static inline void LEDs_Disable(void)
|
||||
{
|
||||
PORTE.DIRCLR = LEDS_ALL_LEDS;
|
||||
PORTE.OUTCLR = LEDS_ALL_LEDS;
|
||||
}
|
||||
static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
|
||||
{
|
||||
PORTE.OUTSET = LEDMask & LEDS_ALL_LEDS;
|
||||
}
|
||||
static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
|
||||
{
|
||||
PORTE.OUTCLR = LEDMask & LEDS_ALL_LEDS;
|
||||
}
|
||||
static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
|
||||
{
|
||||
PORTE.OUTCLR = LEDS_ALL_LEDS;
|
||||
PORTE.OUTSET = LEDMask & LEDS_ALL_LEDS;
|
||||
}
|
||||
static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, const uint8_t ActiveMask)
|
||||
{
|
||||
PORTE.OUTCLR = (LEDMask & LEDS_ALL_LEDS);
|
||||
PORTE.OUTSET = (ActiveMask & LEDS_ALL_LEDS);
|
||||
}
|
||||
static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
|
||||
{
|
||||
PORTE.OUTTGL = (LEDMask & LEDS_ALL_LEDS);
|
||||
}
|
||||
static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
|
||||
static inline uint8_t LEDs_GetLEDs(void)
|
||||
{
|
||||
return ((PORTE.OUT & LEDS_ALL_LEDS));
|
||||
}
|
||||
#endif
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2014.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.lufa-lib.org
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaims all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief LUFA Library Configuration Header File
|
||||
*
|
||||
* This header file is used to configure LUFA's compile time options,
|
||||
* as an alternative to the compile time constants supplied through
|
||||
* a makefile.
|
||||
*
|
||||
* For information on what each token does, refer to the LUFA
|
||||
* manual section "Summary of Compile Tokens".
|
||||
*/
|
||||
|
||||
#ifndef _LUFA_CONFIG_H_
|
||||
#define _LUFA_CONFIG_H_
|
||||
|
||||
#if (ARCH == ARCH_AVR8)
|
||||
|
||||
/* Non-USB Related Configuration Tokens: */
|
||||
// #define DISABLE_TERMINAL_CODES
|
||||
|
||||
/* USB Class Driver Related Tokens: */
|
||||
// #define HID_HOST_BOOT_PROTOCOL_ONLY
|
||||
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_MAX_COLLECTIONS {Insert Value Here}
|
||||
// #define HID_MAX_REPORTITEMS {Insert Value Here}
|
||||
// #define HID_MAX_REPORT_IDS {Insert Value Here}
|
||||
// #define NO_CLASS_DRIVER_AUTOFLUSH
|
||||
|
||||
/* General USB Driver Related Tokens: */
|
||||
// #define ORDERED_EP_CONFIG
|
||||
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
|
||||
#define USB_DEVICE_ONLY
|
||||
// #define USB_HOST_ONLY
|
||||
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
|
||||
// #define NO_LIMITED_CONTROLLER_CONNECT
|
||||
// #define NO_SOF_EVENTS
|
||||
|
||||
/* USB Device Mode Driver Related Tokens: */
|
||||
// #define USE_RAM_DESCRIPTORS
|
||||
#define USE_FLASH_DESCRIPTORS
|
||||
// #define USE_EEPROM_DESCRIPTORS
|
||||
// #define NO_INTERNAL_SERIAL
|
||||
#define FIXED_CONTROL_ENDPOINT_SIZE 8
|
||||
// #define DEVICE_STATE_AS_GPIOR {Insert Value Here}
|
||||
#define FIXED_NUM_CONFIGURATIONS 1
|
||||
// #define CONTROL_ONLY_DEVICE
|
||||
#define INTERRUPT_CONTROL_ENDPOINT
|
||||
// #define NO_DEVICE_REMOTE_WAKEUP
|
||||
// #define NO_DEVICE_SELF_POWER
|
||||
|
||||
/* USB Host Mode Driver Related Tokens: */
|
||||
// #define HOST_STATE_AS_GPIOR {Insert Value Here}
|
||||
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
|
||||
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
|
||||
// #define NO_AUTO_VBUS_MANAGEMENT
|
||||
// #define INVERTED_VBUS_ENABLE_LINE
|
||||
|
||||
#elif (ARCH == ARCH_XMEGA)
|
||||
|
||||
/* Non-USB Related Configuration Tokens: */
|
||||
// #define DISABLE_TERMINAL_CODES
|
||||
|
||||
/* USB Class Driver Related Tokens: */
|
||||
// #define HID_HOST_BOOT_PROTOCOL_ONLY
|
||||
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_MAX_COLLECTIONS {Insert Value Here}
|
||||
// #define HID_MAX_REPORTITEMS {Insert Value Here}
|
||||
// #define HID_MAX_REPORT_IDS {Insert Value Here}
|
||||
// #define NO_CLASS_DRIVER_AUTOFLUSH
|
||||
|
||||
/* General USB Driver Related Tokens: */
|
||||
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_RC32MCLKSRC | USB_OPT_BUSEVENT_PRIHIGH)
|
||||
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
|
||||
// #define NO_LIMITED_CONTROLLER_CONNECT
|
||||
// #define NO_SOF_EVENTS
|
||||
|
||||
/* USB Device Mode Driver Related Tokens: */
|
||||
// #define USE_RAM_DESCRIPTORS
|
||||
#define USE_FLASH_DESCRIPTORS
|
||||
// #define USE_EEPROM_DESCRIPTORS
|
||||
// #define NO_INTERNAL_SERIAL
|
||||
#define FIXED_CONTROL_ENDPOINT_SIZE 8
|
||||
// #define DEVICE_STATE_AS_GPIOR {Insert Value Here}
|
||||
#define FIXED_NUM_CONFIGURATIONS 1
|
||||
// #define CONTROL_ONLY_DEVICE
|
||||
#define MAX_ENDPOINT_INDEX 4
|
||||
// #define NO_DEVICE_REMOTE_WAKEUP
|
||||
// #define NO_DEVICE_SELF_POWER
|
||||
|
||||
#else
|
||||
|
||||
#error Unsupported architecture for this LUFA configuration file.
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* Descriptors.c
|
||||
* (c) 2014 flabbergast
|
||||
* USB Descriptors.
|
||||
* Most code comes from a LUFA library Demo (license below).
|
||||
*/
|
||||
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2014.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.lufa-lib.org
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaims all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* USB Device Descriptors, for library use when in USB device mode. Descriptors are special
|
||||
* computer-readable structures which the host requests upon device enumeration, to determine
|
||||
* the device's capabilities and functions.
|
||||
*/
|
||||
|
||||
#include "Descriptors.h"
|
||||
|
||||
|
||||
/** HID class report descriptor. This is a special descriptor constructed with values from the
|
||||
* USBIF HID class specification to describe the reports and capabilities of the HID device. This
|
||||
* descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
|
||||
* the device will send, and what it may be sent back from the host. Refer to the HID specification for
|
||||
* more details on HID report descriptors.
|
||||
*/
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
|
||||
{
|
||||
/* Use the HID class driver's standard Keyboard report.
|
||||
* Max simultaneous keys: 6
|
||||
*/
|
||||
HID_DESCRIPTOR_KEYBOARD(6)
|
||||
};
|
||||
|
||||
/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
|
||||
* device characteristics, including the supported USB version, control endpoint size and the
|
||||
* number of device configurations. The descriptor is read out by the USB host when the enumeration
|
||||
* process begins.
|
||||
*/
|
||||
const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
|
||||
|
||||
.USBSpecification = VERSION_BCD(1,1,0),
|
||||
.Class = USB_CSCP_IADDeviceClass,
|
||||
.SubClass = USB_CSCP_IADDeviceSubclass,
|
||||
.Protocol = USB_CSCP_IADDeviceProtocol,
|
||||
|
||||
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
|
||||
|
||||
.VendorID = 0x03EB,
|
||||
.ProductID = 0x206F,
|
||||
.ReleaseNumber = VERSION_BCD(0,0,1),
|
||||
|
||||
.ManufacturerStrIndex = STRING_ID_Manufacturer,
|
||||
.ProductStrIndex = STRING_ID_Product,
|
||||
.SerialNumStrIndex = USE_INTERNAL_SERIAL,
|
||||
|
||||
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
|
||||
};
|
||||
|
||||
/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
|
||||
* of the device in one of its supported configurations, including information about any device interfaces
|
||||
* and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
|
||||
* a configuration so that the host may correctly communicate with the USB device.
|
||||
*/
|
||||
const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
{
|
||||
.Config =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
|
||||
|
||||
.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
|
||||
.TotalInterfaces = 3,
|
||||
|
||||
.ConfigurationNumber = 1,
|
||||
.ConfigurationStrIndex = NO_DESCRIPTOR,
|
||||
|
||||
.ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED),
|
||||
|
||||
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
|
||||
},
|
||||
|
||||
.CDC_IAD =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
|
||||
|
||||
.FirstInterfaceIndex = INTERFACE_ID_CDC_CCI,
|
||||
.TotalInterfaces = 2,
|
||||
|
||||
.Class = CDC_CSCP_CDCClass,
|
||||
.SubClass = CDC_CSCP_ACMSubclass,
|
||||
.Protocol = CDC_CSCP_ATCommandProtocol,
|
||||
|
||||
.IADStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
.CDC_CCI_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = INTERFACE_ID_CDC_CCI,
|
||||
.AlternateSetting = 0,
|
||||
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = CDC_CSCP_CDCClass,
|
||||
.SubClass = CDC_CSCP_ACMSubclass,
|
||||
.Protocol = CDC_CSCP_ATCommandProtocol,
|
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
.CDC_Functional_Header =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface},
|
||||
.Subtype = CDC_DSUBTYPE_CSInterface_Header,
|
||||
|
||||
.CDCSpecification = VERSION_BCD(1,1,0),
|
||||
},
|
||||
|
||||
.CDC_Functional_ACM =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface},
|
||||
.Subtype = CDC_DSUBTYPE_CSInterface_ACM,
|
||||
|
||||