aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Kconfig10
-rw-r--r--src/generic/usb_cdc.c31
-rw-r--r--src/generic/usb_cdc.h1
-rw-r--r--src/lpc176x/Kconfig4
-rw-r--r--src/lpc176x/usbserial.c46
5 files changed, 82 insertions, 10 deletions
diff --git a/src/Kconfig b/src/Kconfig
index be6e7246..36cb7c12 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -50,6 +50,10 @@ config SERIAL_BAUD
Specify the baud rate of the serial port. This should be set
to 250000. Read the FAQ before changing this value.
+config HAVE_CHIPID
+ bool
+ default n
+
# Generic configuration options for USB
menu "USB ids"
depends on USBSERIAL
@@ -61,8 +65,12 @@ config USB_DEVICE_ID
hex "USB device ID"
default 0xabcd
config USB_SERIAL_NUMBER
- string "USB serial number"
+ string "USB serial number" if !USB_SERIAL_NUMBER_CHIPID
default "12345"
+config USB_SERIAL_NUMBER_CHIPID
+ depends on HAVE_CHIPID
+ bool "USB serial number from CHIPID"
+ default y
endmenu
diff --git a/src/generic/usb_cdc.c b/src/generic/usb_cdc.c
index c995db49..fa1c5cb1 100644
--- a/src/generic/usb_cdc.c
+++ b/src/generic/usb_cdc.c
@@ -358,21 +358,34 @@ usb_req_get_descriptor(struct usb_ctrlrequest *req)
{
if (req->bRequestType != USB_DIR_IN)
goto fail;
- uint_fast8_t i;
+ void *desc = NULL;
+ uint_fast8_t flags, size, i;
for (i=0; i<ARRAY_SIZE(cdc_descriptors); i++) {
const struct descriptor_s *d = &cdc_descriptors[i];
if (READP(d->wValue) == req->wValue
&& READP(d->wIndex) == req->wIndex) {
- uint_fast8_t size = READP(d->size);
- uint_fast8_t flags = NEED_PROGMEM ? UX_SEND_PROGMEM : UX_SEND;
- if (size > req->wLength)
- size = req->wLength;
- else if (size < req->wLength)
- flags |= UX_SEND_ZLP;
- usb_do_xfer((void*)READP(d->desc), size, flags);
- return;
+ flags = NEED_PROGMEM ? UX_SEND_PROGMEM : UX_SEND;
+ size = READP(d->size);
+ desc = (void*)READP(d->desc);
}
}
+ if (CONFIG_USB_SERIAL_NUMBER_CHIPID
+ && req->wValue == ((USB_DT_STRING<<8) | USB_STR_ID_SERIAL)
+ && req->wIndex == USB_LANGID_ENGLISH_US) {
+ struct usb_string_descriptor *usbserial_serialid;
+ usbserial_serialid = usbserial_get_serialid();
+ flags = UX_SEND;
+ size = usbserial_serialid->bLength;
+ desc = (void*)usbserial_serialid;
+ }
+ if (desc) {
+ if (size > req->wLength)
+ size = req->wLength;
+ else if (size < req->wLength)
+ flags |= UX_SEND_ZLP;
+ usb_do_xfer(desc, size, flags);
+ return;
+ }
fail:
usb_do_stall();
}
diff --git a/src/generic/usb_cdc.h b/src/generic/usb_cdc.h
index 1763a843..279c486c 100644
--- a/src/generic/usb_cdc.h
+++ b/src/generic/usb_cdc.h
@@ -22,6 +22,7 @@ void usb_stall_ep0(void);
void usb_set_address(uint_fast8_t addr);
void usb_set_configure(void);
void usb_request_bootloader(void);
+struct usb_string_descriptor *usbserial_get_serialid(void);
// usb_cdc.c
void usb_notify_bulk_in(void);
diff --git a/src/lpc176x/Kconfig b/src/lpc176x/Kconfig
index 2df9419f..052396e9 100644
--- a/src/lpc176x/Kconfig
+++ b/src/lpc176x/Kconfig
@@ -66,4 +66,8 @@ config SERIAL
bool
default y
+config HAVE_CHIPID
+ bool
+ default y
+
endif
diff --git a/src/lpc176x/usbserial.c b/src/lpc176x/usbserial.c
index 95ce6e74..54c28a31 100644
--- a/src/lpc176x/usbserial.c
+++ b/src/lpc176x/usbserial.c
@@ -13,6 +13,7 @@
#include "byteorder.h" // cpu_to_le32
#include "command.h" // DECL_CONSTANT_STR
#include "generic/usb_cdc.h" // usb_notify_ep0
+#include "generic/usbstd.h" // usb_string_descriptor
#include "internal.h" // gpio_peripheral
#include "sched.h" // DECL_INIT
#include "usb_cdc_ep.h" // USB_CDC_EP_BULK_IN
@@ -34,6 +35,12 @@
#define RD_EN (1<<0)
#define WR_EN (1<<1)
+// IAP interface
+#define IAP_LOCATION 0x1fff1ff1
+#define IAP_CMD_READ_UID 58
+#define IAP_UID_LEN 16
+typedef void (*IAP)(uint32_t *, uint32_t *);
+
static void
usb_irq_disable(void)
{
@@ -104,6 +111,16 @@ sie_select_and_clear(uint32_t idx)
/****************************************************************
* Interface
****************************************************************/
+#define USB_STR_SERIAL_CHIPID u"0123456789ABCDEF0123456789ABCDEF"
+
+#define SIZE_cdc_string_serial_chipid \
+ (sizeof(cdc_string_serial_chipid) + sizeof(USB_STR_SERIAL_CHIPID) - 2)
+
+static struct usb_string_descriptor cdc_string_serial_chipid = {
+ .bLength = SIZE_cdc_string_serial_chipid,
+ .bDescriptorType = USB_DT_STRING,
+ .data = USB_STR_SERIAL_CHIPID,
+};
static int_fast8_t
usb_write_packet(uint32_t ep, const void *data, uint_fast8_t len)
@@ -260,10 +277,36 @@ usb_request_bootloader(void)
NVIC_SystemReset();
}
+struct usb_string_descriptor *
+usbserial_get_serialid(void)
+{
+ return &cdc_string_serial_chipid;
+}
/****************************************************************
* Setup and interrupts
****************************************************************/
+static void
+usb_set_serial(void)
+{
+ uint32_t iap_cmd_uid[5] = {IAP_CMD_READ_UID, 0, 0, 0, 0};
+ uint32_t iap_resp[5];
+
+ IAP iap_entry = (IAP)IAP_LOCATION;
+ __disable_irq();
+ iap_entry(iap_cmd_uid, iap_resp);
+ __enable_irq();
+
+ uint8_t *chipid = (uint8_t *)&iap_resp[1];
+ uint8_t i, j, c;
+ for (i = 0; i < IAP_UID_LEN; i++) {
+ for (j = 0; j < 2; j++) {
+ c = (chipid[i] >> 4*j) & 0xF;
+ c = (c < 10) ? '0'+c : 'A'-10+c;
+ cdc_string_serial_chipid.data[2*i+((j)?0:1)] = c;
+ }
+ }
+}
void
USB_IRQHandler(void)
@@ -300,6 +343,9 @@ DECL_CONSTANT_STR("RESERVE_PINS_USB", "P0.30,P0.29,P2.9");
void
usbserial_init(void)
{
+ if (CONFIG_USB_SERIAL_NUMBER_CHIPID)
+ usb_set_serial();
+
usb_irq_disable();
// enable power
enable_pclock(PCLK_USB);