* main.c - main routine of neug
*
* Main routine:
- * Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
+ * Copyright (C) 2011, 2012, 2013, 2015, 2016
+ * Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of NeuG, a True Random Number Generator
#include "neug.h"
#include "usb_lld.h"
#include "sys.h"
-#include "stm32f103.h"
+#include "mcu/stm32f103.h"
#include "adc.h"
-chopstx_mutex_t usb_mtx;
-chopstx_cond_t cnd_usb;
+enum {
+ FSIJ_DEVICE_RUNNING = 0,
+ FSIJ_DEVICE_EXITED,
+ FSIJ_DEVICE_EXEC_REQUESTED,
+ /**/
+ FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED = 254,
+ FSIJ_DEVICE_NEUG_EXIT_REQUESTED = 255
+};
+
+#ifdef FRAUCHEKY_SUPPORT
+static uint8_t running_neug;
+extern void EP6_IN_Callback (uint32_t len);
+extern void EP6_OUT_Callback (void);
+#endif
+
+static chopstx_mutex_t usb_mtx;
+static chopstx_cond_t usb_cnd;
+static uint32_t bDeviceState = UNCONNECTED; /* USB device status */
+static uint8_t fsij_device_state = FSIJ_DEVICE_RUNNING;
+static uint8_t connected;
+
#define ENDP0_RXADDR (0x40)
#define ENDP0_TXADDR (0x80)
/* USB Device Descriptor */
static const uint8_t vcom_device_desc[18] = {
18, /* bLength */
- USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
+ DEVICE_DESCRIPTOR, /* bDescriptorType */
0x10, 0x01, /* bcdUSB = 1.1 */
0x02, /* bDeviceClass (CDC). */
0x00, /* bDeviceSubClass. */
1 /* bNumConfigurations. */
};
+#define VCOM_FEATURE_BUS_POWERED 0x80
+
/* Configuration Descriptor tree for a CDC.*/
-static const uint8_t vcom_configuration_desc[67] = {
+static const uint8_t vcom_config_desc[67] = {
9,
- USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
+ CONFIG_DESCRIPTOR, /* bDescriptorType: Configuration */
/* Configuration Descriptor.*/
67, 0x00, /* wTotalLength. */
0x02, /* bNumInterfaces. */
0x01, /* bConfigurationValue. */
0, /* iConfiguration. */
- 0x80, /* bmAttributes (bus powered). */
+ VCOM_FEATURE_BUS_POWERED, /* bmAttributes. */
50, /* bMaxPower (100mA). */
/* Interface Descriptor.*/
9,
- USB_INTERFACE_DESCRIPTOR_TYPE,
+ INTERFACE_DESCRIPTOR,
0x00, /* bInterfaceNumber. */
0x00, /* bAlternateSetting. */
0x01, /* bNumEndpoints. */
0x01, /* bSlaveInterface0 (Data Class Interface). */
/* Endpoint 2 Descriptor.*/
7,
- USB_ENDPOINT_DESCRIPTOR_TYPE,
+ ENDPOINT_DESCRIPTOR,
ENDP2|0x80, /* bEndpointAddress. */
0x03, /* bmAttributes (Interrupt). */
0x08, 0x00, /* wMaxPacketSize. */
0xFF, /* bInterval. */
/* Interface Descriptor.*/
9,
- USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
+ INTERFACE_DESCRIPTOR, /* bDescriptorType: */
0x01, /* bInterfaceNumber. */
0x00, /* bAlternateSetting. */
0x02, /* bNumEndpoints. */
0x00, /* iInterface. */
/* Endpoint 3 Descriptor.*/
7,
- USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
+ ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
ENDP3, /* bEndpointAddress. */
0x02, /* bmAttributes (Bulk). */
0x40, 0x00, /* wMaxPacketSize. */
0x00, /* bInterval. */
/* Endpoint 1 Descriptor.*/
7,
- USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
+ ENDPOINT_DESCRIPTOR, /* bDescriptorType: Endpoint */
ENDP1|0x80, /* bEndpointAddress. */
0x02, /* bmAttributes (Bulk). */
0x40, 0x00, /* wMaxPacketSize. */
*/
static const uint8_t vcom_string0[4] = {
4, /* bLength */
- USB_STRING_DESCRIPTOR_TYPE,
+ STRING_DESCRIPTOR,
0x09, 0x04 /* LangID = 0x0409: US-English */
};
-#define USB_STRINGS_FOR_NEUG 1
#include "usb-strings.c.inc"
-/*
- * Serial Number string. NOTE: This does not have CONST qualifier.
- */
-static uint8_t vcom_string3[28] = {
- 28, /* bLength. */
- USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType. */
- '0', 0, '.', 0, '0', 0, '6', 0, /* Version number of NeuG. */
- '-', 0,
- 0, 0, 0, 0, /* Filled by Unique device ID. */
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
-};
-
+static void neug_setup_endpoints_for_interface (uint16_t interface, int stop);
+#ifdef FRAUCHEKY_SUPPORT
+extern int fraucheky_enabled (void);
+extern void fraucheky_main (void);
+
+extern void fraucheky_setup_endpoints_for_interface (int stop);
+extern int fraucheky_setup (uint8_t req, uint8_t req_no,
+ struct req_args *detail);
+extern int fraucheky_get_descriptor (uint8_t rcp, uint8_t desc_type,
+ uint8_t desc_index,
+ struct req_args *detail);
+#endif
#define NUM_INTERFACES 2
-uint32_t bDeviceState = UNCONNECTED; /* USB device status */
-
void
usb_cb_device_reset (void)
{
- /* Set DEVICE as not configured */
- usb_lld_set_configuration (0);
-
- /* Current Feature initialization */
- usb_lld_set_feature (vcom_configuration_desc[7]);
+ int i;
- usb_lld_reset ();
+ usb_lld_reset (VCOM_FEATURE_BUS_POWERED);
- /* Initialize Endpoint 0 */
+ /* Initialize Endpoint 0. */
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
+
+ /* Stop the interface */
+ for (i = 0; i < NUM_INTERFACES; i++)
+ neug_setup_endpoints_for_interface (i, 1);
+
+ /* Notify upper layer. */
+ chopstx_mutex_lock (&usb_mtx);
+ bDeviceState = ATTACHED;
+ connected = 0;
+ chopstx_cond_signal (&usb_cnd);
+ chopstx_mutex_unlock (&usb_mtx);
}
extern uint8_t _regnual_start, __heap_end__;
#define USB_FSIJ_MEMINFO 0
#define USB_FSIJ_DOWNLOAD 1
#define USB_FSIJ_EXEC 2
+#define USB_NEUG_SET_PASSWD 253
#define USB_NEUG_GET_INFO 254
#define USB_NEUG_EXIT 255 /* Ask to exit and to receive reGNUal */
-enum {
- FSIJ_DEVICE_RUNNING = 0,
- FSIJ_DEVICE_EXITED,
- FSIJ_DEVICE_EXEC_REQUESTED,
- /**/
- FSIJ_DEVICE_NEUG_EXIT_REQUESTED = 255
-};
+uint8_t neug_passwd[33] __attribute__ ((section(".passwd"))) = {
+ 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+static uint8_t usbbuf[64];
-static uint8_t fsij_device_state = FSIJ_DEVICE_RUNNING;
+#define DEFAULT_PASSWD "12345678"
+#define DEFAULT_PASSWD_LEN 8
+
+static void set_passwd (void)
+{
+ flash_unlock ();
+ if (neug_passwd[0] != 0xff)
+ flash_erase_page ((uint32_t)neug_passwd);
+ if (usbbuf[0] == DEFAULT_PASSWD_LEN
+ && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
+ return;
+ flash_write ((uint32_t)neug_passwd, usbbuf, usbbuf[0] + 1);
+}
static uint32_t rbit (uint32_t v)
{
return USB_UNSUPPORT;
}
-void
-usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value,
- uint16_t index, uint16_t len)
-{
- uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
- if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)
- && USB_SETUP_SET (req) && len == 0)
- {
- if (req_no == USB_FSIJ_EXEC)
- {
- if (fsij_device_state != FSIJ_DEVICE_EXITED)
- return;
-
- (void)value; (void)index;
- usb_lld_prepare_shutdown (); /* No further USB communication */
- fsij_device_state = FSIJ_DEVICE_EXEC_REQUESTED;
- }
- else if (req_no == USB_NEUG_EXIT)
- {
- /* Force exit from the main loop. */
- chopstx_mutex_lock (&usb_mtx);
- chopstx_cond_signal (&cnd_usb);
- chopstx_mutex_unlock (&usb_mtx);
- }
- }
-}
+#define NEUG_SPECIAL_BITRATE 110
struct line_coding
{
uint8_t format;
uint8_t paritytype;
uint8_t datatype;
-};
+} __attribute__((packed));
static struct line_coding line_coding = {
115200, /* baud rate: 115200 */
0x08 /* bits: 8 */
};
-static uint8_t connected;
+#define CDC_CTRL_DTR 0x0001
-static int
-vcom_port_data_setup (uint8_t req, uint8_t req_no, uint16_t value)
+void
+usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
{
- if (USB_SETUP_GET (req))
+ uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
+
+ if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) && USB_SETUP_SET (req))
{
- if (req_no == USB_CDC_REQ_GET_LINE_CODING)
+ if (req_no == USB_FSIJ_EXEC)
{
- usb_lld_set_data_to_send (&line_coding, sizeof(line_coding));
- return USB_SUCCESS;
+ chopstx_mutex_lock (&usb_mtx);
+ if (fsij_device_state == FSIJ_DEVICE_EXITED)
+ {
+ usb_lld_prepare_shutdown (); /* No further USB communication */
+ fsij_device_state = FSIJ_DEVICE_EXEC_REQUESTED;
+ }
+ chopstx_mutex_unlock (&usb_mtx);
+ }
+ else if (req_no == USB_NEUG_SET_PASSWD)
+ set_passwd ();
+ else if (req_no == USB_NEUG_EXIT)
+ {
+ if ((neug_passwd[0] == 0xff && usbbuf[0] == DEFAULT_PASSWD_LEN
+ && !memcmp (usbbuf + 1, DEFAULT_PASSWD, DEFAULT_PASSWD_LEN))
+ || (neug_passwd[0] == usbbuf[0]
+ && !memcmp (neug_passwd+1, usbbuf+1, neug_passwd[0])))
+ {
+ chopstx_mutex_lock (&usb_mtx);
+ fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
+ chopstx_cond_signal (&usb_cnd);
+ chopstx_mutex_unlock (&usb_mtx);
+ }
}
}
- else /* USB_SETUP_SET (req) */
+ else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0
+ && USB_SETUP_SET (req))
{
- if (req_no == USB_CDC_REQ_SET_LINE_CODING)
+ if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
{
- usb_lld_set_data_to_recv (&line_coding, sizeof(line_coding));
- return USB_SUCCESS;
+ /* Open/close the connection. */
+ chopstx_mutex_lock (&usb_mtx);
+ connected = (arg->value & CDC_CTRL_DTR)? 1 : 0;
+ chopstx_cond_signal (&usb_cnd);
+ chopstx_mutex_unlock (&usb_mtx);
}
- else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
+#ifdef FRAUCHEKY_SUPPORT
+ else if (req_no == USB_CDC_REQ_SET_LINE_CODING)
{
- uint8_t connected_saved = connected;
-
- if (value != 0)
- {
- if (connected == 0)
- /* It's Open call */
- connected++;
- }
- else
+ chopstx_mutex_lock (&usb_mtx);
+ if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
{
- if (connected)
- /* Close call */
- connected = 0;
+ fsij_device_state = FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED;
+ chopstx_cond_signal (&usb_cnd);
}
-
- chopstx_mutex_lock (&usb_mtx);
- if (connected != connected_saved)
- chopstx_cond_signal (&cnd_usb);
+ else if (fsij_device_state == FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED)
+ fsij_device_state = FSIJ_DEVICE_RUNNING;
chopstx_mutex_unlock (&usb_mtx);
+ }
+#endif
+ }
+}
+
+static int
+vcom_port_data_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
+{
+ if (USB_SETUP_GET (req))
+ {
+ if (req_no == USB_CDC_REQ_GET_LINE_CODING)
+ return usb_lld_reply_request (&line_coding, sizeof(line_coding), arg);
+ }
+ else /* USB_SETUP_SET (req) */
+ {
+ if (req_no == USB_CDC_REQ_SET_LINE_CODING
+ && arg->len == sizeof (line_coding))
+ {
+ usb_lld_set_data_to_recv (&line_coding, sizeof (line_coding));
return USB_SUCCESS;
}
+ else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
+ return USB_SUCCESS;
}
return USB_UNSUPPORT;
}
int
-usb_cb_setup (uint8_t req, uint8_t req_no,
- uint16_t value, uint16_t index, uint16_t len)
+usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
{
uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
{
if (req_no == USB_FSIJ_MEMINFO)
{
- usb_lld_set_data_to_send (mem_info, sizeof (mem_info));
+ chopstx_mutex_lock (&usb_mtx);
+ if (fsij_device_state != FSIJ_DEVICE_EXITED)
+ {
+ chopstx_mutex_unlock (&usb_mtx);
+ return USB_UNSUPPORT;
+ }
+ chopstx_mutex_unlock (&usb_mtx);
+ usb_lld_reply_request (mem_info, sizeof (mem_info), arg);
return USB_SUCCESS;
}
else if (req_no == USB_NEUG_GET_INFO)
{
- if (index == 0)
- usb_lld_set_data_to_send (&neug_mode, sizeof (uint8_t));
- else if (index == 1)
- usb_lld_set_data_to_send (&neug_err_cnt, sizeof (uint16_t));
- else if (index == 2)
- usb_lld_set_data_to_send (&neug_err_cnt_rc, sizeof (uint16_t));
- else if (index == 3)
- usb_lld_set_data_to_send (&neug_err_cnt_p64, sizeof (uint16_t));
- else if (index == 4)
- usb_lld_set_data_to_send (&neug_err_cnt_p4k, sizeof (uint16_t));
- else if (index == 5)
- usb_lld_set_data_to_send (&neug_rc_max, sizeof (uint16_t));
- else if (index == 6)
- usb_lld_set_data_to_send (&neug_p64_max, sizeof (uint16_t));
- else if (index == 7)
- usb_lld_set_data_to_send (&neug_p4k_max, sizeof (uint16_t));
+ if (arg->index == 0)
+ usb_lld_reply_request (&neug_mode, sizeof (uint8_t), arg);
+ else if (arg->index == 1)
+ usb_lld_reply_request (&neug_err_cnt, sizeof (uint16_t), arg);
+ else if (arg->index == 2)
+ usb_lld_reply_request (&neug_err_cnt_rc, sizeof (uint16_t), arg);
+ else if (arg->index == 3)
+ usb_lld_reply_request (&neug_err_cnt_p64, sizeof (uint16_t), arg);
+ else if (arg->index == 4)
+ usb_lld_reply_request (&neug_err_cnt_p4k, sizeof (uint16_t), arg);
+ else if (arg->index == 5)
+ usb_lld_reply_request (&neug_rc_max, sizeof (uint16_t), arg);
+ else if (arg->index == 6)
+ usb_lld_reply_request (&neug_p64_max, sizeof (uint16_t), arg);
+ else if (arg->index == 7)
+ usb_lld_reply_request (&neug_p4k_max, sizeof (uint16_t), arg);
else
return USB_UNSUPPORT;
}
else /* SETUP_SET */
{
- uint8_t *addr = (uint8_t *)(0x20000000 + value * 0x100 + index);
+ uint8_t *addr = (uint8_t *)(0x20000000 + arg->value * 0x100 + arg->index);
if (req_no == USB_FSIJ_DOWNLOAD)
{
+ chopstx_mutex_lock (&usb_mtx);
if (fsij_device_state != FSIJ_DEVICE_EXITED)
- return USB_UNSUPPORT;
+ {
+ chopstx_mutex_unlock (&usb_mtx);
+ return USB_UNSUPPORT;
+ }
+ chopstx_mutex_unlock (&usb_mtx);
- if (addr < &_regnual_start || addr + len > &__heap_end__)
+ if (addr < &_regnual_start || addr + arg->len > &__heap_end__)
return USB_UNSUPPORT;
- if (index + len < 256)
- memset (addr + index + len, 0, 256 - (index + len));
+ if (arg->index + arg->len < 256)
+ memset (addr + arg->index + arg->len, 0, 256 - (arg->index + arg->len));
- usb_lld_set_data_to_recv (addr, len);
+ usb_lld_set_data_to_recv (addr, arg->len);
return USB_SUCCESS;
}
- else if (req_no == USB_FSIJ_EXEC && len == 0)
+ else if (req_no == USB_FSIJ_EXEC && arg->len == 0)
{
+ chopstx_mutex_lock (&usb_mtx);
if (fsij_device_state != FSIJ_DEVICE_EXITED)
- return USB_UNSUPPORT;
+ {
+ chopstx_mutex_unlock (&usb_mtx);
+ return USB_UNSUPPORT;
+ }
+ chopstx_mutex_unlock (&usb_mtx);
if (((uint32_t)addr & 0x03))
return USB_UNSUPPORT;
return download_check_crc32 ((uint32_t *)addr);
}
- else if (req_no == USB_NEUG_EXIT && len == 0)
+ else if (req_no == USB_NEUG_SET_PASSWD && arg->len <= 32)
+ {
+ usbbuf[0] = arg->len;
+ usb_lld_set_data_to_recv (usbbuf + 1, arg->len);
+ return USB_SUCCESS;
+ }
+ else if (req_no == USB_NEUG_EXIT && arg->len <= 32)
{
+ chopstx_mutex_lock (&usb_mtx);
if (fsij_device_state != FSIJ_DEVICE_RUNNING)
- return USB_UNSUPPORT;
+ {
+ chopstx_mutex_unlock (&usb_mtx);
+ return USB_UNSUPPORT;
+ }
+ chopstx_mutex_unlock (&usb_mtx);
- fsij_device_state = FSIJ_DEVICE_NEUG_EXIT_REQUESTED;
+ usbbuf[0] = arg->len;
+ usb_lld_set_data_to_recv (usbbuf + 1, arg->len);
return USB_SUCCESS;
}
}
}
- else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT))
- if (index == 0)
- return vcom_port_data_setup (req, req_no, value);
+ else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)
+ && arg->index == 0)
+ {
+#ifdef FRAUCHEKY_SUPPORT
+ if (running_neug)
+ return vcom_port_data_setup (req, req_no, arg);
+ else
+ fraucheky_setup (req, req_no, arg);
+#else
+ return vcom_port_data_setup (req, req_no, arg);
+#endif
+ }
return USB_UNSUPPORT;
}
int
-usb_cb_get_descriptor (uint8_t desc_type, uint16_t index, uint16_t value)
+usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
+ struct req_args *arg)
{
- (void)index;
+#ifdef FRAUCHEKY_SUPPORT
+ if (!running_neug)
+ return fraucheky_get_descriptor (rcp, desc_type, desc_index, arg);
+#endif
+
+ if (rcp != DEVICE_RECIPIENT)
+ return USB_UNSUPPORT;
+
if (desc_type == DEVICE_DESCRIPTOR)
- {
- usb_lld_set_data_to_send (vcom_device_desc, sizeof (vcom_device_desc));
- return USB_SUCCESS;
- }
+ return usb_lld_reply_request (vcom_device_desc, sizeof (vcom_device_desc),
+ arg);
else if (desc_type == CONFIG_DESCRIPTOR)
- {
- usb_lld_set_data_to_send (vcom_configuration_desc,
- sizeof (vcom_configuration_desc));
- return USB_SUCCESS;
- }
+ return usb_lld_reply_request (vcom_config_desc, sizeof (vcom_config_desc),
+ arg);
else if (desc_type == STRING_DESCRIPTOR)
{
- uint8_t desc_index = value & 0xff;
const uint8_t *str;
int size;
size = sizeof (neug_string_product);
break;
case 3:
- str = vcom_string3;
- size = sizeof (vcom_string3);
+ str = neug_string_serial;
+ size = sizeof (neug_string_serial);
break;
case 4:
str = neug_revision_detail;
str = sys_version;
size = sizeof (sys_version);
break;
+#ifdef USE_SYS3
+ case 7:
+ {
+ int i;
+ str = usbbuf;
+ for (i = 0; i < (int)sizeof (usbbuf)/2 - 2; i++)
+ {
+ if (sys_board_name[i] == 0)
+ break;
+
+ usbbuf[i*2+2] = sys_board_name[i];
+ usbbuf[i*2+3] = 0;
+ }
+ usbbuf[0] = i*2 + 2;
+ usbbuf[1] = STRING_DESCRIPTOR;
+ size = i*2 + 2;
+ }
+ break;
+#endif
default:
return USB_UNSUPPORT;
}
- usb_lld_set_data_to_send (str, size);
- return USB_SUCCESS;
+ return usb_lld_reply_request (str, size, arg);
}
return USB_UNSUPPORT;
{
if (interface == 0)
{
+#ifdef FRAUCHEKY_SUPPORT
+ if (running_neug)
+ {
+ if (!stop)
+ usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
+ else
+ usb_lld_stall_tx (ENDP2);
+ }
+ else
+ fraucheky_setup_endpoints_for_interface (stop);
+#else
if (!stop)
usb_lld_setup_endpoint (ENDP2, EP_INTERRUPT, 0, 0, ENDP2_TXADDR, 0);
else
usb_lld_stall_tx (ENDP2);
+#endif
}
else if (interface == 1)
{
{
usb_lld_setup_endpoint (ENDP1, EP_BULK, 0, 0, ENDP1_TXADDR, 0);
usb_lld_setup_endpoint (ENDP3, EP_BULK, 0, ENDP3_RXADDR, 0, 64);
+ /* Start with no data receiving (ENDP3 not enabled) */
}
else
{
switch (event_type)
{
case USB_EVENT_ADDRESS:
+ chopstx_mutex_lock (&usb_mtx);
bDeviceState = ADDRESSED;
+ chopstx_mutex_unlock (&usb_mtx);
return USB_SUCCESS;
case USB_EVENT_CONFIG:
current_conf = usb_lld_current_configuration ();
usb_lld_set_configuration (1);
for (i = 0; i < NUM_INTERFACES; i++)
neug_setup_endpoints_for_interface (i, 0);
+ chopstx_mutex_lock (&usb_mtx);
bDeviceState = CONFIGURED;
+ chopstx_mutex_unlock (&usb_mtx);
}
else if (current_conf != value)
{
usb_lld_set_configuration (0);
for (i = 0; i < NUM_INTERFACES; i++)
neug_setup_endpoints_for_interface (i, 1);
+ chopstx_mutex_lock (&usb_mtx);
bDeviceState = ADDRESSED;
+ chopstx_mutex_unlock (&usb_mtx);
}
/* Do nothing when current_conf == value */
return USB_SUCCESS;
-
- return USB_SUCCESS;
default:
break;
}
}
-int usb_cb_interface (uint8_t cmd, uint16_t interface, uint16_t alt)
+int usb_cb_interface (uint8_t cmd, struct req_args *arg)
{
- static uint8_t zero = 0;
+ const uint8_t zero = 0;
+ uint16_t interface = arg->index;
+ uint16_t alt = arg->value;
if (interface >= NUM_INTERFACES)
return USB_UNSUPPORT;
}
case USB_GET_INTERFACE:
- usb_lld_set_data_to_send (&zero, 1);
- return USB_SUCCESS;
+ return usb_lld_reply_request (&zero, 1, arg);
default:
case USB_QUERY_INTERFACE:
}
#define INTR_REQ_USB 20
-#define PRIO_USB 2
+#define PRIO_USB 3
static void *
usb_intr (void *arg)
chopstx_intr_t interrupt;
(void)arg;
- asm volatile ("cpsid i" : : : "memory");
- /* Disable because usb_lld_init assumes interrupt handler. */
- usb_lld_init (vcom_configuration_desc[7]);
+ usb_lld_init (VCOM_FEATURE_BUS_POWERED);
chopstx_claim_irq (&interrupt, INTR_REQ_USB);
- /* Enable */
- asm volatile ("cpsie i" : : : "memory");
+ usb_interrupt_handler (); /* For old SYS < 3.0 */
while (1)
{
- chopstx_intr_wait (&interrupt);
+ chopstx_poll (NULL, 1, &interrupt);
/* Process interrupt. */
usb_interrupt_handler ();
return NULL;
}
-
+#define ID_OFFSET (2+SERIALNO_STR_LEN*2)
static void fill_serial_no_by_unique_id (void)
{
extern const uint8_t * unique_device_id (void);
- uint8_t *p = &vcom_string3[12];
- const uint8_t *u = unique_device_id ();
+ uint8_t *p = &neug_string_serial[ID_OFFSET];
+ const uint8_t *u = unique_device_id () + 8;
int i;
for (i = 0; i < 4; i++)
{
- uint8_t b = u[i];
- uint8_t nibble;
+ uint8_t b = u[3-i];
+ uint8_t nibble;
nibble = (b >> 4);
nibble += (nibble >= 10 ? ('A' - 10) : '0');
p[i*4] = nibble;
+ p[i*4+1] = 0;
nibble = (b & 0x0f);
nibble += (nibble >= 10 ? ('A' - 10) : '0');
p[i*4+2] = nibble;
+ p[i*4+3] = 0;
}
}
-\f
-void
-EP1_IN_Callback (void)
-{
- chopstx_mutex_lock (&usb_mtx);
- chopstx_cond_signal (&cnd_usb);
- chopstx_mutex_unlock (&usb_mtx);
-}
+
void
-EP2_IN_Callback (void)
+usb_cb_tx_done (uint8_t ep_num, uint32_t len)
{
+ (void)len;
+
+ if (ep_num == ENDP1)
+ {
+ chopstx_mutex_lock (&usb_mtx);
+ chopstx_cond_signal (&usb_cnd);
+ chopstx_mutex_unlock (&usb_mtx);
+ }
+ else if (ep_num == ENDP2)
+ {
+ /* INTERRUPT Transfer done */
+ }
+#ifdef FRAUCHEKY_SUPPORT
+ else if (ep_num == ENDP6)
+ EP6_IN_Callback (len);
+#endif
}
void
-EP3_OUT_Callback (void)
+usb_cb_rx_ready (uint8_t ep_num)
{
- usb_lld_rx_enable (ENDP3);
+ if (ep_num == ENDP3)
+ usb_lld_rx_enable (ENDP3);
+#ifdef FRAUCHEKY_SUPPORT
+ else if (ep_num == ENDP6)
+ EP6_OUT_Callback ();
+#endif
}
\f
typedef uint32_t eventmask_t;
const size_t __stacksize_usb = (size_t)&__process3_stack_size__;
-#define PRIO_LED 1
-struct event_flag led_event;
+#define PRIO_LED 3
+static struct event_flag led_event;
#define LED_ONESHOT_SHORT ((eventmask_t)1)
#define LED_TWOSHOTS ((eventmask_t)2)
/*
* LED blinker: When notified, let LED emit for 100ms.
*/
-static void *led_blinker (void *arg)
+static void *
+led_blinker (void *arg)
{
(void)arg;
eventmask_t m;
m = event_flag_waitone (&led_event, ALL_EVENTS);
- if (fsij_device_state != FSIJ_DEVICE_RUNNING)
- break;
set_led (1);
if (m == LED_ONESHOT_SHORT)
set_led (0);
}
- return 0;
+ return NULL;
}
\f
#define RANDOM_BYTES_LENGTH 64
}
+static int
+check_usb_status (void *arg)
+{
+ (void)arg;
+
+ return (connected || bDeviceState != CONFIGURED
+ || fsij_device_state != FSIJ_DEVICE_RUNNING);
+}
+
/*
* Entry point.
*
{
uint32_t entry;
chopstx_t led_thread, usb_thd;
- chopstx_attr_t attr;
+ unsigned int count;
(void)argc;
(void)argv;
event_flag_init (&led_event);
- chopstx_attr_init (&attr);
- chopstx_attr_setschedparam (&attr, PRIO_LED);
- chopstx_attr_setstack (&attr, __stackaddr_led, __stacksize_led);
- chopstx_create (&led_thread, &attr, led_blinker, NULL);
-
chopstx_mutex_init (&usb_mtx);
- chopstx_cond_init (&cnd_usb);
+ chopstx_cond_init (&usb_cnd);
- chopstx_attr_setschedparam (&attr, PRIO_USB);
- chopstx_attr_setstack (&attr, __stackaddr_usb, __stacksize_usb);
- chopstx_create (&usb_thd, &attr, usb_intr, NULL);
+#ifdef FRAUCHEKY_SUPPORT
+ if (fraucheky_enabled ())
+ {
+ go_fraucheky:
+ bDeviceState = UNCONNECTED;
+ running_neug = 0;
+ usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
+ usb_intr, NULL);
+ while (bDeviceState != CONFIGURED)
+ chopstx_usec_wait (250*1000);
+ set_led (1);
+ fraucheky_main ();
+ chopstx_cancel (usb_thd);
+ chopstx_join (usb_thd, NULL);
+ usb_lld_shutdown ();
+ bDeviceState = UNCONNECTED;
+ }
+
+ running_neug = 1;
+#endif
+
+ led_thread = chopstx_create (PRIO_LED, __stackaddr_led, __stacksize_led,
+ led_blinker, NULL);
+
+ usb_thd = chopstx_create (PRIO_USB, __stackaddr_usb, __stacksize_usb,
+ usb_intr, NULL);
neug_init (random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
+ chopstx_mutex_lock (&usb_mtx);
+
+ not_configured:
+ count = 0;
+ /* Initial run-up */
+ while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
+ {
+ if (fsij_device_state != FSIJ_DEVICE_RUNNING)
+ break;
+
+ chopstx_mutex_unlock (&usb_mtx);
+ neug_wait_full ();
+ neug_flush ();
+
+ if ((count & 0x0007) == 0)
+ event_flag_signal (&led_event, LED_ONESHOT_SHORT);
+ chopstx_usec_wait (25*1000);
+ count++;
+ chopstx_mutex_lock (&usb_mtx);
+ }
+
+ /* Holding USB_MTX... */
while (1)
{
- unsigned int count = 0;
int last_was_fullsizepacket = 0;
if (fsij_device_state != FSIJ_DEVICE_RUNNING)
break;
- while (count < NEUG_PRE_LOOP || bDeviceState != CONFIGURED)
+ chopstx_mutex_unlock (&usb_mtx);
+ while (1)
{
- if (fsij_device_state != FSIJ_DEVICE_RUNNING)
- break;
+ chopstx_poll_cond_t poll_desc;
+ uint32_t usec = 5000*1000;
- neug_wait_full ();
- neug_flush ();
+ poll_desc.type = CHOPSTX_POLL_COND;
+ poll_desc.ready = 0;
+ poll_desc.cond = &usb_cnd;
+ poll_desc.mutex = &usb_mtx;
+ poll_desc.check = check_usb_status;
+ poll_desc.arg = NULL;
- if ((count & 0x0007) == 0)
- event_flag_signal (&led_event, LED_ONESHOT_SHORT);
- chopstx_usec_wait (25*1000);
- count++;
- }
-
- waiting_connection:
- while (connected == 0)
- {
- if (fsij_device_state != FSIJ_DEVICE_RUNNING)
+ if (chopstx_poll (&usec, 1, &poll_desc))
break;
+ /* Timeout */
neug_flush ();
+ neug_mode_select (line_coding.paritytype);
event_flag_signal (&led_event, LED_TWOSHOTS);
- chopstx_usec_wait (5000*1000);
}
- if (fsij_device_state != FSIJ_DEVICE_RUNNING)
- break;
+ chopstx_mutex_lock (&usb_mtx);
+ if (bDeviceState != CONFIGURED)
+ goto not_configured;
/* The connection opened. */
count = 0;
- /*
- * No parity is standard. It means to provide conditioned output.
- * When parity enabled, it means to provide raw output.
- */
- neug_mode_select (line_coding.paritytype); /* 0: None, 1: Odd, 2: Even */
while (1)
{
int i;
- if (fsij_device_state != FSIJ_DEVICE_RUNNING)
- break;
-
- if (bDeviceState != CONFIGURED)
- break;
+ chopstx_mutex_unlock (&usb_mtx);
+ /*
+ * No parity is standard. It means providing conditioned output.
+ * When parity enabled, it means to provide raw output
+ * (CRC32 filtered when odd, direct sample of ADC when even).
+ *
+ * line_coding.paritytype:
+ * 0: None, 1: Odd, 2: Even
+ */
+ neug_mode_select (line_coding.paritytype);
if ((count & 0x03ff) == 0)
event_flag_signal (&led_event, LED_ONESHOT_SHORT);
if (i == 0 && !last_was_fullsizepacket)
{ /* Only send ZLP when the last packet was fullsize. */
neug_wait_full ();
- continue;
- }
- if (i == 64/4)
- last_was_fullsizepacket = 1;
- else
- last_was_fullsizepacket = 0;
-
- chopstx_mutex_lock (&usb_mtx);
- if (connected == 0)
- {
- chopstx_mutex_unlock (&usb_mtx);
- goto waiting_connection;
+ chopstx_mutex_lock (&usb_mtx);
+ if (bDeviceState != CONFIGURED || !connected
+ || fsij_device_state != FSIJ_DEVICE_RUNNING)
+ break;
}
else
{
+ if (i == 64/4)
+ last_was_fullsizepacket = 1;
+ else
+ last_was_fullsizepacket = 0;
+
+ chopstx_mutex_lock (&usb_mtx);
+ if (bDeviceState != CONFIGURED || !connected
+ || fsij_device_state != FSIJ_DEVICE_RUNNING)
+ break;
+
+ /* Prepare sending random data. */
usb_lld_tx_enable (ENDP1, i * 4);
- chopstx_cond_wait (&cnd_usb, &usb_mtx);
+ chopstx_cond_wait (&usb_cnd, &usb_mtx);
+ count++;
}
- chopstx_mutex_unlock (&usb_mtx);
-
- count++;
}
}
- event_flag_signal (&led_event, LED_ONESHOT_SHORT);
+ chopstx_mutex_unlock (&usb_mtx);
+
+ chopstx_cancel (led_thread);
chopstx_join (led_thread, NULL);
/*
- * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED.
+ * We come here, because of FSIJ_DEVICE_NEUG_EXIT_REQUESTED
+ * or FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED.
*/
neug_fini ();
+ chopstx_mutex_lock (&usb_mtx);
+#ifdef FRAUCHEKY_SUPPORT
+ if (line_coding.bitrate == NEUG_SPECIAL_BITRATE)
+ {
+ while (fsij_device_state == FSIJ_DEVICE_NEUG_FRAUCHEKY_REQUESTED)
+ {
+ chopstx_mutex_unlock (&usb_mtx);
+ set_led (1);
+ chopstx_usec_wait (500*1000);
+ set_led (0);
+ chopstx_usec_wait (500*1000);
+ chopstx_mutex_lock (&usb_mtx);
+ }
+
+ usb_lld_prepare_shutdown ();
+ chopstx_mutex_unlock (&usb_mtx);
+ chopstx_cancel (usb_thd);
+ chopstx_join (usb_thd, NULL);
+ usb_lld_shutdown ();
+ goto go_fraucheky;
+ }
+#endif
+
fsij_device_state = FSIJ_DEVICE_EXITED;
while (fsij_device_state == FSIJ_DEVICE_EXITED)
- chopstx_usec_wait (500*1000);
+ {
+ chopstx_mutex_unlock (&usb_mtx);
+ chopstx_usec_wait (500*1000);
+ chopstx_mutex_lock (&usb_mtx);
+ }
+ chopstx_mutex_unlock (&usb_mtx);
flash_unlock (); /* Flash unlock should be done here */
set_led (1);
#ifdef DFU_SUPPORT
#define FLASH_SYS_START_ADDR 0x08000000
#define FLASH_SYS_END_ADDR (0x08000000+0x1000)
+#define CHIP_ID_REG ((uint32_t *)0xE0042000)
{
extern uint8_t _sys;
uint32_t addr;
handler *new_vector = (handler *)FLASH_SYS_START_ADDR;
- void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[10];
+ void (*func) (void (*)(void)) = (void (*)(void (*)(void)))new_vector[9];
+ uint32_t flash_page_size = 1024; /* 1KiB default */
+
+ if ((*CHIP_ID_ADDR)&0x07 == 0x04) /* High dencity device. */
+ flash_page_size += 0x0400; /* It's 2KiB. */
/* Kill DFU */
for (addr = FLASH_SYS_START_ADDR; addr < FLASH_SYS_END_ADDR;
- addr += FLASH_PAGE_SIZE)
+ addr += flash_page_size)
flash_erase_page (addr);
/* copy system service routines */