1
0
Fork 0

Initial checkin.

This commit is contained in:
flabbergast 2014-11-14 10:11:41 +00:00
commit d853bc95d9
31 changed files with 5815 additions and 0 deletions

13
.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
*.hex
*.bin
*.eep
*.o
*.elf
*.map
*.lss
*.lst
*.d
*.sym
.idea
LUFA/

19
LICENSE Normal file
View File

@ -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.

81
README.md Normal file
View File

@ -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/

47
arduino/README.md Normal file
View File

@ -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.

View File

@ -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);
}

57
avr/Board/Board.h Normal file
View File

@ -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

74
avr/Board/Buttons.h Normal file
View File

@ -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

99
avr/Board/LEDs.h Normal file
View File

@ -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

126
avr/Config/LUFAConfig.h Normal file
View File

@ -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

325
avr/Descriptors.c Normal file
View File

@ -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,