This commit is contained in:
NIIBE Yutaka
2013-10-31 16:52:51 +09:00
parent 1b1cf7f0e3
commit 6eccd35e47
10 changed files with 156 additions and 140 deletions

View File

@@ -1,3 +1,12 @@
2013-10-31 Niibe Yutaka <gniibe@fsij.org>
* src/main.c (main): Call msc_init before USB interrupt thread.
* src/gnuk.h, src/usb-msc.h, src/usb-msc.c, src/pin-dnd.c: Port to
Chipstx.
* src/openpgp.c (get_pinpad_input): Follow the change.
* src/usb_ctrl.c (gnuk_setup_endpoints_for_interface): Don't stall
RX of ENDP6.
2013-10-24 Niibe Yutaka <gniibe@fsij.org>
* src/Makefile.in (DEFS): Add -DCHX_PRIO_MAIN=5 for LED blink.

View File

@@ -369,7 +369,6 @@ extern void cir_ext_enable (void);
extern void dial_sw_disable (void);
extern void dial_sw_enable (void);
# elif defined(PINPAD_DND_SUPPORT)
extern uint8_t media_available;
extern void msc_init (void);
extern void msc_media_insert_change (int available);
extern int msc_scsi_write (uint32_t lba, const uint8_t *buf, size_t size);
@@ -383,7 +382,7 @@ extern void msc_scsi_stop (uint8_t code);
extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
extern uint8_t pin_input_len;
extern int pinpad_getline (int msg_code, systime_t timeout);
extern int pinpad_getline (int msg_code, uint32_t timeout_usec);
#endif

View File

@@ -330,13 +330,13 @@ main (int argc, char *argv[])
ccid_thd = chopstx_create (PRIO_CCID, __stackaddr_ccid,
__stacksize_ccid, USBthread, NULL);
usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
usb_intr, NULL);
#ifdef PINPAD_DND_SUPPORT
msc_init ();
#endif
usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
usb_intr, NULL);
while (1)
{
if (bDeviceState != UNCONNECTED)

View File

@@ -127,7 +127,7 @@ get_pinpad_input (int msg_code)
int r;
led_blink (LED_START_COMMAND);
r = pinpad_getline (msg_code, MS2ST (8000));
r = pinpad_getline (msg_code, 8000000);
led_blink (LED_FINISH_COMMAND);
return r;
}

View File

@@ -601,7 +601,7 @@ static Thread *pin_thread;
* The string itself is in PIN_INPUT_BUFFER.
*/
int
pinpad_getline (int msg_code, systime_t timeout)
pinpad_getline (int msg_code, uint32_t timeout)
{
(void)msg_code;

View File

@@ -128,7 +128,7 @@ dial_sw_interrupt (void)
int
pinpad_getline (int msg_code, systime_t timeout)
pinpad_getline (int msg_code, uint32_t timeout)
{
uint16_t count, count_prev;
uint8_t input_mode;

View File

@@ -1,7 +1,7 @@
/*
* pin-dnd.c -- PIN input support (Drag and Drop with File Manager)
*
* Copyright (C) 2011 Free Software Initiative of Japan
* Copyright (C) 2011, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -21,8 +21,12 @@
*
*/
#include <stdint.h>
#include <string.h>
#include <chopstx.h>
#include <eventflag.h>
#include "config.h"
#include "ch.h"
#include "board.h"
#include "gnuk.h"
#include "usb-msc.h"
@@ -39,7 +43,7 @@ static const struct folder folder_ini = { 0, { 1, 2, 3, 4, 5, 6, 7 } };
uint8_t pin_input_buffer[MAX_PIN_CHARS];
uint8_t pin_input_len;
static Thread *pin_thread;
static uint8_t msg;
/*
* Let user input PIN string.
@@ -47,9 +51,9 @@ static Thread *pin_thread;
* The string itself is in PIN_INPUT_BUFFER.
*/
int
pinpad_getline (int msg_code, systime_t timeout)
pinpad_getline (int msg_code, uint32_t timeout)
{
msg_t msg;
uint8_t msg_received;
(void)msg_code;
(void)timeout;
@@ -65,14 +69,13 @@ pinpad_getline (int msg_code, systime_t timeout)
while (1)
{
chSysLock ();
pin_thread = chThdSelf ();
chSchGoSleepS (THD_STATE_SUSPENDED);
msg = chThdSelf ()->p_u.rdymsg;
chSysUnlock ();
chopstx_mutex_lock (pinpad_mutex);
chopstx_cond_wait (pinpad_cond, pinpad_mutex);
msg_received = msg;
chopstx_mutex_unlock (pinpad_mutex);
led_blink (LED_ONESHOT);
if (msg != 0)
if (msg_received != 0)
break;
}
@@ -86,21 +89,21 @@ pinpad_getline (int msg_code, systime_t timeout)
static void pinpad_input (void)
{
chSysLock ();
pin_thread->p_u.rdymsg = 0;
chSchReadyI (pin_thread);
chSysUnlock ();
chopstx_mutex_lock (pinpad_mutex);
msg = 0;
chopstx_cond_signal (pinpad_cond);
chopstx_mutex_unlock (pinpad_mutex);
}
static void pinpad_finish_entry (int cancel)
{
chSysLock ();
chopstx_mutex_lock (pinpad_mutex);
if (cancel)
pin_thread->p_u.rdymsg = 2;
msg = 2;
else
pin_thread->p_u.rdymsg = 1;
chSchReadyI (pin_thread);
chSysUnlock ();
msg = 1;
chopstx_cond_signal (pinpad_cond);
chopstx_mutex_unlock (pinpad_mutex);
}
#define TOTAL_SECTOR 68

View File

@@ -1,7 +1,7 @@
/*
* usb-msc.c -- USB Mass Storage Class protocol handling
*
* Copyright (C) 2011, 2012 Free Software Initiative of Japan
* Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@@ -21,12 +21,37 @@
*
*/
#include <stdint.h>
#include <string.h>
#include <chopstx.h>
#include "config.h"
#include "ch.h"
#include "gnuk.h"
#include "usb_lld.h"
#include "usb-msc.h"
extern uint8_t __process5_stack_base__, __process5_stack_size__;
const uint32_t __stackaddr_msc = (uint32_t)&__process5_stack_base__;
const size_t __stacksize_msc = (size_t)&__process5_stack_size__;
#define PRIO_MSC 3
static chopstx_mutex_t a_pinpad_mutex;
static chopstx_cond_t a_pinpad_cond;
static chopstx_mutex_t a_msc_mutex;
static chopstx_cond_t a_msc_cond;
#define RDY_OK 0
#define RDY_RESET 1
static uint8_t msg;
chopstx_mutex_t *pinpad_mutex = &a_pinpad_mutex;
chopstx_cond_t *pinpad_cond = &a_pinpad_cond;
static chopstx_mutex_t *msc_mutex = &a_msc_mutex;
static chopstx_cond_t *msc_cond = &a_msc_cond;
struct usb_endp_in {
const uint8_t *txbuf; /* Pointer to the transmission buffer. */
size_t txsize; /* Transmit transfer size remained. */
@@ -42,8 +67,6 @@ struct usb_endp_out {
static struct usb_endp_in ep6_in;
static struct usb_endp_out ep6_out;
static Thread *the_thread;
#define ENDP_MAX_SIZE 64
static uint8_t msc_state;
@@ -61,10 +84,14 @@ static void usb_start_transmit (const uint8_t *p, size_t n)
}
/* "Data Transmitted" callback */
void EP6_IN_Callback (void)
void
EP6_IN_Callback (void)
{
size_t n = (size_t)usb_lld_tx_data_len (ENDP6);
size_t n;
chopstx_mutex_lock (msc_mutex);
n = (size_t)usb_lld_tx_data_len (ENDP6);
ep6_in.txbuf += n;
ep6_in.txcnt += n;
ep6_in.txsize -= n;
@@ -76,27 +103,21 @@ void EP6_IN_Callback (void)
else
n = ep6_in.txsize;
usb_lld_write (ENDP6, (uint8_t *)ep6_in.txbuf, n);
return;
}
/* Transmit has been completed, notify the waiting thread */
switch (msc_state)
{
case MSC_SENDING_CSW:
case MSC_DATA_IN:
if (the_thread != NULL) {
Thread *tp;
chSysLockFromIsr ();
tp = the_thread;
the_thread = NULL;
tp->p_u.rdymsg = RDY_OK;
chSchReadyI (tp);
chSysUnlockFromIsr ();
else
/* Transmit has been completed, notify the waiting thread */
switch (msc_state)
{
case MSC_SENDING_CSW:
case MSC_DATA_IN:
msg = RDY_OK;
chopstx_cond_signal (msc_cond);
break;
default:
break;
}
break;
default:
break;
}
chopstx_mutex_unlock (msc_mutex);
}
@@ -109,11 +130,15 @@ static void usb_start_receive (uint8_t *p, size_t n)
}
/* "Data Received" call back */
void EP6_OUT_Callback (void)
void
EP6_OUT_Callback (void)
{
size_t n = (size_t)usb_lld_rx_data_len (ENDP6);
size_t n;
int err = 0;
chopstx_mutex_lock (msc_mutex);
n = (size_t)usb_lld_rx_data_len (ENDP6);
if (n > ep6_out.rxsize)
{ /* buffer overflow */
err = 1;
@@ -126,29 +151,22 @@ void EP6_OUT_Callback (void)
ep6_out.rxsize -= n;
if (n == ENDP_MAX_SIZE && ep6_out.rxsize != 0)
{ /* More data to be received */
usb_lld_rx_enable (ENDP6);
return;
}
/* Receiving has been completed, notify the waiting thread */
switch (msc_state)
{
case MSC_IDLE:
case MSC_DATA_OUT:
if (the_thread != NULL) {
Thread *tp;
chSysLockFromIsr ();
tp = the_thread;
the_thread = NULL;
tp->p_u.rdymsg = err? RDY_RESET : RDY_OK;
chSchReadyI (tp);
chSysUnlockFromIsr ();
/* More data to be received */
usb_lld_rx_enable (ENDP6);
else
/* Receiving has been completed, notify the waiting thread */
switch (msc_state)
{
case MSC_IDLE:
case MSC_DATA_OUT:
msg = err ? RDY_RESET : RDY_OK;
chopstx_cond_signal (msc_cond);
break;
default:
break;
}
break;
default:
break;
}
chopstx_mutex_unlock (msc_mutex);
}
static const uint8_t scsi_inquiry_data_00[] = { 0, 0, 0, 0, 0 };
@@ -193,7 +211,8 @@ static uint8_t scsi_sense_data_fixed[] = {
0x00, 0x00, 0x00,
};
static void set_scsi_sense_data(uint8_t sense_key, uint8_t asc) {
static void set_scsi_sense_data(uint8_t sense_key, uint8_t asc)
{
scsi_sense_data_desc[1] = scsi_sense_data_fixed[2] = sense_key;
scsi_sense_data_desc[2] = scsi_sense_data_fixed[12] = asc;
}
@@ -206,7 +225,8 @@ static uint8_t keep_contingent_allegiance;
uint8_t media_available;
void msc_media_insert_change (int available)
void
msc_media_insert_change (int available)
{
contingent_allegiance = 1;
media_available = available;
@@ -239,38 +259,27 @@ static struct CBW CBW;
static struct CSW CSW;
/* called with holding the lock. */
static int msc_recv_data (void)
{
msg_t msg;
chSysLock ();
msc_state = MSC_DATA_OUT;
the_thread = chThdSelf ();
usb_start_receive (buf, 512);
chSchGoSleepS (THD_STATE_SUSPENDED);
msg = chThdSelf ()->p_u.rdymsg;
chSysUnlock ();
chopstx_cond_wait (msc_cond, msc_mutex);
return 0;
}
/* called with holding the lock. */
static void msc_send_data (const uint8_t *p, size_t n)
{
msg_t msg;
chSysLock ();
msc_state = MSC_DATA_IN;
the_thread = chThdSelf ();
usb_start_transmit (p, n);
chSchGoSleepS (THD_STATE_SUSPENDED);
msg = chThdSelf ()->p_u.rdymsg;
chopstx_cond_wait (msc_cond, msc_mutex);
CSW.dCSWDataResidue -= (uint32_t)n;
chSysUnlock();
}
/* called with holding the lock. */
static void msc_send_result (const uint8_t *p, size_t n)
{
msg_t msg;
if (p != NULL)
{
if (n > CBW.dCBWDataTransferLength)
@@ -282,44 +291,32 @@ static void msc_send_result (const uint8_t *p, size_t n)
}
CSW.dCSWSignature = MSC_CSW_SIGNATURE;
chSysLock ();
msc_state = MSC_SENDING_CSW;
the_thread = chThdSelf ();
usb_start_transmit ((uint8_t *)&CSW, sizeof CSW);
chSchGoSleepS (THD_STATE_SUSPENDED);
msg = chThdSelf ()->p_u.rdymsg;
chSysUnlock ();
chopstx_cond_wait (msc_cond, msc_mutex);
}
void msc_handle_command (void)
void
msc_handle_command (void)
{
size_t n;
uint32_t nblocks, secsize;
uint32_t lba;
int r;
msg_t msg;
chSysLock();
chopstx_mutex_lock (msc_mutex);
msc_state = MSC_IDLE;
the_thread = chThdSelf ();
usb_start_receive ((uint8_t *)&CBW, sizeof CBW);
chSchGoSleepTimeoutS (THD_STATE_SUSPENDED, MS2ST (1000));
msg = chThdSelf ()->p_u.rdymsg;
chSysUnlock ();
chopstx_cond_wait (msc_cond, msc_mutex);
if (msg != RDY_OK)
{
/* Error occured, ignore the request and go into error state */
msc_state = MSC_ERROR;
if (msg != RDY_TIMEOUT)
{
chSysLock ();
usb_lld_stall_rx (ENDP6);
chSysUnlock ();
}
return;
usb_lld_stall_rx (ENDP6);
goto done;
}
n = ep6_out.rxcnt;
@@ -327,10 +324,8 @@ void msc_handle_command (void)
if ((n != sizeof (struct CBW)) || (CBW.dCBWSignature != MSC_CBW_SIGNATURE))
{
msc_state = MSC_ERROR;
chSysLock ();
usb_lld_stall_rx (ENDP6);
chSysUnlock ();
return;
goto done;
}
CSW.dCSWTag = CBW.dCBWTag;
@@ -348,7 +343,7 @@ void msc_handle_command (void)
contingent_allegiance = 0;
set_scsi_sense_data (0x00, 0x00);
}
return;
goto done;
case SCSI_INQUIRY:
if (CBW.CBWCB[1] & 0x01) /* EVPD */
/* assume page 00 */
@@ -357,7 +352,7 @@ void msc_handle_command (void)
else
msc_send_result ((uint8_t *)&scsi_inquiry_data,
sizeof scsi_inquiry_data);
return;
goto done;
case SCSI_READ_FORMAT_CAPACITIES:
buf[8] = scsi_read_format_capacities (&nblocks, &secsize);
buf[0] = buf[1] = buf[2] = 0;
@@ -370,7 +365,7 @@ void msc_handle_command (void)
buf[10] = (uint8_t)(secsize >> 8);
buf[11] = (uint8_t)(secsize >> 0);
msc_send_result (buf, 12);
return;
goto done;
case SCSI_START_STOP_UNIT:
if (CBW.CBWCB[4] == 0x00 /* stop */
|| CBW.CBWCB[4] == 0x02 /* eject */ || CBW.CBWCB[4] == 0x03 /* close */)
@@ -388,7 +383,7 @@ void msc_handle_command (void)
CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
CSW.dCSWDataResidue = 0;
msc_send_result (NULL, 0);
return;
goto done;
}
/* fall through */
success:
@@ -398,12 +393,12 @@ void msc_handle_command (void)
CSW.bCSWStatus = MSC_CSW_STATUS_PASSED;
CSW.dCSWDataResidue = CBW.dCBWDataTransferLength;
msc_send_result (NULL, 0);
return;
goto done;
case SCSI_MODE_SENSE6:
buf[0] = 0x03;
buf[1] = buf[2] = buf[3] = 0;
msc_send_result (buf, 4);
return;
goto done;
case SCSI_READ_CAPACITY10:
scsi_read_format_capacities (&nblocks, &secsize);
buf[0] = (uint8_t)((nblocks - 1) >> 24);
@@ -415,7 +410,7 @@ void msc_handle_command (void)
buf[6] = (uint8_t)(secsize >> 8);
buf[7] = (uint8_t)(secsize >> 0);
msc_send_result (buf, 8);
return;
goto done;
case SCSI_READ10:
case SCSI_WRITE10:
break;
@@ -425,16 +420,14 @@ void msc_handle_command (void)
CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
CSW.dCSWDataResidue = 0;
msc_send_result (NULL, 0);
return;
goto done;
}
else
{
msc_state = MSC_ERROR;
chSysLock ();
usb_lld_stall_tx (ENDP6);
usb_lld_stall_rx (ENDP6);
chSysUnlock ();
return;
goto done;
}
}
@@ -501,6 +494,10 @@ void msc_handle_command (void)
}
msc_recv_data ();
if (msg != RDY_OK)
/* ignore erroneous packet, ang go next. */
continue;
if ((r = msc_scsi_write (lba, buf, 512)) == 0)
{
if (++CBW.CBWCB[5] == 0)
@@ -526,25 +523,34 @@ void msc_handle_command (void)
msc_send_result (NULL, 0);
}
}
done:
chopstx_mutex_unlock (msc_mutex);
}
static msg_t
static void *
msc_main (void *arg)
{
(void)arg;
chopstx_mutex_init (msc_mutex);
chopstx_cond_init (msc_cond);
chopstx_mutex_init (pinpad_mutex);
chopstx_cond_init (pinpad_cond);
/* Initially, it starts with no media */
msc_media_insert_change (0);
while (1)
msc_handle_command ();
return 0;
return NULL;
}
static WORKING_AREA(wa_msc_thread, 128);
void msc_init (void)
void
msc_init (void)
{
chThdCreateStatic (wa_msc_thread, sizeof (wa_msc_thread),
NORMALPRIO, msc_main, NULL);
chopstx_create (PRIO_MSC, __stackaddr_msc, __stacksize_msc, msc_main, NULL);
}

View File

@@ -50,3 +50,5 @@ struct CSW {
#define SCSI_ERROR_DATA_PROTECT 7
extern uint8_t media_available;
extern chopstx_mutex_t *pinpad_mutex;
extern chopstx_cond_t *pinpad_cond;

View File

@@ -162,11 +162,8 @@ gnuk_setup_endpoints_for_interface (uint16_t interface, int stop)
else if (interface == MSC_INTERFACE_NO)
{
if (!stop)
{
usb_lld_setup_endpoint (ENDP6, EP_BULK, 0,
ENDP6_RXADDR, ENDP6_TXADDR, 64);
usb_lld_stall_rx (ENDP6);
}
usb_lld_setup_endpoint (ENDP6, EP_BULK, 0,
ENDP6_RXADDR, ENDP6_TXADDR, 64);
else
{
usb_lld_stall_tx (ENDP6);