- Use commit number as the basis for bcdDevice field (maximum is 2^16) - Change iSerial from commit date to chip Unique ID - Update both Firmware and Bootloader to use the same scheme (bcdDevice and iSerial) - Cleanup of Bootloader code - Split out build info CMake commands to a new fileblockKey
###| CMAKE Kiibohd Controller Bootloader |### | ###| CMAKE Kiibohd Controller Bootloader |### | ||||
# | # | ||||
# Jacob Alexander 2011-2014 | |||||
# Jacob Alexander 2011-2016 | |||||
# Due to this file's usefulness: | # Due to this file's usefulness: | ||||
# | # | ||||
# Released into the Public Domain | # Released into the Public Domain | ||||
#| You _MUST_ set this to match the microcontroller you are trying to compile for | #| You _MUST_ set this to match the microcontroller you are trying to compile for | ||||
#| You _MUST_ clean the build directory if you change this value | #| You _MUST_ clean the build directory if you change this value | ||||
#| | #| | ||||
set( CHIP | |||||
set ( CHIP | |||||
"mk20dx128vlf5" # McHCK mk20dx128vlf5 | "mk20dx128vlf5" # McHCK mk20dx128vlf5 | ||||
# "mk20dx256vlh7" # Kiibohd-dfu mk20dx256vlh7 | # "mk20dx256vlh7" # Kiibohd-dfu mk20dx256vlh7 | ||||
CACHE STRING "Chip" | CACHE STRING "Chip" | ||||
#| *** EXPERIMENTAL *** | #| *** EXPERIMENTAL *** | ||||
#| Stick with gcc unless you know what you're doing | #| Stick with gcc unless you know what you're doing | ||||
#| Currently only arm is supported with clang | #| Currently only arm is supported with clang | ||||
set( COMPILER | |||||
set ( COMPILER | |||||
"gcc" # arm-none-eabi-gcc / avr-gcc - Default | "gcc" # arm-none-eabi-gcc / avr-gcc - Default | ||||
# "clang" # arm-none-eabi | # "clang" # arm-none-eabi | ||||
CACHE STRING "Compiler Type" | CACHE STRING "Compiler Type" | ||||
# Compiler Intialization | # Compiler Intialization | ||||
# | # | ||||
set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/../Lib/CMake ) | set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/../Lib/CMake ) | ||||
include( initialize ) | |||||
include ( initialize ) | |||||
## | ## | ||||
# Source Defines | # Source Defines | ||||
# | # | ||||
set( SRCS | |||||
set ( SRCS | |||||
main.c | main.c | ||||
dfu.c | dfu.c | ||||
dfu.desc.c | dfu.desc.c | ||||
) | ) | ||||
# Only compile in if necessary | # Only compile in if necessary | ||||
if( CHIP STREQUAL "mk20dx256vlh7" ) | |||||
if ( CHIP STREQUAL "mk20dx256vlh7" ) | |||||
set( SRCS ${SRCS} | set( SRCS ${SRCS} | ||||
debug.c | debug.c | ||||
) | ) | ||||
endif() | |||||
endif () | |||||
message( STATUS "Bootloader Source Files:" ) | |||||
message( "${SRCS}" ) | |||||
message ( STATUS "Bootloader Source Files:" ) | |||||
message ( "${SRCS}" ) | |||||
#| Add Lib sources to main list | #| Add Lib sources to main list | ||||
foreach( SRC_FILE ${COMPILER_SRCS} ) | |||||
set( SRCS ${SRCS} ${CMAKE_SOURCE_DIR}/../${SRC_FILE} ) | |||||
endforeach() | |||||
foreach ( SRC_FILE ${COMPILER_SRCS} ) | |||||
set ( SRCS ${SRCS} ${CMAKE_SOURCE_DIR}/../${SRC_FILE} ) | |||||
endforeach () | |||||
# | # | ||||
#| Project | #| Project | ||||
project( kiibohd_bootloader ) | |||||
project ( kiibohd_bootloader ) | |||||
#| Target Name (output name) | #| Target Name (output name) | ||||
set( TARGET kiibohd_bootloader ) | |||||
set ( TARGET kiibohd_bootloader ) | |||||
#| General Settings | #| General Settings | ||||
cmake_minimum_required( VERSION 2.8 ) | |||||
cmake_minimum_required ( VERSION 2.8 ) | |||||
### | ### | ||||
# Generate Header Files | |||||
# CMake Build Env | |||||
# | # | ||||
configure_file( _buildvars.h buildvars.h ) | |||||
include_directories( ${CMAKE_BINARY_DIR} ) | |||||
include ( buildinfo ) | |||||
### | ### | ||||
# CMake Module Checking | |||||
# Generate Header Files | |||||
# | # | ||||
find_package( Git REQUIRED ) | |||||
find_package( Ctags ) # Optional | |||||
configure_file ( _buildvars.h buildvars.h ) | |||||
include_directories ( ${CMAKE_BINARY_DIR} ) | |||||
### | ### | ||||
# ctag Generation | # ctag Generation | ||||
# | # | ||||
if( CTAGS_EXECUTABLE ) | |||||
find_package ( Ctags ) # Optional | |||||
if ( CTAGS_EXECUTABLE ) | |||||
# Generate the ctags | # Generate the ctags | ||||
execute_process( COMMAND ctags ${SRCS} | execute_process( COMMAND ctags ${SRCS} | ||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} | ||||
) | ) | ||||
endif() | |||||
endif () | |||||
# | # | ||||
#| Create the .ELF file | #| Create the .ELF file | ||||
set( TARGET_ELF ${TARGET}.elf ) | |||||
add_executable( ${TARGET_ELF} ${SRCS} ) | |||||
set ( TARGET_ELF ${TARGET}.elf ) | |||||
add_executable ( ${TARGET_ELF} ${SRCS} ) | |||||
#| .ELF Properties | #| .ELF Properties | ||||
set_target_properties( ${TARGET_ELF} PROPERTIES | |||||
set_target_properties ( ${TARGET_ELF} PROPERTIES | |||||
LINK_FLAGS ${LINKER_FLAGS} | LINK_FLAGS ${LINKER_FLAGS} | ||||
SUFFIX "" # XXX Force Windows to keep the .exe off | SUFFIX "" # XXX Force Windows to keep the .exe off | ||||
) | ) | ||||
#| Convert the .ELF into a .bin to load onto the McHCK | #| Convert the .ELF into a .bin to load onto the McHCK | ||||
set( TARGET_BIN ${TARGET}.bin ) | |||||
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD | |||||
set ( TARGET_BIN ${TARGET}.bin ) | |||||
add_custom_command ( TARGET ${TARGET_ELF} POST_BUILD | |||||
COMMAND ${CMAKE_OBJCOPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN} | COMMAND ${CMAKE_OBJCOPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN} | ||||
COMMENT "Creating binary file to load: ${TARGET_BIN}" | COMMENT "Creating binary file to load: ${TARGET_BIN}" | ||||
) | ) | ||||
#| Generate the Extended .LSS | #| Generate the Extended .LSS | ||||
set( TARGET_LSS ${TARGET}.lss ) | |||||
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD | |||||
set ( TARGET_LSS ${TARGET}.lss ) | |||||
add_custom_command ( TARGET ${TARGET_ELF} POST_BUILD | |||||
COMMAND ${CMAKE_OBJDUMP} ${LSS_FLAGS} ${TARGET_ELF} > ${TARGET_LSS} | COMMAND ${CMAKE_OBJDUMP} ${LSS_FLAGS} ${TARGET_ELF} > ${TARGET_LSS} | ||||
COMMENT "Creating Extended Listing: ${TARGET_LSS}" | COMMENT "Creating Extended Listing: ${TARGET_LSS}" | ||||
) | ) | ||||
#| Generate the Symbol Table .SYM | #| Generate the Symbol Table .SYM | ||||
set( TARGET_SYM ${TARGET}.sym ) | |||||
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD | |||||
set ( TARGET_SYM ${TARGET}.sym ) | |||||
add_custom_command ( TARGET ${TARGET_ELF} POST_BUILD | |||||
COMMAND ${CMAKE_NM} -n ${TARGET_ELF} > ${TARGET_SYM} | COMMAND ${CMAKE_NM} -n ${TARGET_ELF} > ${TARGET_SYM} | ||||
COMMENT "Creating Symbol Table: ${TARGET_SYM}" | COMMENT "Creating Symbol Table: ${TARGET_SYM}" | ||||
) | ) | ||||
#| Compiler Selection Record | #| Compiler Selection Record | ||||
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD | |||||
add_custom_command ( TARGET ${TARGET_ELF} POST_BUILD | |||||
COMMAND ${CMAKE_SOURCE_DIR}/../Lib/CMake/writer compiler ${COMPILER_FAMILY} | COMMAND ${CMAKE_SOURCE_DIR}/../Lib/CMake/writer compiler ${COMPILER_FAMILY} | ||||
) | ) | ||||
# | # | ||||
#| After Changes Size Information | #| After Changes Size Information | ||||
add_custom_target( SizeAfter ALL | |||||
add_custom_target ( SizeAfter ALL | |||||
COMMAND ${CMAKE_SOURCE_DIR}/../Lib/CMake/sizeCalculator ${CMAKE_SIZE} ram ${TARGET_ELF} ${SIZE_RAM} " SRAM" | COMMAND ${CMAKE_SOURCE_DIR}/../Lib/CMake/sizeCalculator ${CMAKE_SIZE} ram ${TARGET_ELF} ${SIZE_RAM} " SRAM" | ||||
COMMAND ${CMAKE_SOURCE_DIR}/../Lib/CMake/sizeCalculator ${CMAKE_SIZE} flash ${TARGET_ELF} ${SIZE_FLASH} "Flash" | COMMAND ${CMAKE_SOURCE_DIR}/../Lib/CMake/sizeCalculator ${CMAKE_SIZE} flash ${TARGET_ELF} ${SIZE_FLASH} "Flash" | ||||
DEPENDS ${TARGET_ELF} | DEPENDS ${TARGET_ELF} |
/* Copyright (C) 2013-2015 by Jacob Alexander | |||||
/* Copyright (C) 2013-2016 by Jacob Alexander | |||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
// ----- Defines ----- | // ----- Defines ----- | ||||
// You can change these to give your code its own name. | // You can change these to give your code its own name. | ||||
#define STR_MANUFACTURER u"Kiibohd" | |||||
#define STR_MANUFACTURER u"@MANUFACTURER@" | |||||
#define STR_PRODUCT u"Kiibohd DFU Bootloader" | #define STR_PRODUCT u"Kiibohd DFU Bootloader" | ||||
#define STR_SERIAL u"@CHIP@" | |||||
#define STR_SERIAL u"00000000000000000000000000000000 - @CHIP@" | |||||
#define STR_ALTNAME u"@BOOT_DFU_ALTNAME@" | #define STR_ALTNAME u"@BOOT_DFU_ALTNAME@" | ||||
// Windows, even though the driver is supplied by Microsoft, an | // Windows, even though the driver is supplied by Microsoft, an | ||||
// INF file is needed to load the driver. These numbers need to | // INF file is needed to load the driver. These numbers need to | ||||
// match the INF file. | // match the INF file. | ||||
#define VENDOR_ID @BOOT_VENDOR_ID@ | |||||
#define PRODUCT_ID @BOOT_PRODUCT_ID@ | |||||
#define VENDOR_ID @BOOT_VENDOR_ID@ | |||||
#define PRODUCT_ID @BOOT_PRODUCT_ID@ | |||||
#define BCD_VERSION @Git_Commit_Number@ | |||||
// ----- Macros ----- | |||||
#define LSB(n) ((n) & 255) | |||||
#define MSB(n) (((n) >> 8) & 255) | |||||
// ----- Structs ----- | // ----- Structs ----- | ||||
static const struct usb_config_1 usb_config_1 = { | static const struct usb_config_1 usb_config_1 = { | ||||
.bMaxPacketSize0 = EP0_BUFSIZE, | .bMaxPacketSize0 = EP0_BUFSIZE, | ||||
.idVendor = VENDOR_ID, | .idVendor = VENDOR_ID, | ||||
.idProduct = PRODUCT_ID, | .idProduct = PRODUCT_ID, | ||||
.bcdDevice = { .raw = 0 }, | |||||
.bcdDevice = { .maj = MSB( BCD_VERSION ), .min = LSB( BCD_VERSION ) }, | |||||
.iManufacturer = 1, | .iManufacturer = 1, | ||||
.iProduct = 2, | .iProduct = 2, | ||||
.iSerialNumber = 3, | .iSerialNumber = 3, | ||||
.bNumConfigurations = 1, | .bNumConfigurations = 1, | ||||
}; | }; | ||||
static const struct usb_desc_string_t * const dfu_device_str_desc[] = { | |||||
struct usb_desc_string_t * const dfu_device_str_desc[] = { | |||||
USB_DESC_STRING_LANG_ENUS, | USB_DESC_STRING_LANG_ENUS, | ||||
USB_DESC_STRING(STR_MANUFACTURER), | USB_DESC_STRING(STR_MANUFACTURER), | ||||
USB_DESC_STRING(STR_PRODUCT), | USB_DESC_STRING(STR_PRODUCT), |
// Originally Generated from MCHCK Toolkit | // Originally Generated from MCHCK Toolkit | ||||
/* Copyright (c) Jacob Alexander 2014-2015 <[email protected]> | |||||
/* Copyright (c) Jacob Alexander 2014-2016 <[email protected]> | |||||
* | * | ||||
* This program is free software: you can redistribute it and/or modify | * This program is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
// ----- Variables ----- | // ----- Variables ----- | ||||
const struct usbd_device dfu_device; | |||||
extern const struct usbd_device dfu_device; | |||||
extern struct usb_desc_string_t * const dfu_device_str_desc[]; | |||||
usbd_init_fun_t init_usb_bootloader; | usbd_init_fun_t init_usb_bootloader; | ||||
/* Copyright (c) 2011,2012 Simon Schubert <[email protected]>. | /* Copyright (c) 2011,2012 Simon Schubert <[email protected]>. | ||||
* Modifications by Jacob Alexander 2014 <[email protected]> | |||||
* Modifications by Jacob Alexander 2014-2016 <[email protected]> | |||||
* | * | ||||
* This program is free software: you can redistribute it and/or modify | * This program is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
#include "usb.h" | #include "usb.h" | ||||
#include "usb-internal.h" | #include "usb-internal.h" | ||||
#include "dfu.desc.h" | |||||
static int usb_tx_string_desc(int idx, int reqlen) | static int usb_tx_string_desc(int idx, int reqlen) | ||||
{ | { | ||||
const struct usb_desc_string_t * const *d; | |||||
struct usb_desc_string_t * const *d; | |||||
for (d = usb.identity->string_descs; idx != 0 && *d != NULL; ++d) | for (d = usb.identity->string_descs; idx != 0 && *d != NULL; ++d) | ||||
--idx; | --idx; | ||||
prev->next = ctx; | prev->next = ctx; | ||||
} | } | ||||
// XXX | |||||
// Int32 to Hex16 UTF16LE | |||||
// This function takes advantage of a few things to save on flash space | |||||
// 1) Does not set anything if zero | |||||
// 2) No padding | |||||
void int32ToHex16( uint32_t num, uint16_t* str ) | |||||
{ | |||||
for ( ; num; num /= 16 ) | |||||
{ | |||||
uint32_t cur = num % 16; | |||||
*--str = (uint16_t)( cur + (( cur < 10 ) ? '0' : 'A' - 10) ); | |||||
} | |||||
} | |||||
void usb_init(const struct usbd_device *identity) | void usb_init(const struct usbd_device *identity) | ||||
{ | { | ||||
// Set the device serial number to the reserved iSerial string memory | |||||
int32ToHex16( SIM_UIDH, &(dfu_device_str_desc[3]->bString[8]) ); | |||||
int32ToHex16( SIM_UIDMH, &(dfu_device_str_desc[3]->bString[16]) ); | |||||
int32ToHex16( SIM_UIDML, &(dfu_device_str_desc[3]->bString[24]) ); | |||||
int32ToHex16( SIM_UIDL, &(dfu_device_str_desc[3]->bString[32]) ); | |||||
usb.identity = identity; | usb.identity = identity; | ||||
usb_enable(); | usb_enable(); | ||||
} | } |
/* Copyright (c) 2011,2012 Simon Schubert <[email protected]>. | /* Copyright (c) 2011,2012 Simon Schubert <[email protected]>. | ||||
* Modifications by Jacob Alexander 2014-2015 <[email protected]> | |||||
* Modifications by Jacob Alexander 2014-2016 <[email protected]> | |||||
* | * | ||||
* This program is free software: you can redistribute it and/or modify | * This program is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
// ----- Macros ----- | // ----- Macros ----- | ||||
#define USB_DESC_STRING(s) \ | #define USB_DESC_STRING(s) \ | ||||
(const void *)&(const struct { \ | |||||
(void *)&(struct { \ | |||||
struct usb_desc_string_t dsc; \ | struct usb_desc_string_t dsc; \ | ||||
char16_t str[sizeof(s) / 2 - 1]; \ | char16_t str[sizeof(s) / 2 - 1]; \ | ||||
}) {{ \ | |||||
}) {{ \ | |||||
.bLength = sizeof(struct usb_desc_string_t) + \ | .bLength = sizeof(struct usb_desc_string_t) + \ | ||||
sizeof(s) - 2, \ | sizeof(s) - 2, \ | ||||
.bDescriptorType = USB_DESC_STRING, \ | .bDescriptorType = USB_DESC_STRING, \ | ||||
#define USB_DESC_STRING_LANG_ENUS USB_DESC_STRING(u"\x0409") | #define USB_DESC_STRING_LANG_ENUS USB_DESC_STRING(u"\x0409") | ||||
#define USB_DESC_STRING_SERIALNO ((const void *)1) | #define USB_DESC_STRING_SERIALNO ((const void *)1) | ||||
#define USB_FUNCTION_IFACE(iface, iface_off, tx_ep_off, rx_ep_off) \ | |||||
((iface_off) + (iface)) | |||||
#define USB_FUNCTION_TX_EP(ep, iface_off, tx_ep_off, rx_ep_off) \ | |||||
((tx_ep_off) + (ep)) | |||||
#define USB_FUNCTION_RX_EP(ep, iface_off, tx_ep_off, rx_ep_off) \ | |||||
((rx_ep_off) + (ep)) | |||||
#define USB__INCREMENT(i, _0) (i + 1) | |||||
#define USB__COUNT_IFACE_EP(i, e) \ | |||||
__DEFER(USB__COUNT_IFACE_EP_)(__EXPAND i, e) | |||||
#define USB__COUNT_IFACE_EP_(iface, tx_ep, rx_ep, func) \ | |||||
(iface + USB_FUNCTION_ ## func ## _IFACE_COUNT, \ | |||||
tx_ep + USB_FUNCTION_ ## func ## _TX_EP_COUNT, \ | |||||
rx_ep + USB_FUNCTION_ ## func ## _RX_EP_COUNT) | |||||
#define USB__GET_FUNCTION_IFACE_COUNT(iter, func) \ | |||||
USB_FUNCTION_ ## func ## _IFACE_COUNT + | |||||
#define USB__DEFINE_FUNCTION_DESC(iter, func) \ | |||||
USB_FUNCTION_DESC_ ## func ## _DECL __CAT(__usb_func_desc, __COUNTER__); | |||||
#define USB__INIT_FUNCTION_DESC(iter, func) \ | |||||
USB_FUNCTION_DESC_ ## func iter, | |||||
#define USB__DEFINE_CONFIG_DESC(confignum, name, ...) \ | |||||
&((const struct name { \ | |||||
struct usb_desc_config_t config; \ | |||||
__REPEAT_INNER(, __EAT, USB__DEFINE_FUNCTION_DESC, __VA_ARGS__) \ | |||||
}){ \ | |||||
.config = { \ | |||||
.bLength = sizeof(struct usb_desc_config_t), \ | |||||
.bDescriptorType = USB_DESC_CONFIG, \ | |||||
.wTotalLength = sizeof(struct name), \ | |||||
.bNumInterfaces = __REPEAT_INNER(, __EAT, USB__GET_FUNCTION_IFACE_COUNT, __VA_ARGS__) 0, \ | |||||
.bConfigurationValue = confignum, \ | |||||
.iConfiguration = 0, \ | |||||
.one = 1, \ | |||||
.bMaxPower = 50 \ | |||||
}, \ | |||||
__REPEAT_INNER((0, 0, 0), USB__COUNT_IFACE_EP, USB__INIT_FUNCTION_DESC, __VA_ARGS__) \ | |||||
}).config | |||||
#define USB__DEFINE_CONFIG(iter, args) \ | |||||
__DEFER(USB__DEFINE_CONFIG_)(iter, __EXPAND args) | |||||
#define USB__DEFINE_CONFIG_(confignum, initfun, ...) \ | |||||
&(const struct usbd_config){ \ | |||||
.init = initfun, \ | |||||
.desc = USB__DEFINE_CONFIG_DESC( \ | |||||
confignum, \ | |||||
__CAT(__usb_desc, __COUNTER__), \ | |||||
__VA_ARGS__) \ | |||||
}, | |||||
#define USB_INIT_DEVICE(vid, pid, manuf, product, ...) \ | |||||
{ \ | |||||
.dev_desc = &(const struct usb_desc_dev_t){ \ | |||||
.bLength = sizeof(struct usb_desc_dev_t), \ | |||||
.bDescriptorType = USB_DESC_DEV, \ | |||||
.bcdUSB = { .maj = 2 }, \ | |||||
.bDeviceClass = USB_DEV_CLASS_SEE_IFACE, \ | |||||
.bDeviceSubClass = USB_DEV_SUBCLASS_SEE_IFACE, \ | |||||
.bDeviceProtocol = USB_DEV_PROTO_SEE_IFACE, \ | |||||
.bMaxPacketSize0 = EP0_BUFSIZE, \ | |||||
.idVendor = vid, \ | |||||
.idProduct = pid, \ | |||||
.bcdDevice = { .raw = 0 }, \ | |||||
.iManufacturer = 1, \ | |||||
.iProduct = 2, \ | |||||
.iSerialNumber = 3, \ | |||||
.bNumConfigurations = __PP_NARG(__VA_ARGS__), \ | |||||
}, \ | |||||
.string_descs = (const struct usb_desc_string_t * const []){ \ | |||||
USB_DESC_STRING_LANG_ENUS, \ | |||||
USB_DESC_STRING(manuf), \ | |||||
USB_DESC_STRING(product), \ | |||||
USB_DESC_STRING_SERIALNO, \ | |||||
NULL \ | |||||
}, \ | |||||
.configs = { \ | |||||
__REPEAT(1, USB__INCREMENT, USB__DEFINE_CONFIG, __VA_ARGS__) \ | |||||
NULL \ | |||||
} \ | |||||
} | |||||
// ----- Structs & Enumerations ----- | // ----- Structs & Enumerations ----- | ||||
struct usb_bcd_t { | struct usb_bcd_t { | ||||
UNION_STRUCT_START(16); | UNION_STRUCT_START(16); | ||||
struct { | struct { | ||||
uint8_t sub : 4; | |||||
uint8_t min : 4; | |||||
uint16_t maj : 8; | |||||
uint8_t min : 8; | |||||
uint8_t maj : 8; | |||||
}; | }; | ||||
UNION_STRUCT_END; | UNION_STRUCT_END; | ||||
}; | }; | ||||
struct usb_desc_string_t { | struct usb_desc_string_t { | ||||
uint8_t bLength; | uint8_t bLength; | ||||
enum usb_desc_type bDescriptorType : 8; /* = USB_DESC_STRING */ | enum usb_desc_type bDescriptorType : 8; /* = USB_DESC_STRING */ | ||||
const char16_t bString[]; | |||||
char16_t bString[]; | |||||
}; | }; | ||||
CTASSERT_SIZE_BYTE(struct usb_desc_string_t, 2); | CTASSERT_SIZE_BYTE(struct usb_desc_string_t, 2); | ||||
*/ | */ | ||||
struct usbd_device { | struct usbd_device { | ||||
const struct usb_desc_dev_t *dev_desc; | const struct usb_desc_dev_t *dev_desc; | ||||
const struct usb_desc_string_t * const *string_descs; | |||||
struct usb_desc_string_t * const *string_descs; | |||||
const struct usbd_config *configs[]; | const struct usbd_config *configs[]; | ||||
}; | }; | ||||
/* Copyright (C) 2014-2015 by Jacob Alexander | |||||
/* Copyright (C) 2014-2016 by Jacob Alexander | |||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
print( " \033[1mModules:\033[0m " CLI_Modules NL ); | print( " \033[1mModules:\033[0m " CLI_Modules NL ); | ||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | #if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | ||||
print( " \033[1mUnique Id:\033[0m " ); | print( " \033[1mUnique Id:\033[0m " ); | ||||
printHex32_op( SIM_UIDH, 4 ); | |||||
printHex32_op( SIM_UIDMH, 4 ); | |||||
printHex32_op( SIM_UIDML, 4 ); | |||||
printHex32_op( SIM_UIDL, 4 ); | |||||
printHex32_op( SIM_UIDH, 8 ); | |||||
printHex32_op( SIM_UIDMH, 8 ); | |||||
printHex32_op( SIM_UIDML, 8 ); | |||||
printHex32_op( SIM_UIDL, 8 ); | |||||
#elif defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) | #elif defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) | ||||
#else | #else | ||||
#error "No unique id defined." | #error "No unique id defined." |
} | } | ||||
// Converts a number to UTF-16LE | |||||
// Useful for fields in the USB Descriptor | |||||
void hex32ToStr16( uint32_t in, uint16_t* out, uint8_t op ) | |||||
{ | |||||
// Convert number to ASCII | |||||
char tmpStr[11]; | |||||
hex32ToStr_op( in, tmpStr, op ); | |||||
// Convert number to UTF-16LE | |||||
// Just add an extra NULL after every character | |||||
for ( uint8_t byte = 0; byte < sizeof( tmpStr ); byte++ ) | |||||
{ | |||||
// Don't copy the character if NULL and the current is not NULL | |||||
// Just stop | |||||
if ( tmpStr[byte] == '\0' && out[byte] != 0x0000 ) | |||||
{ | |||||
break; | |||||
} | |||||
out[byte] = tmpStr[byte] | 0x0000; | |||||
} | |||||
} | |||||
void revsStr( char* in ) | void revsStr( char* in ) | ||||
{ | { | ||||
// Iterators | // Iterators |
/* Copyright (C) 2011-2015 by Jacob Alexander | |||||
/* Copyright (C) 2011-2016 by Jacob Alexander | |||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
int16_t eqStr ( char* str1, char* str2 ); // Returns -1 if identical, last character of str1 comparison (0 if str1 is like str2) | int16_t eqStr ( char* str1, char* str2 ); // Returns -1 if identical, last character of str1 comparison (0 if str1 is like str2) | ||||
int numToInt ( char* in ); // Returns the int representation of a string | int numToInt ( char* in ); // Returns the int representation of a string | ||||
void hex32ToStr16 ( uint32_t in, uint16_t* out, uint8_t op ); // Used for USB Descriptors | |||||
###| CMAKE Kiibohd Controller Source Configurator |### | |||||
# | |||||
# Written by Jacob Alexander in 2011-2016 for the Kiibohd Controller | |||||
# | |||||
# Released into the Public Domain | |||||
# | |||||
### | |||||
find_package ( Git REQUIRED ) | |||||
### | |||||
# Generate Build Defines | |||||
# | |||||
#| Manufacturer name | |||||
set ( MANUFACTURER "Kiibohd" ) | |||||
#| Modified | |||||
#| Takes a bit of work to extract the "M " using CMake, and not using it if there are no modifications | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} status -s -uno --porcelain | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Modified_INFO | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
string ( LENGTH "${Git_Modified_INFO}" Git_Modified_LENGTH ) | |||||
set ( Git_Modified_Status "Clean" ) | |||||
if ( ${Git_Modified_LENGTH} GREATER 2 ) | |||||
string ( SUBSTRING "${Git_Modified_INFO}" 1 2 Git_Modified_Flag_INFO ) | |||||
set ( Git_Modified_Status "Dirty" ) | |||||
endif () | |||||
#| List of modified files | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD -- | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Modified_Files | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
string ( REGEX REPLACE "\n" "\\\\r\\\\n\\\\t" Git_Modified_Files "${Git_Modified_Files}" ) | |||||
set ( Git_Modified_Files "\\r\\n\\t${Git_Modified_Files}" ) | |||||
#| Branch | |||||
execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Branch_INFO | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Date | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format=%ci | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Date_INFO | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Commit Author and Email | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format="%cn <%ce>" | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Commit_Author | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Commit Revision | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format=%H | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Commit_Revision | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Commit Number (on branch) | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} rev-list --count HEAD | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Commit_Number | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Origin URL | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Origin_URL | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Build Date | |||||
execute_process ( COMMAND "date" "+%Y-%m-%d %T %z" | |||||
OUTPUT_VARIABLE Build_Date | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Last Commit Date | |||||
set ( GitLastCommitDate "${Git_Modified_Status} ${Git_Branch_INFO} - ${Git_Date_INFO}" ) | |||||
###| CMAKE Kiibohd Controller Source Configurator |### | ###| CMAKE Kiibohd Controller Source Configurator |### | ||||
# | # | ||||
# Written by Jacob Alexander in 2011-2015 for the Kiibohd Controller | |||||
# Written by Jacob Alexander in 2011-2016 for the Kiibohd Controller | |||||
# | # | ||||
# Released into the Public Domain | # Released into the Public Domain | ||||
# | # | ||||
### | ### | ||||
# CMake Module Checking | |||||
# CMake Build Env Checking | |||||
# | # | ||||
find_package ( Git REQUIRED ) | |||||
find_package ( Ctags ) # Optional | |||||
include( buildinfo ) | |||||
### | |||||
# Generate USB Defines | |||||
# | |||||
#| Manufacturer name | |||||
set ( MANUFACTURER "Kiibohd" ) | |||||
#| Serial Number | |||||
#| Attempt to call Git to get the branch, last commit date, and whether code modified since last commit | |||||
#| Modified | |||||
#| Takes a bit of work to extract the "M " using CMake, and not using it if there are no modifications | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} status -s -uno --porcelain | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Modified_INFO | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
string ( LENGTH "${Git_Modified_INFO}" Git_Modified_LENGTH ) | |||||
set ( Git_Modified_Status "Clean" ) | |||||
if ( ${Git_Modified_LENGTH} GREATER 2 ) | |||||
string ( SUBSTRING "${Git_Modified_INFO}" 1 2 Git_Modified_Flag_INFO ) | |||||
set ( Git_Modified_Status "Dirty" ) | |||||
endif () | |||||
#| List of modified files | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD -- | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Modified_Files | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
string ( REGEX REPLACE "\n" "\\\\r\\\\n\\\\t" Git_Modified_Files "${Git_Modified_Files}" ) | |||||
set ( Git_Modified_Files "\\r\\n\\t${Git_Modified_Files}" ) | |||||
#| Branch | |||||
execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Branch_INFO | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Date | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format=%ci | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Date_INFO | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Commit Author and Email | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format="%cn <%ce>" | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Commit_Author | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Commit Revision | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format=%H | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Commit_Revision | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Origin URL | |||||
execute_process ( COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url | |||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | |||||
OUTPUT_VARIABLE Git_Origin_URL | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Build Date | |||||
execute_process ( COMMAND "date" "+%Y-%m-%d %T %z" | |||||
OUTPUT_VARIABLE Build_Date | |||||
ERROR_QUIET | |||||
OUTPUT_STRIP_TRAILING_WHITESPACE | |||||
) | |||||
#| Last Commit Date | |||||
set ( GitLastCommitDate "${Git_Modified_Status} ${Git_Branch_INFO} - ${Git_Date_INFO}" ) | |||||
#| Uses CMake variables to include as defines | #| Uses CMake variables to include as defines | ||||
#| Primarily for USB configuration | #| Primarily for USB configuration | ||||
# ctag Generation | # ctag Generation | ||||
# | # | ||||
find_package ( Ctags ) # Optional | |||||
if ( CTAGS_EXECUTABLE ) | if ( CTAGS_EXECUTABLE ) | ||||
# Populate list of directories for ctags to parse | # Populate list of directories for ctags to parse | ||||
# NOTE: Doesn't support dots in the folder names... | # NOTE: Doesn't support dots in the folder names... |
/* Copyright (C) 2013-2015 by Jacob Alexander | |||||
/* Copyright (C) 2013-2016 by Jacob Alexander | |||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
// You can change these to give your code its own name. | // You can change these to give your code its own name. | ||||
#define STR_MANUFACTURER L"@MANUFACTURER@" | #define STR_MANUFACTURER L"@MANUFACTURER@" | ||||
#define STR_PRODUCT L"Keyboard - @ScanModule@ @MacroModule@ @OutputModule@ @DebugModule@" | #define STR_PRODUCT L"Keyboard - @ScanModule@ @MacroModule@ @OutputModule@ @DebugModule@" | ||||
#define STR_SERIAL L"@GitLastCommitDate@" | |||||
#define STR_SERIAL L"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - @CHIP@" | |||||
// Strings used in the CLI module | // Strings used in the CLI module | ||||
// match the INF file. | // match the INF file. | ||||
#define VENDOR_ID @VENDOR_ID@ | #define VENDOR_ID @VENDOR_ID@ | ||||
#define PRODUCT_ID @PRODUCT_ID@ | #define PRODUCT_ID @PRODUCT_ID@ | ||||
#define BCD_VERSION @Git_Commit_Number@ | |||||
EP0_SIZE, // bMaxPacketSize0 | EP0_SIZE, // bMaxPacketSize0 | ||||
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor | LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor | ||||
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct | LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct | ||||
0x00, 0x01, // bcdDevice | |||||
LSB(BCD_VERSION), MSB(BCD_VERSION), // bcdDevice | |||||
1, // iManufacturer | 1, // iManufacturer | ||||
2, // iProduct | 2, // iProduct | ||||
3, // iSerialNumber | 3, // iSerialNumber | ||||
// referenced by index numbers. These descriptors are the | // referenced by index numbers. These descriptors are the | ||||
// actual string data | // actual string data | ||||
struct usb_string_descriptor_struct { | |||||
uint8_t bLength; | |||||
uint8_t bDescriptorType; | |||||
uint16_t wString[]; | |||||
}; | |||||
extern struct usb_string_descriptor_struct usb_string_manufacturer_name | extern struct usb_string_descriptor_struct usb_string_manufacturer_name | ||||
__attribute__ ((weak, alias("usb_string_manufacturer_name_default"))); | __attribute__ ((weak, alias("usb_string_manufacturer_name_default"))); | ||||
extern struct usb_string_descriptor_struct usb_string_product_name | extern struct usb_string_descriptor_struct usb_string_product_name |
// ----- Enumerations ----- | |||||
// ----- Structs ----- | |||||
typedef struct { | typedef struct { | ||||
uint16_t wValue; | uint16_t wValue; | ||||
} usb_descriptor_list_t; | } usb_descriptor_list_t; | ||||
struct usb_string_descriptor_struct { | |||||
uint8_t bLength; | |||||
uint8_t bDescriptorType; | |||||
uint16_t wString[]; | |||||
}; | |||||
// ----- Variables ----- | // ----- Variables ----- | ||||
extern uint8_t *usb_bMaxPower; | extern uint8_t *usb_bMaxPower; | ||||
// ----- Functions ----- | // ----- Functions ----- | ||||
void usb_set_config_descriptor_size(); | void usb_set_config_descriptor_size(); |
// Simplifies defines considerably | // Simplifies defines considerably | ||||
usb_set_config_descriptor_size(); | usb_set_config_descriptor_size(); | ||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
// Write the unique id to the USB Descriptor memory location | |||||
// It's split up into 4 32 bit registers | |||||
// 1) Read out register | |||||
// 2) Convert to UTF-16-LE | |||||
// 3) Write to USB Descriptor Memory (space is pre-allocated) | |||||
extern struct usb_string_descriptor_struct usb_string_serial_number_default; | |||||
hex32ToStr16( SIM_UIDH, &(usb_string_serial_number_default.wString[0]), 8 ); | |||||
hex32ToStr16( SIM_UIDMH, &(usb_string_serial_number_default.wString[8]), 8 ); | |||||
hex32ToStr16( SIM_UIDML, &(usb_string_serial_number_default.wString[16]), 8 ); | |||||
hex32ToStr16( SIM_UIDL, &(usb_string_serial_number_default.wString[24]), 8 ); | |||||
#endif | |||||
// Clear out endpoints table | // Clear out endpoints table | ||||
for ( int i = 0; i <= NUM_ENDPOINTS * 4; i++ ) | for ( int i = 0; i <= NUM_ENDPOINTS * 4; i++ ) | ||||
{ | { |