From 3761545fcf173ea975494dafe4516e0f4c669081 Mon Sep 17 00:00:00 2001 From: Eric Wild Date: Mon, 27 Jan 2020 14:20:44 +0100 Subject: [PATCH] usb serial number descriptor Change-Id: I4a23682cee0849c788e5f6c611df4ed1f1cac3da --- config/usbd_config.h | 6 ++-- usb_dfu_main.c | 54 ++++++++++++++++++++++++++++++++++ usb_start.c | 69 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 3 deletions(-) diff --git a/config/usbd_config.h b/config/usbd_config.h index f82934c..7ae1b05 100644 --- a/config/usbd_config.h +++ b/config/usbd_config.h @@ -163,7 +163,7 @@ // Enable string descriptor of iSerialNum // usb_dfud_iserialnum_en #ifndef CONF_USB_DFUD_ISERIALNUM_EN -#define CONF_USB_DFUD_ISERIALNUM_EN 0 +#define CONF_USB_DFUD_ISERIALNUM_EN 1 #endif #ifndef CONF_USB_DFUD_ISERIALNUM @@ -175,11 +175,11 @@ // Unicode string of iSerialNum // usb_dfud_iserialnum_str #ifndef CONF_USB_DFUD_ISERIALNUM_STR -#define CONF_USB_DFUD_ISERIALNUM_STR "123456789ABCDEF" +#define CONF_USB_DFUD_ISERIALNUM_STR "dummy" #endif #ifndef CONF_USB_DFUD_ISERIALNUM_STR_DESC -#define CONF_USB_DFUD_ISERIALNUM_STR_DESC +#define CONF_USB_DFUD_ISERIALNUM_STR_DESC 12, 0x03, 'd', 0x00, 'u', 0x00, 'm', 0x00, 'm', 0x00, 'y', 0x00, #endif // diff --git a/usb_dfu_main.c b/usb_dfu_main.c index 19fe437..9115bf7 100644 --- a/usb_dfu_main.c +++ b/usb_dfu_main.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "atmel_start.h" #include "atmel_start_pins.h" @@ -85,10 +86,63 @@ static void start_application(void) SCB->VTOR = ((uint32_t) application_start_address & SCB_VTOR_TBLOFF_Msk); // re-base the vector table base address asm("bx %0"::"r"(*(application_start_address + 1))); // jump to application Reset Handler in the application */ } +#if defined(SYSMOOCTSIM) +/* Section 9.6 of SAMD5x/E5x Family Data Sheet */ +static int get_chip_unique_serial(uint8_t *out, size_t len) +{ + uint32_t *out32 = (uint32_t *)out; + if (len < 16) + return -EINVAL; + + out32[0] = *(uint32_t *)0x008061fc; + out32[1] = *(uint32_t *)0x00806010; + out32[2] = *(uint32_t *)0x00806014; + out32[3] = *(uint32_t *)0x00806018; + + return 0; +} + +/* same as get_chip_unique_serial but in hex-string format */ +static int get_chip_unique_serial_str(char *out, size_t len) +{ + uint8_t buf[16]; + int rc; + + if (len < 16*2 + 1) + return -EINVAL; + + rc = get_chip_unique_serial(buf, sizeof(buf)); + if (rc < 0) + return rc; + for (int i = 0; i < sizeof(buf); i++) + sprintf(&out[i*2], "%02x", buf[i]); + return 0; +} + +static int str_to_usb_desc(char* in, uint8_t in_sz, uint8_t* out, uint8_t out_sz){ + if (2+in_sz*2 < out_sz) + return -1; + + memset(out, 0, out_sz); + out[0] = out_sz; + out[1] = 0x3; + for (int i= 2; i < out_sz; i+=2) + out[i] = in[(i >> 1) - 1]; + return 0; +} + +char sernr_buf[16*2+1]; +//unicode for descriptor +uint8_t sernr_buf_descr[1+1+16*2*2]; +#endif int main(void) { atmel_start_init(); // initialise system +#if defined(SYSMOOCTSIM) + get_chip_unique_serial_str(sernr_buf, sizeof(sernr_buf)); + str_to_usb_desc(sernr_buf, sizeof(sernr_buf), sernr_buf_descr, sizeof(sernr_buf_descr)); +#endif if (!check_bootloader()) { // check bootloader // blink the LED to tell the user we don't know where the application starts while (true) { diff --git a/usb_start.c b/usb_start.c index 93059ad..24cde4f 100644 --- a/usb_start.c +++ b/usb_start.c @@ -17,6 +17,7 @@ */ #include "atmel_start.h" #include "usb_start.h" +#include "config/usbd_config.h" #if CONF_USBD_HS_SP static uint8_t single_desc_bytes[] = { @@ -45,6 +46,71 @@ static const usb_dfu_func_desc_t* usb_dfu_func_desc = (usb_dfu_func_desc_t*)&usb /** Ctrl endpoint buffer */ static uint8_t ctrl_buffer[64]; + + +/* transmit given string descriptor */ +static bool send_str_desc(uint8_t ep, const struct usb_req *req, enum usb_ctrl_stage stage, + const uint8_t *desc) +{ + uint16_t len_req = LE16(req->wLength); + uint16_t len_desc = desc[0]; + uint16_t len_tx; + bool need_zlp = !(len_req & (CONF_USB_DFUD_BMAXPKSZ0 - 1)); + + if (len_req <= len_desc) { + need_zlp = false; + len_tx = len_req; + } else { + len_tx = len_desc; + } + + if (ERR_NONE != usbdc_xfer(ep, (uint8_t *)desc, len_tx, need_zlp)) { + return true; + } + + return false; +} + +extern uint8_t sernr_buf_descr[]; +/* call-back for every control EP request */ +static int32_t string_req_cb(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage) +{ + uint8_t index, type; + + if (stage != USB_SETUP_STAGE) + return ERR_NOT_FOUND; + + if ((req->bmRequestType & (USB_REQT_TYPE_MASK | USB_REQT_DIR_IN)) != + (USB_REQT_TYPE_STANDARD | USB_REQT_DIR_IN)) + return ERR_NOT_FOUND; + + /* abort if it's not a GET DESCRIPTOR request */ + if (req->bRequest != USB_REQ_GET_DESC) + return ERR_NOT_FOUND; + + /* abort if it's not about a string descriptor */ + type = req->wValue >> 8; + if (type != USB_DT_STRING) + return ERR_NOT_FOUND; +#if 0 + printf("ep=%02x, bmReqT=%04x, bReq=%02x, wValue=%04x, stage=%d\r\n", + ep, req->bmRequestType, req->bRequest, req->wValue, stage); +#endif + /* abort if it's not a standard GET request */ + index = req->wValue & 0x00FF; + switch (index) { + case CONF_USB_DFUD_ISERIALNUM: + return send_str_desc(ep, req, stage, sernr_buf_descr); + default: + return ERR_NOT_FOUND; + } +} + + +static struct usbdc_handler string_req_h = {NULL, (FUNC_PTR)string_req_cb}; + + + /** * \brief USB DFU Init */ @@ -52,6 +118,9 @@ void usb_dfu_init(void) { usbdc_init(ctrl_buffer); dfudf_init(); +#if defined(SYSMOOCTSIM) + usbdc_register_handler(USBDC_HDL_REQ, &string_req_h); +#endif usbdc_start(single_desc); usbdc_attach();