qmk-firmware/tmk_core/protocol/arm_atsam/usb/spfssf.c

269 lines
19 KiB
C
Raw Normal View History

Massdrop keyboard support (#3780) * Massdrop SAMD51 Massdrop SAMD51 keyboards initial project upload * Removing relocated files Removing files that were relocated and not deleted from previous location * LED queue fix and cleaning Cleaned some white space or comments. Fix for LED I2C command queue. Cleaned up interrupts. Added debug function for printing numbers to scope through m15 line. * Factory programmed serial usage Ability to use factory programmed serial in hub and keyboard usb descriptors * USB serial number and bugfix Added support for factory programmed serial and usage. Incorporated bootloader's conditional compiling to align project closer. Fixed issue when USB device attempted to send before enabled. General white space and comment cleanup. * Project cleanup Cleaned up project in terms of white space, commented code, and unecessary files. NKRO keyboard is now using correct setreport although KBD was fine to use. Fixed broken linkage to __xprintf for serial debug statements. * Fix for extra keys Fixed possible USB hang on extra keys report set missing * I2C cleanup I2C cleanup and file renames necessary for master branch merge * Boot tracing and clocks cleanup Added optional boot debug trace mode through debug LED codes. General clock code cleanup. * Relocate ARM/Atmel headers Moved ARM/Atmel header folder from drivers to lib and made necessary makefile changes. * Pull request changes Pull request changes * Keymap and compile flag fix Keymap fix for momentary layer. Potential compile flag fix for Travis CI failure. * va_list include fix Fix for va_list compile failure * Include file case fixes Fixes for include files with incorrect case * ctrl and alt67 keyboard readme Added ctrl and alt67 keyboard readme files
2018-08-29 19:07:52 +00:00
#include "samd51j18a.h"
#include "stdarg.h"
#include "spfssf.h"
#include "usb_util.h"
int vspf(char *_Dest, const char *_Format, va_list va)
{
//va_list va; //Variable argument list variable
char *d = _Dest; //Pointer to dest
//va_start(va,_Format); //Initialize the variable argument list
while (*_Format) //While not end of format string
{
if (*_Format == SPF_SPEC_START) //If current format string character is the specifier start character
{
_Format++; //Skip over the character
while (*_Format && *_Format <= 64) _Format++; //Forward past any options
if (*_Format == SPF_SPEC_START) *d++ = *_Format; //If the character is the specifier start character, output the character and advance dest
else if (*_Format == SPF_SPEC_LONG) //If the character is the long type
{
_Format++; //Skip over the character
if (*_Format == SPF_SPEC_DECIMAL) //If the character is the decimal type
{
int64_t buf = va_arg(va,int64_t); //Get the next value from the va list
//if (buf < 0) { *d++ = '-'; buf = -buf; } //If the given number is negative, add a negative sign to the dest and invert number
//spf_uint2str_32_3t(&d,buf,32); //Perform the conversion
d += UTIL_ltoa_radix(buf, d, 10);
}
else if (*_Format == SPF_SPEC_UNSIGNED) //If the character is the unsigned type
{
uint64_t num = va_arg(va,uint64_t); //Get the next value from the va list
//spf_uint2str_32_3t(&d,num,32); //Perform the conversion
d += UTIL_ltoa_radix(num, d, 10);
}
else if (*_Format == SPF_SPEC_UHINT || *_Format == SPF_SPEC_UHINT_UP) //If the character is the unsigned type
{
uint64_t buf = va_arg(va,uint64_t); //Get the next value from the va list
//spf_uint2hex_32(&d,(unsigned long) buf);
d += UTIL_ltoa_radix(buf, d, 16);
}
else //If the character was not a known type
{
*d++ = SPF_SPEC_START; //Output the start specifier
*d++ = SPF_SPEC_LONG; //Output the long type
*d++ = *_Format; //Output the unknown type
}
}
else if (*_Format == SPF_SPEC_DECIMAL) //If the character is the decimal type
{
int buf = va_arg(va,int); //Get the next value from the va list
//if (buf < 0) { *d++ = '-'; buf = -buf; } //If the given number is negative, add a negative sign to the dest and invert number
//spf_uint2str_32_3t(&d,buf,16); //Perform the conversion
d += UTIL_itoa(buf, d);
}
else if (*_Format == SPF_SPEC_INT) //If the character is the integer type
{
int buf = va_arg(va,int); //Get the next value from the va list
//if (buf < 0) { *d++ = '-'; buf = -buf; } //If the given number is negative, add a negative sign to the dest and inverted number
//spf_uint2str_32_3t(&d,buf,16); //Perform the conversion
d += UTIL_itoa(buf, d);
}
else if (*_Format == SPF_SPEC_UINT) //If the character is the unsigned integer type
{
int buf = va_arg(va,int); //Get the next value from the va list
//spf_uint2str_32_3t(&d,buf,16); //Perform the conversion
d += UTIL_utoa(buf, d);
}
else if (*_Format == SPF_SPEC_STRING) //If the character is the string type
{
char *buf = va_arg(va,char*); //Get the next value from the va list
while (*buf) *d++ = *buf++; //Perform the conversion (simply output characters and adcance pointers)
}
else if (*_Format == SPF_SPEC_UHINT || *_Format == SPF_SPEC_UHINT_UP) //If the character is the short type
{
int buf = va_arg(va,unsigned int); //Get the next value from the va list
//spf_uint2hex_32(&d,(unsigned long) buf); //Perform the conversion
d += UTIL_utoa(buf, d);
}
else //If the character type is unknown
{
*d++ = SPF_SPEC_START; //Output the start specifier
*d++ = *_Format; //Output the unknown type
}
}
else *d++ = *_Format; //If the character is unknown, output it to dest and advance dest
_Format++; //Advance the format buffer pointer to next character
}
//va_end(va); //End the variable argument list
*d = '\0'; //Cap off the destination string with a zero
return d - _Dest; //Return the length of the destintion buffer
}
int spf(char *_Dest, const char *_Format, ...)
{
va_list va; //Variable argument list variable
int result;
va_start(va,_Format); //Initialize the variable argument list
result = vspf(_Dest, _Format, va);
va_end(va);
return result;
}
//sscanf string to number (integer types)
int64_t ssf_ston(const char **_Src, uint32_t count, uint32_t *conv_count)
{
int64_t value = 0; //Return value accumulator
uint32_t counter=count; //Counter to keep track of numbers converted
const char* p; //Pointer to first non space character
while (*(*_Src) == SSF_SKIP_SPACE) (*_Src)++; //Forward through the whitespace to next non whitespace
p = (*_Src); //Set pointer to first non space character
if (*p == '+' || *p == '-') (*_Src)++; //Skip over sign if any
while (*(*_Src) >= ASCII_NUM_START &&
*(*_Src) <= ASCII_NUM_END &&
counter) //While the source character is a digit and counter is not zero
{
value *= 10; //Multiply result by 10 to make room for next 1's place number
value += *(*_Src)++ - ASCII_NUM_START; //Add source number to value
counter--; //Decrement counter
}
if (counter - count == 0) return 0; //If no number conversion were performed, return 0
if (*p == '-') value = -value; //If the number given was negative, make the result negative
if (conv_count) (*conv_count)++; //Increment the converted count
return value; //Return the value
}
uint64_t ssf_hton(const char **_Src, uint32_t count,uint32_t *conv_count)
{
int64_t value=0; //Return value accumulator
uint32_t counter=count; //Counter to keep track of numbers converted
//const char* p; //Pointer to first non space character
char c;
while (*(*_Src) == SSF_SKIP_SPACE) (*_Src)++; //Forward through the whitespace to next non whitespace
//p = (*_Src); //Set pointer to first non space character
while (counter)
{
c = *(*_Src)++;
if (c >= 'a' && c <= 'f') c -= ('a'-'A'); //toupper
if (c < '0' || (c > '9' && c < 'A') || c > 'F') break;
value *= 16; //Multiply result by 10 to make room for next 1's place number
c = c - '0';
if (c > 9) c -= 7;
value += c; //Add source number to value
counter--; //Decrement counter
}
if (counter - count == 0) return 0; //If no number conversion were performed, return 0
//if (*p == '-') value = -value; //If the number given was negative, make the result negative
if (conv_count) (*conv_count)++; //Increment the converted count
return value;
}
//sscanf
int ssf(const char *_Src, const char *_Format, ...)
{
va_list va; //Variable argument list variable
unsigned char looking_for=0; //Static char specified in format to be found in source
uint32_t conv_count=0; //Count of conversions made
va_start(va,_Format); //Initialize the variable argument list
while (*_Format) //While the format string has not been fully read
{
if (looking_for != 0) //If we are looking for a matching character in the source string
{
while (*_Src != looking_for && *_Src) _Src++; //While the character is not found in the source string and not the end of the source
// string, increment the pointer position
if (*_Src == looking_for) _Src++; //If the character was found, step over it
else break; //Else the end was reached and the scan is now invalid (Could not find static character)
looking_for = 0; //Clear the looking for character
}
if (*_Format == SSF_SPEC_START) //If the current format character is the specifier start character
{
_Format++; //Step over the specifier start character
if (*_Format == SSF_SPEC_DECIMAL) //If the decimal specifier type is found
{
int *value=va_arg(va,int*); //User given destination address
//*value = (int)ssf_ston(&_Src,5,&conv_count); //Run conversion
*value = (int)ssf_ston(&_Src,10,&conv_count); //Run conversion
}
else if (*_Format == SSF_SPEC_LONG) //If the long specifier type is found
{
_Format++; //Skip over the specifier type
if (*_Format == SSF_SPEC_DECIMAL) //If the decimal specifier type is found
{
int64_t *value=va_arg(va,int64_t*); //User given destination address
//*value = (int64_t)ssf_ston(&_Src,10,&conv_count); //Run conversion
*value = (int64_t)ssf_ston(&_Src,19,&conv_count); //Run conversion
}
else if (*_Format == SSF_SPEC_UHINT) //If the decimal specifier type is found
{
uint64_t *value=va_arg(va,uint64_t *); //User given destination address
//*value = (uint64_t int)ssf_hton(&_Src,12,&conv_count); //Run conversion
*value = (uint64_t)ssf_hton(&_Src,16,&conv_count); //Run conversion
}
}
else if (*_Format == SSF_SPEC_SHORTINT) //If the short int specifier type is found
{
_Format++; //Skip over the specifier type
if (*_Format == SSF_SPEC_SHORTINT) //If the short int specifier type is found
{
_Format++; //Skip over the specifier type
if (*_Format == SSF_SPEC_DECIMAL) //If the decimal specifier type is found
{
unsigned char *value=va_arg(va,unsigned char*); //User given destination address
//*value = (unsigned char)ssf_ston(&_Src,3,&conv_count); //Run conversion
*value = (unsigned char)ssf_ston(&_Src,5,&conv_count); //Run conversion
}
}
}
else if (*_Format == SSF_SPEC_STRING) //If the specifier type is string
{
char *value=va_arg(va,char*); //User given destination address, max chars read pointer
while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
while (*_Src != SSF_SKIP_SPACE && *_Src) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
*value = 0; //Cap off the string pointer with zero
conv_count++; //Increment the converted count
}
else if (*_Format == SSF_SPEC_VERSION) //If the specifier type is string
{
char *value=va_arg(va,char*); //User given destination address, max chars read pointer
while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
while (*_Src != SSF_DELIM_COMMA && *_Src) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
*value = 0; //Cap off the string pointer with zero
conv_count++; //Increment the converted count
}
else if (*_Format >= ASCII_NUM_START && *_Format <= ASCII_NUM_END)
{
uint32_t len = (uint32_t)ssf_ston(&_Format,3,NULL); //Convert the given length
if (*_Format == SSF_SPEC_STRING) //If the specifier type is string
{
char *value=va_arg(va,char*),*e; //User given destination address, max chars read pointer
while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
e = (char*)_Src+len; //Set a maximum length pointer location
while (*_Src != SSF_SKIP_SPACE && *_Src && _Src != e) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
*value = 0; //Cap off the string pointer with zero
conv_count++; //Increment the converted count
}
else if (*_Format == SSF_SPEC_VERSION) //If the specifier type is string
{
char *value=va_arg(va,char*),*e; //User given destination address, max chars read pointer
while (*_Src == SSF_SKIP_SPACE) _Src++; //Forward through the whitespace to next non whitespace
e = (char*)_Src+len; //Set a maximum length pointer location
while (*_Src != SSF_DELIM_COMMA && *_Src && _Src != e) *value++ = *_Src++; //While any character but space and not end of string and not end location, copy char to dest
*value = 0; //Cap off the string pointer with zero
conv_count++; //Increment the converted count
}
}
else if (*_Format == SSF_SPEC_START) looking_for = *_Format; //If another start specifier character is found, output a specifier character
else break; //Scan is now invalid (Uknown type specified)
}
else if (*_Format == SSF_SKIP_SPACE) { } //If a space is found, ignore it
else looking_for = *_Format; //If any other character is found, it is static and should be found in src as well
_Format++; //Skip over current format character
}
va_end(va); //End the variable argument list
return conv_count; //Return the number of conversions made
}