|
- /*-
- * Copyright 2021 John-Mark Gurney.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
- #include "usb_hid_def.h"
-
- #include "stm32f1xx.h"
- #include "stm32f1xx_hal.h"
-
- #include <stdbool.h>
-
- #include <comms.h>
- #include <misc.h>
- #include <rs485frame.h>
- #include <strobe_rng_init.h>
- #include <strobe_pki.h>
-
- #include <cycle.h>
-
- #include <sysinit.h>
-
- static struct pktbuf rxpktbuf;
- static volatile int dorx = 0;
- static uint8_t rxbuf[128];
- static volatile int gotrxdone = 0;
- static volatile int gottxdone = 0;
- static volatile int goterr = 0;
- static volatile int rxbufsize = 0;
- static volatile int rxbuftrunc = 0;
-
- enum {
- CMD_TERMINATE = 1,
- CMD_WAITFOR = 2,
- CMD_RUNFOR = 3,
- CMD_PING = 4,
- CMD_SETUNSET = 5,
- CMD_ADV = 6,
- CMD_CLEAR = 7,
- CMD_KEY = 8,
- };
-
- static struct comms_state cs;
-
- static void
- c13led(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
-
- __HAL_RCC_GPIOB_CLK_ENABLE();
- __HAL_RCC_GPIOC_CLK_ENABLE();
-
- GPIO_InitStruct = (GPIO_InitTypeDef){
- .Pin = GPIO_PIN_13,
- .Mode = GPIO_MODE_OUTPUT_PP,
- .Pull = GPIO_NOPULL,
- .Speed = GPIO_SPEED_FREQ_LOW,
- };
- HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
-
- HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
- }
- SYSINIT_VF(c13led, SI_SUB_HAL, SI_ORDER_SECOND, c13led);
-
- void
- txdone(void)
- {
-
- gottxdone = 1;
- }
-
- void
- errfunc(void)
- {
-
- debug_printf("error\n");
- goterr = 1;
- }
-
- struct pktbuf shared_key_buf = {
- .pkt = (uint8_t *)"abcd1234",
- .pktlen = 8,
- };
-
- static uint32_t rxts;
-
- void
- rxdone(const uint8_t *payload, size_t size)
- {
-
- if (size > sizeof rxbuf) {
- size = sizeof rxbuf;
- rxbuftrunc = 1;
- }
-
- debug_printf("rx: %d: %02x %02x ...\n", size, payload[0], payload[1]);
-
- memcpy(rxbuf, payload, size);
- rxbufsize = size;
- gotrxdone = 1;
- rxts = HAL_GetTick();
- }
-
- static inline uint32_t
- letoh_32(uint8_t *v)
- {
- return v[0] | (v[1] << 8) | (v[2] << 16) | ((unsigned)v[3] << 24);
- }
-
- static inline void
- htole_32(uint8_t *d, uint32_t v)
- {
-
- d[0] = v;
- d[1] = v >> 8;
- d[2] = v >> 16;
- d[3] = v >> 24;
- }
-
- struct chaninfo {
- GPIO_TypeDef *bank;
- uint16_t pinnum;
- bool init;
- bool invert;
- } chans[] = {
- [0] = { .bank = GPIOB, .pinnum = GPIO_PIN_5, .invert = true, },
- [1] = { .bank = GPIOB, .pinnum = GPIO_PIN_6, .invert = true, },
- [2] = { .bank = GPIOB, .pinnum = GPIO_PIN_7, .invert = true, },
- [3] = { .bank = GPIOB, .pinnum = GPIO_PIN_9, .invert = true, },
- /* Turn on LED at start */
- [4] = { .bank = GPIOB, .pinnum = GPIO_PIN_8, .init = true, },
- };
- #define nitems(x) (sizeof(x) / sizeof *(x))
-
- static void
- set_chan(uint32_t chan, bool val)
- {
- struct chaninfo ci;
-
- if (chan < nitems(chans)) {
- ci = chans[chan];
- HAL_GPIO_WritePin(ci.bank, ci.pinnum, val ^ ci.invert ?
- GPIO_PIN_SET : GPIO_PIN_RESET);
- }
- }
-
- static void
- setup_gpio(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- int i;
-
- for (i = 0; i < nitems(chans); i++) {
- GPIO_InitStruct = (GPIO_InitTypeDef){
- .Pin = chans[i].pinnum,
- .Mode = GPIO_MODE_OUTPUT_PP,
- .Pull = GPIO_NOPULL,
- .Speed = GPIO_SPEED_FREQ_LOW,
- };
- HAL_GPIO_Init(chans[i].bank, &GPIO_InitStruct);
- set_chan(i, chans[i].init);
- }
- }
- SYSINIT_VF(setup_gpio, SI_SUB_STANDARD, SI_ORDER_ANY, setup_gpio);
-
- static struct sched {
- uint32_t cmd;
- uint32_t end_wait_tick; /* end if running, otherwise how long to wait */
- uint32_t chan;
- } schedule[20];
- static int schedpos; /* position in schedule, % nitems(schedule)*/
- static int schedcnt; /* total items waiting */
-
- #define SCHED_ITEM(x) (schedule[(schedpos + x) % nitems(schedule)])
- #define SCHED_HEAD SCHED_ITEM(0)
- #define SCHED_TAIL SCHED_ITEM(schedcnt)
-
- static void
- start_sched(struct sched *sched)
- {
-
- sched->end_wait_tick += uwTick;
-
- if (sched->cmd == CMD_RUNFOR)
- set_chan(sched->chan, 1);
- }
-
- static bool
- canproc_sched()
- {
-
- /* nothing to do? */
- if (schedcnt == 0)
- return false;
-
- /* not yet expired */
- if (uwTick < SCHED_HEAD.end_wait_tick)
- return false;
-
- return true;
- }
-
- static void
- process_sched()
- {
-
- if (!canproc_sched())
- return;
-
- if (SCHED_HEAD.cmd == CMD_RUNFOR)
- set_chan(SCHED_HEAD.chan, 0);
-
- /* we are done, advance */
- schedpos++;
- schedcnt--;
-
- if (schedcnt)
- start_sched(&SCHED_HEAD);
- }
-
- static void
- enqueue_sched(uint32_t cmd, uint32_t ticks, uint32_t chan)
- {
-
- if (schedcnt >= nitems(schedule))
- return;
-
- SCHED_TAIL = (struct sched){
- .cmd = cmd,
- .end_wait_tick = ticks,
- .chan = chan,
- };
-
- if (schedcnt == 0)
- start_sched(&SCHED_HEAD);
-
- schedcnt++;
- }
-
- static void
- procmsg(struct pktbuf inbuf, struct pktbuf *outbuf)
- {
- uint32_t args[5];
- uint32_t keycnt;
- int i, r, apos, cnt;
-
- i = 1;
- apos = 0;
- for (i = 1, apos = 0; apos < sizeof args / sizeof *args && i + 4 <= inbuf.pktlen; i += 4, apos++) {
- args[apos] = letoh_32(&inbuf.pkt[i]);
- }
-
- outbuf->pkt[0] = inbuf.pkt[0];
- outbuf->pktlen = 1;
-
- switch (inbuf.pkt[0]) {
- case CMD_WAITFOR:
- if (apos == 1)
- enqueue_sched(CMD_WAITFOR, args[0], -1);
- break;
-
- case CMD_RUNFOR:
- if (apos == 2)
- enqueue_sched(CMD_RUNFOR, args[0], args[1]);
- break;
-
- case CMD_PING:
- break;
-
- case CMD_SETUNSET:
- if (apos == 2)
- set_chan(args[0], args[1]);
- break;
-
- case CMD_ADV:
- cnt = 1;
- if (apos == 1)
- cnt = args[0];
-
- for (i = 0; i < cnt && i < schedcnt; i++)
- SCHED_ITEM(i).end_wait_tick = 0;
- break;
-
- case CMD_CLEAR:
- if (schedcnt)
- schedcnt = 1;
- break;
-
- case CMD_KEY:
- i = 1;
-
- keycnt = 0;
- for (i = 1; i + REPORT_SIZE <= inbuf.pktlen; i += REPORT_SIZE) {
- r = report_insert(&inbuf.pkt[i]);
- if (!r)
- break;
-
- keycnt++;
- }
- htole_32(&outbuf->pkt[1], keycnt);
- outbuf->pktlen = 5;
- break;
-
- default:
- outbuf->pkt[0] = 0;
- break;
- }
- }
-
- static void
- setup_button()
- {
- GPIO_InitTypeDef GPIO_InitStruct;
-
- __HAL_RCC_GPIOA_CLK_ENABLE();
- GPIO_InitStruct = (GPIO_InitTypeDef){
- .Pin = GPIO_PIN_7,
- .Mode = GPIO_MODE_INPUT,
- .Pull = GPIO_PULLUP,
- .Speed = GPIO_SPEED_FREQ_LOW,
- };
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
- SYSINIT_VF(setup_button, SI_SUB_STANDARD, SI_ORDER_ANY, setup_button);
-
- /* check if the button has been pushed, returns true once for each "push" */
- static int
- button_pushed(void)
- {
- static uint32_t lasthightick;
- static uint32_t waspushed;
- uint32_t tick;
- uint8_t pinstate;
-
- tick = HAL_GetTick();
- pinstate = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7);
-
- if (pinstate) {
- /* Reset button state */
- waspushed = 0;
- lasthightick = tick;
- return 0;
- }
-
- /* only return IF the it's been held for 5ms & wasn't returned before */
- if (tick - lasthightick > 5 && !waspushed) {
- waspushed = 1;
- return 1;
- }
-
- return 0;
- }
-
- static const uint8_t hexkeymap[] = {
- [0] = 0x27,
- [1] = 0x1e,
- [2] = 0x1f,
- [3] = 0x20,
- [4] = 0x21,
- [5] = 0x22,
- [6] = 0x23,
- [7] = 0x24,
- [8] = 0x25,
- [9] = 0x26,
- [10] = 0x04,
- [11] = 0x05,
- [12] = 0x06,
- [13] = 0x07,
- [14] = 0x08,
- [15] = 0x09,
- };
- static_assert(sizeof hexkeymap == 16);
-
- volatile uint32_t v;
-
- void
- report_blocking_insert(uint8_t rep[REPORT_SIZE])
- {
- int inserted;
-
- do {
- report_process();
-
- inserted = report_insert(rep);
- } while(!inserted);
- }
-
- int
- main()
- {
- struct strobepkikey keys;
-
- debug_printf("starting...");
-
- sysinit_run();
-
- #if 0
- /* turn on LED */
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
- #endif
-
- keys = get_key();
-
- comms_init(&cs, procmsg, NULL, &keys.privkey, &keys.pubkey);
-
- /* Clear out pointer to private key. */
- keys.privkey = (struct pktbuf){};
-
- rs485_register(txdone, rxdone, errfunc);
-
- uint8_t txbuf[128] = "i'mhere";
- struct pktbuf txpktbuf;
-
- txpktbuf = (struct pktbuf){
- .pkt = txbuf,
- .pktlen = 7,
- };
- //rs485_starttx(txpktbuf.pkt, txpktbuf.pktlen);
- dorx = 1;
-
- int laststartrx = 0;
- loop:
- while (canproc_sched())
- process_sched();
-
- #if 0
- BoardLowPowerHandler();
- #else
- //(void)BoardLowPowerHandler;
- #endif
-
- /* process any pending keys */
- report_process();
-
- if (button_pushed()) {
- /* Send the public key */
- uint8_t pubkey[EC_PUBLIC_BYTES];
- uint8_t reportbuf[REPORT_SIZE];
- const uint8_t *buf;
- int remainnibbles;
- uint8_t lastkey, key;
-
- get_pubkey(pubkey);
-
- buf = pubkey;
- remainnibbles = keys.pubkey.pktlen * 2;
-
- memset(reportbuf, 0, sizeof reportbuf);
-
- /* clear any previous key presses */
- report_blocking_insert(reportbuf);
-
- for (remainnibbles = keys.pubkey.pktlen * 2; remainnibbles; remainnibbles--) {
- /* top nibble when even, bottom when odd */
- if (remainnibbles & 1) {
- key = hexkeymap[buf[0] & 0xf];
- buf++;
- } else
- key = hexkeymap[buf[0] >> 4];
-
- lastkey = reportbuf[2];
-
- /*
- * if previous key matches, we need to "up" it, to make
- * a transition, otherwise, speed things along.
- */
- if (key == lastkey) {
- reportbuf[2] = 0;
- report_blocking_insert(reportbuf);
- }
-
- reportbuf[2] = key;
- report_blocking_insert(reportbuf);
-
- }
-
- /* clear last key */
- reportbuf[2] = 0;
- report_blocking_insert(reportbuf);
- }
-
- if (gottxdone) {
- dorx = 1;
- gottxdone = 0;
- }
-
- if (gotrxdone) {
- rxpktbuf = (struct pktbuf){
- .pkt = rxbuf,
- .pktlen = rxbufsize,
- };
- txpktbuf = (struct pktbuf){
- .pkt = txbuf,
- .pktlen = sizeof txbuf,
- };
- /* process available packet */
- #if 1
- uint32_t gt;
- gt = HAL_GetTick();
- reset_timer();
- start_timer();
- comms_process(&cs, rxpktbuf, &txpktbuf);
- stop_timer();
- debug_printf("comproc: %u cycles, ticks: %u, fromrx: %u\n", getCycles(), HAL_GetTick() - gt, HAL_GetTick() - rxts);
- #else
- txpktbuf = rxpktbuf;
- #endif
-
- //debug_printf("totx: %d: %02x %02x ...\n", txpktbuf.pktlen, txpktbuf.pkt[0], txpktbuf.pkt[1]);
- gotrxdone = false;
-
- if (txpktbuf.pktlen) {
- int i;
-
- //debug_printf("rx to tx: %d\n", HAL_GetTick() - rxts);
- for (i = 0; i < 1; i++) {
- //HAL_Delay(20);
- rs485_starttx(txpktbuf.pkt, txpktbuf.pktlen);
- }
-
- /* Make sure we don't interrupt tx */
- laststartrx = HAL_GetTick();
- } else {
- dorx = 1;
- }
- }
-
- if (dorx || goterr || HAL_GetTick() > laststartrx + 1000000) {
- //usb_printf("dorx\r\n");
- laststartrx = HAL_GetTick();
- rs485_startrx();
- //usb_printf("startrx res: %s\r\n", rs485err);
- dorx = 0;
- }
-
- goto loop;
- }
|