PIN input support (dial)
This commit is contained in:
18
ChangeLog
18
ChangeLog
@@ -1,3 +1,21 @@
|
|||||||
|
2011-01-19 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* src/pin-dial.c: New.
|
||||||
|
|
||||||
|
* boards/STBEE_MINI/board.c (hwinit1): Add PINPAD_DIAL_SUPPORT.
|
||||||
|
(dial_sw_disable, dial_sw_enable, EXTI2_IRQHandler): New.
|
||||||
|
|
||||||
|
* src/gnuk.h: Add PINPAD_DIAL_SUPPORT.
|
||||||
|
|
||||||
|
* src/usb-icc.c (icc_handle_data): Handle PIN modification.
|
||||||
|
|
||||||
|
* src/usb_desc.c (gnukConfigDescriptor): bPinSupport = 3 when
|
||||||
|
PINPAD_DIAL_SUPPORT is enabled.
|
||||||
|
|
||||||
|
2011-01-18 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* src/pin-cir.c (pin_main): Call cir_ext_disable at the end.
|
||||||
|
|
||||||
2011-01-17 NIIBE Yutaka <gniibe@fsij.org>
|
2011-01-17 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
* src/gnuk.h (PIN_INPUT_CURRENT, PIN_INPUT_NEW)
|
* src/gnuk.h (PIN_INPUT_CURRENT, PIN_INPUT_NEW)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ hwinit1 (void)
|
|||||||
; /* Wait for JTAG debugger connection */
|
; /* Wait for JTAG debugger connection */
|
||||||
palWritePort(IOPORT2, 0xffff); /* All set */
|
palWritePort(IOPORT2, 0xffff); /* All set */
|
||||||
|
|
||||||
|
#if defined(PINPAD_CIR_SUPPORT)
|
||||||
/* EXTI0 <= PB0 */
|
/* EXTI0 <= PB0 */
|
||||||
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI0_PB;
|
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI0_PB;
|
||||||
EXTI->IMR = 0;
|
EXTI->IMR = 0;
|
||||||
@@ -46,6 +47,33 @@ hwinit1 (void)
|
|||||||
TIM3->ARR = 18000; /* 18 ms */
|
TIM3->ARR = 18000; /* 18 ms */
|
||||||
/* Generate UEV to upload PSC and ARR */
|
/* Generate UEV to upload PSC and ARR */
|
||||||
TIM3->EGR = TIM_EGR_UG;
|
TIM3->EGR = TIM_EGR_UG;
|
||||||
|
#elif defined(PINPAD_DIAL_SUPPORT)
|
||||||
|
/* EXTI2 <= PB2 */
|
||||||
|
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI2_PB;
|
||||||
|
EXTI->IMR = 0;
|
||||||
|
EXTI->FTSR = EXTI_FTSR_TR2;
|
||||||
|
NVICEnableVector(EXTI2_IRQn,
|
||||||
|
CORTEX_PRIORITY_MASK(CORTEX_MINIMUM_PRIORITY));
|
||||||
|
|
||||||
|
/* TIM4 */
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
|
||||||
|
RCC->APB1RSTR = RCC_APB1RSTR_TIM4RST;
|
||||||
|
RCC->APB1RSTR = 0;
|
||||||
|
|
||||||
|
TIM4->CR1 = TIM_CR1_URS | TIM_CR1_ARPE | TIM_CR1_CKD_1;
|
||||||
|
TIM4->CR2 = 0;
|
||||||
|
TIM4->SMCR = TIM_SMCR_SMS_0;
|
||||||
|
TIM4->DIER = 0; /* no interrupt */
|
||||||
|
TIM4->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0
|
||||||
|
| TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 | TIM_CCMR1_IC1F_3
|
||||||
|
| TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_1 | TIM_CCMR1_IC2F_2 | TIM_CCMR1_IC2F_3;
|
||||||
|
TIM4->CCMR2 = 0;
|
||||||
|
TIM4->CCER = 0;
|
||||||
|
TIM4->PSC = 0;
|
||||||
|
TIM4->ARR = 31;
|
||||||
|
/* Generate UEV to upload PSC and ARR */
|
||||||
|
TIM4->EGR = TIM_EGR_UG;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Disable JTAG and SWD, done after hwinit1_common as HAL resets AFIO
|
* Disable JTAG and SWD, done after hwinit1_common as HAL resets AFIO
|
||||||
@@ -74,6 +102,7 @@ set_led (int value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT)
|
||||||
|
#if defined(PINPAD_CIR_SUPPORT)
|
||||||
void
|
void
|
||||||
cir_ext_disable (void)
|
cir_ext_disable (void)
|
||||||
{
|
{
|
||||||
@@ -111,4 +140,31 @@ CH_IRQ_HANDLER (TIM3_IRQHandler)
|
|||||||
chSysUnlockFromIsr();
|
chSysUnlockFromIsr();
|
||||||
CH_IRQ_EPILOGUE();
|
CH_IRQ_EPILOGUE();
|
||||||
}
|
}
|
||||||
|
#elif defined(PINPAD_DIAL_SUPPORT)
|
||||||
|
void
|
||||||
|
dial_sw_disable (void)
|
||||||
|
{
|
||||||
|
EXTI->PR = EXTI_PR_PR2;
|
||||||
|
EXTI->IMR &= ~EXTI_IMR_MR2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dial_sw_enable (void)
|
||||||
|
{
|
||||||
|
EXTI->IMR |= EXTI_IMR_MR2;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void dial_sw_interrupt (void);
|
||||||
|
|
||||||
|
CH_IRQ_HANDLER (EXTI2_IRQHandler)
|
||||||
|
{
|
||||||
|
CH_IRQ_PROLOGUE ();
|
||||||
|
chSysLockFromIsr ();
|
||||||
|
|
||||||
|
dial_sw_interrupt ();
|
||||||
|
|
||||||
|
chSysUnlockFromIsr ();
|
||||||
|
CH_IRQ_EPILOGUE ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -107,8 +107,8 @@
|
|||||||
/* Port B setup. */
|
/* Port B setup. */
|
||||||
#define GPIOB_CIR 0
|
#define GPIOB_CIR 0
|
||||||
#define GPIOB_BUTTON 2
|
#define GPIOB_BUTTON 2
|
||||||
#define GPIOB_ROT_A 3
|
#define GPIOB_ROT_A 6
|
||||||
#define GPIOB_ROT_B 4
|
#define GPIOB_ROT_B 7
|
||||||
|
|
||||||
#define GPIOB_7SEG_DP 15
|
#define GPIOB_7SEG_DP 15
|
||||||
#define GPIOB_7SEG_A 14
|
#define GPIOB_7SEG_A 14
|
||||||
|
|||||||
12
src/gnuk.h
12
src/gnuk.h
@@ -312,15 +312,19 @@ extern void flash_cnt123_write_internal (const uint8_t *p, int which, int v);
|
|||||||
extern void flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len);
|
extern void flash_do_write_internal (const uint8_t *p, int nr, const uint8_t *data, int len);
|
||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT)
|
||||||
|
#if defined(PINPAD_CIR_SUPPORT)
|
||||||
extern void cir_ext_disable (void);
|
extern void cir_ext_disable (void);
|
||||||
extern void cir_ext_enable (void);
|
extern void cir_ext_enable (void);
|
||||||
|
#elif defined(PINPAD_DIAL_SUPPORT)
|
||||||
|
extern void dial_sw_disable (void);
|
||||||
|
extern void dial_sw_enable (void);
|
||||||
|
#endif
|
||||||
|
#define PIN_INPUT_CURRENT 1
|
||||||
|
#define PIN_INPUT_NEW 2
|
||||||
|
#define PIN_INPUT_CONFIRM 3
|
||||||
#define MAX_PIN_CHARS 32
|
#define MAX_PIN_CHARS 32
|
||||||
extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
||||||
extern uint8_t pin_input_len;
|
extern uint8_t pin_input_len;
|
||||||
|
|
||||||
#define PIN_INPUT_CURRENT 1
|
|
||||||
#define PIN_INPUT_NEW 2
|
|
||||||
#define PIN_INPUT_CONFIRM 3
|
|
||||||
extern msg_t pin_main (void *arg);
|
extern msg_t pin_main (void *arg);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
222
src/pin-dial.c
Normal file
222
src/pin-dial.c
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
* pin-dial.c -- PIN input device support (rotary encoder + push switch)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Free Software Initiative of Japan
|
||||||
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
*
|
||||||
|
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
|
*
|
||||||
|
* Gnuk is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Gnuk is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "ch.h"
|
||||||
|
#include "hal.h"
|
||||||
|
#include "board.h"
|
||||||
|
#include "gnuk.h"
|
||||||
|
|
||||||
|
uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
||||||
|
uint8_t pin_input_len;
|
||||||
|
|
||||||
|
#define LED_DISP_BLINK_INTERVAL0 MS2ST(150)
|
||||||
|
#define LED_DISP_BLINK_INTERVAL1 MS2ST(100)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PB6 TIM4_CH1
|
||||||
|
* PB7 TIM4_CH2
|
||||||
|
*
|
||||||
|
* TIM4_SMCR
|
||||||
|
* SMS = 001
|
||||||
|
* TIM4_CCER
|
||||||
|
* CC1P = 0
|
||||||
|
* CC2P = 0
|
||||||
|
* TIM4_CCMR1
|
||||||
|
* CC1S= 01
|
||||||
|
* CC2S= 01
|
||||||
|
* TIM4_CR1
|
||||||
|
* CEN= 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define OFF '\x00'
|
||||||
|
#define ENTER '\x0a'
|
||||||
|
static struct led_pattern { uint8_t c, v; } led_pattern[] =
|
||||||
|
{
|
||||||
|
/* char : dp a b c d e f g */
|
||||||
|
{ ENTER, 0xf8 }, /* |- : 1 1 1 1 1 0 0 0 (enter) */
|
||||||
|
{ ' ', 0xff }, /* SPC : 1 1 1 1 1 1 1 1 */
|
||||||
|
{ '0', 0x81 }, /* 0 : 1 0 0 0 0 0 0 1 */
|
||||||
|
{ '1', 0xcf }, /* 1 : 1 1 0 0 1 1 1 1 */
|
||||||
|
{ '2', 0x92 }, /* 2 : 1 0 0 1 0 0 1 0 */
|
||||||
|
{ '3', 0x86 }, /* 3 : 1 0 0 0 0 1 1 0 */
|
||||||
|
{ '4', 0xcc }, /* 4 : 1 1 0 0 1 1 0 0 */
|
||||||
|
{ '5', 0xa4 }, /* 5 : 1 0 1 0 0 1 0 0 */
|
||||||
|
{ '6', 0xa0 }, /* 6 : 1 0 1 0 0 0 0 0 */
|
||||||
|
{ '7', 0x8d }, /* 7 : 1 0 0 0 1 1 0 1 */
|
||||||
|
{ '8', 0x80 }, /* 8 : 1 0 0 0 0 0 0 0 */
|
||||||
|
{ '9', 0x84 }, /* 9 : 1 0 0 0 0 1 0 0 */
|
||||||
|
{ 'A', 0x88 }, /* A : 1 0 0 0 1 0 0 0 */
|
||||||
|
{ 'B', 0xe0 }, /* b : 1 1 1 0 0 0 0 0 */
|
||||||
|
{ 'C', 0xb1 }, /* C : 1 0 1 1 0 0 0 1 */
|
||||||
|
{ 'D', 0xc2 }, /* d : 1 1 0 0 0 0 1 0 */
|
||||||
|
{ 'E', 0xb0 }, /* E : 1 0 1 1 0 0 0 0 */
|
||||||
|
{ 'F', 0xb8 }, /* F : 1 0 1 1 1 0 0 0 */
|
||||||
|
|
||||||
|
{ 'G', 0xa1 }, /* G : 1 0 1 0 0 0 0 1 */
|
||||||
|
{ '\xff', 0xce }, /* -| : 1 1 0 0 1 1 1 0 (backspace) */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LENGTH_LED_PATTERN (int)(sizeof led_pattern / sizeof (struct led_pattern))
|
||||||
|
|
||||||
|
static void
|
||||||
|
led_disp (uint8_t c)
|
||||||
|
{
|
||||||
|
uint16_t v = palReadPort (IOPORT2) | 0x00ff;
|
||||||
|
|
||||||
|
if (c == OFF)
|
||||||
|
v |= 0xff00;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
v &= 0x80ff;
|
||||||
|
for (i = 0; i < LENGTH_LED_PATTERN; i++)
|
||||||
|
if (led_pattern[i].c == c)
|
||||||
|
{
|
||||||
|
v |= ((led_pattern[i].v & 0x7f) << 8); /* Don't touch DP. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (led_pattern[i].c > c)
|
||||||
|
{
|
||||||
|
v |= 0x7f00; /* default: SPC */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
palWritePort (IOPORT2, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
blink_dp (void)
|
||||||
|
{
|
||||||
|
uint16_t v = palReadPort (IOPORT2) | 0x00ff;
|
||||||
|
|
||||||
|
v ^= 0x8000;
|
||||||
|
palWritePort (IOPORT2, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Thread *pin_thread;
|
||||||
|
#define EV_SW_PUSH (eventmask_t)1
|
||||||
|
|
||||||
|
void
|
||||||
|
dial_sw_interrupt (void)
|
||||||
|
{
|
||||||
|
dial_sw_disable ();
|
||||||
|
chEvtSignalI (pin_thread, EV_SW_PUSH);
|
||||||
|
palClearPad (IOPORT1, GPIOA_LED2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
msg_t
|
||||||
|
pin_main (void *arg)
|
||||||
|
{
|
||||||
|
int msg_code = (int)arg;
|
||||||
|
uint16_t count, count_prev;
|
||||||
|
uint8_t input_mode;
|
||||||
|
uint8_t sw_push_count;
|
||||||
|
uint8_t sw_event;
|
||||||
|
|
||||||
|
(void)msg_code;
|
||||||
|
|
||||||
|
pin_thread = chThdSelf ();
|
||||||
|
led_disp (' ');
|
||||||
|
|
||||||
|
TIM4->CNT = 0;
|
||||||
|
TIM4->CR1 |= TIM_CR1_CEN;
|
||||||
|
input_mode = 0;
|
||||||
|
count = count_prev = 0;
|
||||||
|
pin_input_len = 0;
|
||||||
|
sw_push_count = 0;
|
||||||
|
sw_event = 0;
|
||||||
|
|
||||||
|
while (!chThdShouldTerminate ())
|
||||||
|
{
|
||||||
|
eventmask_t m;
|
||||||
|
|
||||||
|
blink_dp ();
|
||||||
|
dial_sw_enable ();
|
||||||
|
m = chEvtWaitOneTimeout (ALL_EVENTS, LED_DISP_BLINK_INTERVAL0);
|
||||||
|
|
||||||
|
if (m == EV_SW_PUSH || sw_push_count)
|
||||||
|
{
|
||||||
|
if (palReadPad (IOPORT2, GPIOB_BUTTON) == 0)
|
||||||
|
sw_push_count++;
|
||||||
|
else /* ignore this bounce */
|
||||||
|
{
|
||||||
|
palSetPad (IOPORT1, GPIOA_LED2);
|
||||||
|
sw_push_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sw_push_count >= 2)
|
||||||
|
sw_event = 1;
|
||||||
|
|
||||||
|
count = (TIM4->CNT) / 2;
|
||||||
|
|
||||||
|
if (input_mode == 1)
|
||||||
|
{
|
||||||
|
if (count_prev != count)
|
||||||
|
input_mode = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
led_disp (ENTER);
|
||||||
|
if (sw_event)
|
||||||
|
{
|
||||||
|
palSetPad (IOPORT1, GPIOA_LED2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_mode == 0)
|
||||||
|
{
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
|
if (count < 10)
|
||||||
|
c = count + '0';
|
||||||
|
else
|
||||||
|
c = (count - 10) + 'A';
|
||||||
|
|
||||||
|
led_disp (c);
|
||||||
|
|
||||||
|
if (sw_event)
|
||||||
|
{
|
||||||
|
pin_input_buffer[pin_input_len] = c;
|
||||||
|
if (pin_input_len < MAX_PIN_CHARS - 1)
|
||||||
|
pin_input_len++;
|
||||||
|
input_mode = 1;
|
||||||
|
sw_event = sw_push_count = 0;
|
||||||
|
palSetPad (IOPORT1, GPIOA_LED2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chThdSleep (LED_DISP_BLINK_INTERVAL1);
|
||||||
|
count_prev = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
led_disp (OFF);
|
||||||
|
TIM4->CR1 &= ~TIM_CR1_CEN;
|
||||||
|
dial_sw_disable ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -516,6 +516,8 @@ icc_handle_data (void)
|
|||||||
|| icc_header->msg_type == ICC_GET_PARAMS)
|
|| icc_header->msg_type == ICC_GET_PARAMS)
|
||||||
icc_send_params ();
|
icc_send_params ();
|
||||||
else if (icc_header->msg_type == ICC_SECURE)
|
else if (icc_header->msg_type == ICC_SECURE)
|
||||||
|
{
|
||||||
|
if (icc_buffer[10] == 0x00) /* PIN verification */
|
||||||
{
|
{
|
||||||
cmd_APDU[0] = icc_buffer[25];
|
cmd_APDU[0] = icc_buffer[25];
|
||||||
cmd_APDU[1] = icc_buffer[26];
|
cmd_APDU[1] = icc_buffer[26];
|
||||||
@@ -525,6 +527,25 @@ icc_handle_data (void)
|
|||||||
chEvtSignal (gpg_thread, (eventmask_t)1);
|
chEvtSignal (gpg_thread, (eventmask_t)1);
|
||||||
next_state = ICC_STATE_EXECUTE;
|
next_state = ICC_STATE_EXECUTE;
|
||||||
}
|
}
|
||||||
|
else if (icc_buffer[10] == 0x01) /* PIN Modification */
|
||||||
|
{
|
||||||
|
uint8_t num_msgs = icc_buffer[21];
|
||||||
|
|
||||||
|
if (num_msgs == 0x00)
|
||||||
|
num_msgs = 1;
|
||||||
|
else if (num_msgs == 0xff)
|
||||||
|
num_msgs = 3;
|
||||||
|
cmd_APDU[0] = icc_buffer[27 + num_msgs];
|
||||||
|
cmd_APDU[1] = icc_buffer[28 + num_msgs];
|
||||||
|
cmd_APDU[2] = icc_buffer[29 + num_msgs];
|
||||||
|
cmd_APDU[3] = icc_buffer[30 + num_msgs];
|
||||||
|
icc_data_size = 4;
|
||||||
|
chEvtSignal (gpg_thread, (eventmask_t)1);
|
||||||
|
next_state = ICC_STATE_EXECUTE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
icc_error (ICC_MSG_DATA_OFFSET);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_INFO ("ERR03\r\n");
|
DEBUG_INFO ("ERR03\r\n");
|
||||||
|
|||||||
@@ -105,7 +105,11 @@ static const uint8_t gnukConfigDescriptor[] = {
|
|||||||
0xff, /* bClassEnvelope: */
|
0xff, /* bClassEnvelope: */
|
||||||
0, 0, /* wLCDLayout: FIXED VALUE */
|
0, 0, /* wLCDLayout: FIXED VALUE */
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT)
|
||||||
1, /* bPinSupport: with PIN pad */
|
#if defined(PINPAD_CIR_SUPPORT)
|
||||||
|
1, /* bPinSupport: with PIN pad (verify) */
|
||||||
|
#elif defined(PINPAD_DIAL_SUPPORT)
|
||||||
|
3, /* bPinSupport: with PIN pad (verify, modify) */
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
0, /* bPinSupport: No PIN pad */
|
0, /* bPinSupport: No PIN pad */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user