Coding standards

2.0.x
Scott Lahteine 6 years ago
parent 19af90face
commit 3a1b6fe8c1

@ -231,7 +231,7 @@ void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause
// Reset controller // Reset controller
NVIC_SystemReset(); NVIC_SystemReset();
while(1) { WDT_Restart(WDT); } for (;;) WDT_Restart(WDT);
} }
__attribute__((naked)) void NMI_Handler(void) { __attribute__((naked)) void NMI_Handler(void) {

@ -95,7 +95,7 @@ void u8g_SetPILevel_DUE_hw_spi(u8g_t *u8g, uint8_t pin_index, uint8_t level) {
} }
uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch(msg) { switch (msg) {
case U8G_COM_MSG_STOP: case U8G_COM_MSG_STOP:
break; break;

@ -206,7 +206,7 @@ void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause
// Reset controller // Reset controller
NVIC_SystemReset(); NVIC_SystemReset();
while(1) { watchdog_init(); } for (;;) watchdog_init();
} }
extern "C" { extern "C" {

@ -45,12 +45,11 @@
#define OUTPUT 1 #define OUTPUT 1
#define INPUT_PULLUP 2 #define INPUT_PULLUP 2
uint8_t LPC1768_PIN_PORT(const uint8_t pin); uint8_t LPC1768_PIN_PORT(const uint8_t pin);
uint8_t LPC1768_PIN_PIN(const uint8_t pin); uint8_t LPC1768_PIN_PIN(const uint8_t pin);
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
// I/O functions // I/O functions
@ -63,22 +62,21 @@ void pinMode_LCD(uint8_t pin, uint8_t mode) {
PINSEL_FUNC_0, PINSEL_FUNC_0,
PINSEL_PINMODE_TRISTATE, PINSEL_PINMODE_TRISTATE,
PINSEL_PINMODE_NORMAL }; PINSEL_PINMODE_NORMAL };
switch(mode) { switch (mode) {
case INPUT: case INPUT:
LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR &= ~LPC_PIN(LPC1768_PIN_PIN(pin)); LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR &= ~LPC_PIN(LPC1768_PIN_PIN(pin));
PINSEL_ConfigPin(&config); PINSEL_ConfigPin(&config);
break; break;
case OUTPUT: case OUTPUT:
LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR |= LPC_PIN(LPC1768_PIN_PIN(pin)); LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR |= LPC_PIN(LPC1768_PIN_PIN(pin));
PINSEL_ConfigPin(&config); PINSEL_ConfigPin(&config);
break; break;
case INPUT_PULLUP: case INPUT_PULLUP:
LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR &= ~LPC_PIN(LPC1768_PIN_PIN(pin)); LPC_GPIO(LPC1768_PIN_PORT(pin))->FIODIR &= ~LPC_PIN(LPC1768_PIN_PIN(pin));
config.Pinmode = PINSEL_PINMODE_PULLUP; config.Pinmode = PINSEL_PINMODE_PULLUP;
PINSEL_ConfigPin(&config); PINSEL_ConfigPin(&config);
break; break;
default: default: break;
break;
} }
} }
@ -105,7 +103,6 @@ uint8_t u8g_GetPinLevel(uint8_t pin) {
return (uint32_t)LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOPIN & LPC_PIN(LPC1768_PIN_PIN(pin)) ? 1 : 0; return (uint32_t)LPC_GPIO(LPC1768_PIN_PORT(pin))->FIOPIN & LPC_PIN(LPC1768_PIN_PIN(pin)) ? 1 : 0;
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -95,9 +95,8 @@ uint8_t u8g_com_ssd_I2C_start_sequence(u8g_t *u8g) {
if (u8g->pin_list[U8G_PI_SET_A0] == 0) return 1; if (u8g->pin_list[U8G_PI_SET_A0] == 0) return 1;
/* setup bus, might be a repeated start */ /* setup bus, might be a repeated start */
if (u8g_i2c_start(I2C_SLA) == 0) if (u8g_i2c_start(I2C_SLA) == 0) return 0;
return 0; if (u8g->pin_list[U8G_PI_A0_STATE] == 0) {
if (u8g->pin_list[U8G_PI_A0_STATE] == 0 ) {
if (u8g_i2c_send_byte(I2C_CMD_MODE) == 0) return 0; if (u8g_i2c_send_byte(I2C_CMD_MODE) == 0) return 0;
} }
else if (u8g_i2c_send_byte(I2C_DATA_MODE) == 0) else if (u8g_i2c_send_byte(I2C_DATA_MODE) == 0)
@ -108,7 +107,7 @@ uint8_t u8g_com_ssd_I2C_start_sequence(u8g_t *u8g) {
} }
uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { uint8_t u8g_com_HAL_LPC1768_ssd_hw_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch(msg) { switch (msg) {
case U8G_COM_MSG_INIT: case U8G_COM_MSG_INIT:
//u8g_com_arduino_digital_write(u8g, U8G_PI_SCL, HIGH); //u8g_com_arduino_digital_write(u8g, U8G_PI_SCL, HIGH);
//u8g_com_arduino_digital_write(u8g, U8G_PI_SDA, HIGH); //u8g_com_arduino_digital_write(u8g, U8G_PI_SDA, HIGH);

@ -91,7 +91,7 @@ static void u8g_com_LPC1768_st7920_write_byte_hw_spi(uint8_t rs, uint8_t val) {
} }
uint8_t u8g_com_HAL_LPC1768_ST7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { uint8_t u8g_com_HAL_LPC1768_ST7920_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch(msg) { switch (msg) {
case U8G_COM_MSG_INIT: case U8G_COM_MSG_INIT:
u8g_SetPILevel(u8g, U8G_PI_CS, 0); u8g_SetPILevel(u8g, U8G_PI_CS, 0);
u8g_SetPIOutput(u8g, U8G_PI_CS); u8g_SetPIOutput(u8g, U8G_PI_CS);

@ -89,10 +89,8 @@ static void u8g_com_LPC1768_st7920_write_byte_sw_spi(uint8_t rs, uint8_t val) {
swSpiTransfer(val << 4, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL); swSpiTransfer(val << 4, SPI_speed, SCK_pin_ST7920_HAL, -1, MOSI_pin_ST7920_HAL_HAL);
} }
uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) uint8_t u8g_com_HAL_LPC1768_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
{ switch (msg) {
switch(msg)
{
case U8G_COM_MSG_INIT: case U8G_COM_MSG_INIT:
SCK_pin_ST7920_HAL = u8g->pin_list[U8G_PI_SCK]; SCK_pin_ST7920_HAL = u8g->pin_list[U8G_PI_SCK];
MOSI_pin_ST7920_HAL_HAL = u8g->pin_list[U8G_PI_MOSI]; MOSI_pin_ST7920_HAL_HAL = u8g->pin_list[U8G_PI_MOSI];

@ -72,7 +72,7 @@ static void u8g_sw_spi_HAL_LPC1768_shift_out(uint8_t dataPin, uint8_t clockPin,
} }
uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) { uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
switch(msg) { switch (msg) {
case U8G_COM_MSG_INIT: case U8G_COM_MSG_INIT:
u8g_SetPIOutput(u8g, U8G_PI_SCK); u8g_SetPIOutput(u8g, U8G_PI_SCK);
u8g_SetPIOutput(u8g, U8G_PI_MOSI); u8g_SetPIOutput(u8g, U8G_PI_MOSI);

@ -58,7 +58,7 @@ uint8_t u8g_com_stm32duino_fsmc_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, voi
static uint8_t isCommand; static uint8_t isCommand;
switch(msg) { switch (msg) {
case U8G_COM_MSG_STOP: case U8G_COM_MSG_STOP:
break; break;
case U8G_COM_MSG_INIT: case U8G_COM_MSG_INIT:
@ -154,7 +154,7 @@ void LCD_IO_Init(uint8_t cs, uint8_t rs) {
if (fsmcInit) return; if (fsmcInit) return;
fsmcInit = 1; fsmcInit = 1;
switch(cs) { switch (cs) {
case FSMC_CS_NE1: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION1; break; case FSMC_CS_NE1: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION1; break;
case FSMC_CS_NE2: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION2; break; case FSMC_CS_NE2: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION2; break;
case FSMC_CS_NE3: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION3; break; case FSMC_CS_NE3: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION3; break;
@ -164,7 +164,7 @@ void LCD_IO_Init(uint8_t cs, uint8_t rs) {
#define _ORADDR(N) controllerAddress |= (_BV32(N) - 2) #define _ORADDR(N) controllerAddress |= (_BV32(N) - 2)
switch(rs) { switch (rs) {
case FSMC_RS_A0: _ORADDR( 1); break; case FSMC_RS_A0: _ORADDR( 1); break;
case FSMC_RS_A1: _ORADDR( 2); break; case FSMC_RS_A1: _ORADDR( 2); break;
case FSMC_RS_A2: _ORADDR( 3); break; case FSMC_RS_A2: _ORADDR( 3); break;

@ -71,7 +71,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
} }
void HAL_timer_enable_interrupt(const uint8_t timer_num) { void HAL_timer_enable_interrupt(const uint8_t timer_num) {
switch(timer_num) { switch (timer_num) {
case 0: NVIC_ENABLE_IRQ(IRQ_FTM0); break; case 0: NVIC_ENABLE_IRQ(IRQ_FTM0); break;
case 1: NVIC_ENABLE_IRQ(IRQ_FTM1); break; case 1: NVIC_ENABLE_IRQ(IRQ_FTM1); break;
} }
@ -98,7 +98,7 @@ bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
} }
void HAL_timer_isr_prologue(const uint8_t timer_num) { void HAL_timer_isr_prologue(const uint8_t timer_num) {
switch(timer_num) { switch (timer_num) {
case 0: case 0:
FTM0_CNT = 0x0000; FTM0_CNT = 0x0000;
FTM0_SC &= ~FTM_SC_TOF; // Clear FTM Overflow flag FTM0_SC &= ~FTM_SC_TOF; // Clear FTM Overflow flag

@ -72,7 +72,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
} }
void HAL_timer_enable_interrupt(const uint8_t timer_num) { void HAL_timer_enable_interrupt(const uint8_t timer_num) {
switch(timer_num) { switch (timer_num) {
case 0: NVIC_ENABLE_IRQ(IRQ_FTM0); break; case 0: NVIC_ENABLE_IRQ(IRQ_FTM0); break;
case 1: NVIC_ENABLE_IRQ(IRQ_FTM1); break; case 1: NVIC_ENABLE_IRQ(IRQ_FTM1); break;
} }
@ -99,7 +99,7 @@ bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
} }
void HAL_timer_isr_prologue(const uint8_t timer_num) { void HAL_timer_isr_prologue(const uint8_t timer_num) {
switch(timer_num) { switch (timer_num) {
case 0: case 0:
FTM0_CNT = 0x0000; FTM0_CNT = 0x0000;
FTM0_SC &= ~FTM_SC_TOF; // Clear FTM Overflow flag FTM0_SC &= ~FTM_SC_TOF; // Clear FTM Overflow flag

@ -76,7 +76,7 @@ void HAL_analog_pin_state(char buffer[], int8_t pin) {
*/ */
bool HAL_pwm_status(int8_t pin) { bool HAL_pwm_status(int8_t pin) {
char buffer[20]; // for the sprintf statements char buffer[20]; // for the sprintf statements
switch(pin) { switch (pin) {
FTM_CASE(0,0); FTM_CASE(0,0);
FTM_CASE(0,1); FTM_CASE(0,1);
FTM_CASE(0,2); FTM_CASE(0,2);

@ -103,7 +103,7 @@ typedef struct {
* Macros * Macros
**************************************************************************/ **************************************************************************/
#define M_IsOriginValid(v) (((v) & 0x7F) ? true : false) #define M_IsOriginValid(v) !!((v) & 0x7F)
#define M_Origin2Str(v) ((v) ? "VALID" : "INVALID") #define M_Origin2Str(v) ((v) ? "VALID" : "INVALID")
#ifdef UNW_DEBUG #ifdef UNW_DEBUG

@ -32,23 +32,17 @@
* \retval false This is not a data-processing instruction, * \retval false This is not a data-processing instruction,
*/ */
static bool isDataProc(uint32_t instr) { static bool isDataProc(uint32_t instr) {
uint8_t opcode = (instr & 0x01E00000) >> 21; uint8_t opcode = (instr & 0x01E00000) >> 21;
bool S = (instr & 0x00100000) ? true : false; if ((instr & 0xFC000000) != 0xE0000000) return false;
if ((instr & 0xFC000000) != 0xE0000000) { /* TST, TEQ, CMP and CMN all require S to be set */
return false; bool S = !!(instr & 0x00100000);
} if (!S && opcode >= 8 && opcode <= 11) return false;
else if (!S && opcode >= 8 && opcode <= 11) {
/* TST, TEQ, CMP and CMN all require S to be set */ return true;
return false;
}
else
return true;
} }
UnwResult UnwStartArm(UnwState * const state) { UnwResult UnwStartArm(UnwState * const state) {
bool found = false; bool found = false;
uint16_t t = UNW_MAX_INSTR_COUNT; uint16_t t = UNW_MAX_INSTR_COUNT;
@ -56,9 +50,8 @@ UnwResult UnwStartArm(UnwState * const state) {
uint32_t instr; uint32_t instr;
/* Attempt to read the instruction */ /* Attempt to read the instruction */
if (!state->cb->readW(state->regData[15].v, &instr)) { if (!state->cb->readW(state->regData[15].v, &instr))
return UNWIND_IREAD_W_FAIL; return UNWIND_IREAD_W_FAIL;
}
UnwPrintd4("A %x %x %08x:", state->regData[13].v, state->regData[15].v, instr); UnwPrintd4("A %x %x %08x:", state->regData[13].v, state->regData[15].v, instr);
@ -103,31 +96,20 @@ UnwResult UnwStartArm(UnwState * const state) {
} }
/* Determine the return mode */ /* Determine the return mode */
if (state->regData[rn].v & 0x1) { if (state->regData[rn].v & 0x1) /* Branching to THUMB */
/* Branching to THUMB */
return UnwStartThumb(state); return UnwStartThumb(state);
}
else {
/* Branch to ARM */
/* Account for the auto-increment which isn't needed */ /* Branch to ARM */
state->regData[15].v -= 4; /* Account for the auto-increment which isn't needed */
} state->regData[15].v -= 4;
} }
/* Branch */ /* Branch */
else if ((instr & 0xFF000000) == 0xEA000000) { else if ((instr & 0xFF000000) == 0xEA000000) {
int32_t offset = (instr & 0x00FFFFFF); int32_t offset = (instr & 0x00FFFFFF) << 2;
/* Shift value */
offset = offset << 2;
/* Sign extend if needed */ /* Sign extend if needed */
if (offset & 0x02000000) { if (offset & 0x02000000) offset |= 0xFC000000;
offset |= 0xFC000000;
}
UnwPrintd2("B %d\n", offset); UnwPrintd2("B %d\n", offset);
@ -142,11 +124,12 @@ UnwResult UnwStartArm(UnwState * const state) {
/* MRS */ /* MRS */
else if ((instr & 0xFFBF0FFF) == 0xE10F0000) { else if ((instr & 0xFFBF0FFF) == 0xE10F0000) {
#ifdef UNW_DEBUG #ifdef UNW_DEBUG
bool R = (instr & 0x00400000) ? true : false; const bool R = !!(instr & 0x00400000);
#endif #else
constexpr bool R = false;
#endif
uint8_t rd = (instr & 0x0000F000) >> 12; uint8_t rd = (instr & 0x0000F000) >> 12;
UnwPrintd4("MRS r%d,%s\t; r%d invalidated", rd, R ? "SPSR" : "CPSR", rd); UnwPrintd4("MRS r%d,%s\t; r%d invalidated", rd, R ? "SPSR" : "CPSR", rd);
/* Status registers untracked */ /* Status registers untracked */
@ -154,11 +137,10 @@ UnwResult UnwStartArm(UnwState * const state) {
} }
/* MSR */ /* MSR */
else if ((instr & 0xFFB0F000) == 0xE120F000) { else if ((instr & 0xFFB0F000) == 0xE120F000) {
#ifdef UNW_DEBUG #ifdef UNW_DEBUG
bool R = (instr & 0x00400000) ? true : false; UnwPrintd2("MSR %s_?, ???", (instr & 0x00400000) ? "SPSR" : "CPSR");
#endif
UnwPrintd2("MSR %s_?, ???", R ? "SPSR" : "CPSR");
#endif
/* Status registers untracked. /* Status registers untracked.
* Potentially this could change processor mode and switch * Potentially this could change processor mode and switch
* banked registers r8-r14. Most likely is that r13 (sp) will * banked registers r8-r14. Most likely is that r13 (sp) will
@ -170,18 +152,18 @@ UnwResult UnwStartArm(UnwState * const state) {
} }
/* Data processing */ /* Data processing */
else if (isDataProc(instr)) { else if (isDataProc(instr)) {
bool I = (instr & 0x02000000) ? true : false; bool I = !!(instr & 0x02000000);
uint8_t opcode = (instr & 0x01E00000) >> 21; uint8_t opcode = (instr & 0x01E00000) >> 21;
#ifdef UNW_DEBUG #ifdef UNW_DEBUG
bool S = (instr & 0x00100000) ? true : false; bool S = !!(instr & 0x00100000);
#endif #endif
uint8_t rn = (instr & 0x000F0000) >> 16; uint8_t rn = (instr & 0x000F0000) >> 16;
uint8_t rd = (instr & 0x0000F000) >> 12; uint8_t rd = (instr & 0x0000F000) >> 12;
uint16_t operand2 = (instr & 0x00000FFF); uint16_t operand2 = (instr & 0x00000FFF);
uint32_t op2val; uint32_t op2val;
int op2origin; int op2origin;
switch(opcode) { switch (opcode) {
case 0: UnwPrintd4("AND%s r%d,r%d,", S ? "S" : "", rd, rn); break; case 0: UnwPrintd4("AND%s r%d,r%d,", S ? "S" : "", rd, rn); break;
case 1: UnwPrintd4("EOR%s r%d,r%d,", S ? "S" : "", rd, rn); break; case 1: UnwPrintd4("EOR%s r%d,r%d,", S ? "S" : "", rd, rn); break;
case 2: UnwPrintd4("SUB%s r%d,r%d,", S ? "S" : "", rd, rn); break; case 2: UnwPrintd4("SUB%s r%d,r%d,", S ? "S" : "", rd, rn); break;
@ -217,26 +199,23 @@ UnwResult UnwStartArm(UnwState * const state) {
/* Register and shift */ /* Register and shift */
uint8_t rm = (operand2 & 0x000F); uint8_t rm = (operand2 & 0x000F);
uint8_t regShift = (operand2 & 0x0010) ? true : false; uint8_t regShift = !!(operand2 & 0x0010);
uint8_t shiftType = (operand2 & 0x0060) >> 5; uint8_t shiftType = (operand2 & 0x0060) >> 5;
uint32_t shiftDist; uint32_t shiftDist;
#ifdef UNW_DEBUG #ifdef UNW_DEBUG
const char * const shiftMnu[4] = { "LSL", "LSR", "ASR", "ROR" }; const char * const shiftMnu[4] = { "LSL", "LSR", "ASR", "ROR" };
#endif #endif
UnwPrintd2("r%d ", rm); UnwPrintd2("r%d ", rm);
/* Get the shift distance */ /* Get the shift distance */
if (regShift) { if (regShift) {
uint8_t rs = (operand2 & 0x0F00) >> 8; uint8_t rs = (operand2 & 0x0F00) >> 8;
if (operand2 & 0x00800) { if (operand2 & 0x00800) {
UnwPrintd1("\nError: Bit should be zero\n"); UnwPrintd1("\nError: Bit should be zero\n");
return UNWIND_ILLEGAL_INSTR; return UNWIND_ILLEGAL_INSTR;
} }
else if (rs == 15) { else if (rs == 15) {
UnwPrintd1("\nError: Cannot use R15 with register shift\n"); UnwPrintd1("\nError: Cannot use R15 with register shift\n");
return UNWIND_ILLEGAL_INSTR; return UNWIND_ILLEGAL_INSTR;
} }
@ -250,46 +229,33 @@ UnwResult UnwStartArm(UnwState * const state) {
else { else {
shiftDist = (operand2 & 0x0F80) >> 7; shiftDist = (operand2 & 0x0F80) >> 7;
op2origin = REG_VAL_FROM_CONST; op2origin = REG_VAL_FROM_CONST;
if (shiftDist) UnwPrintd3("%s #%d", shiftMnu[shiftType], shiftDist);
if (shiftDist) {
UnwPrintd3("%s #%d", shiftMnu[shiftType], shiftDist);
}
UnwPrintd3("\t; r%d %s", rm, M_Origin2Str(state->regData[rm].o)); UnwPrintd3("\t; r%d %s", rm, M_Origin2Str(state->regData[rm].o));
} }
/* Apply the shift type to the source register */ /* Apply the shift type to the source register */
switch(shiftType) { switch (shiftType) {
case 0: /* logical left */ case 0: /* logical left */
op2val = state->regData[rm].v << shiftDist; op2val = state->regData[rm].v << shiftDist;
break; break;
case 1: /* logical right */ case 1: /* logical right */
if (!regShift && shiftDist == 0) { if (!regShift && shiftDist == 0) shiftDist = 32;
shiftDist = 32;
}
op2val = state->regData[rm].v >> shiftDist; op2val = state->regData[rm].v >> shiftDist;
break; break;
case 2: /* arithmetic right */ case 2: /* arithmetic right */
if (!regShift && shiftDist == 0) { if (!regShift && shiftDist == 0) shiftDist = 32;
shiftDist = 32;
}
if (state->regData[rm].v & 0x80000000) { if (state->regData[rm].v & 0x80000000) {
/* Register shifts maybe greater than 32 */ /* Register shifts maybe greater than 32 */
if (shiftDist >= 32) { if (shiftDist >= 32)
op2val = 0xFFFFFFFF; op2val = 0xFFFFFFFF;
} else
else { op2val = (state->regData[rm].v >> shiftDist) | (0xFFFFFFFF << (32 - shiftDist));
op2val = state->regData[rm].v >> shiftDist;
op2val |= 0xFFFFFFFF << (32 - shiftDist);
}
} }
else { else
op2val = state->regData[rm].v >> shiftDist; op2val = state->regData[rm].v >> shiftDist;
}
break; break;
case 3: /* rotate right */ case 3: /* rotate right */
@ -317,19 +283,14 @@ UnwResult UnwStartArm(UnwState * const state) {
} }
/* Decide the data origin */ /* Decide the data origin */
if (M_IsOriginValid(op2origin) && if (M_IsOriginValid(op2origin) && M_IsOriginValid(state->regData[rm].o))
M_IsOriginValid(state->regData[rm].o)) { op2origin = REG_VAL_ARITHMETIC | state->regData[rm].o;
else
op2origin = state->regData[rm].o;
op2origin |= REG_VAL_ARITHMETIC;
}
else {
op2origin = REG_VAL_INVALID; op2origin = REG_VAL_INVALID;
}
} }
/* Propagate register validity */ /* Propagate register validity */
switch(opcode) { switch (opcode) {
case 0: /* AND: Rd := Op1 AND Op2 */ case 0: /* AND: Rd := Op1 AND Op2 */
case 1: /* EOR: Rd := Op1 EOR Op2 */ case 1: /* EOR: Rd := Op1 EOR Op2 */
case 2: /* SUB: Rd:= Op1 - Op2 */ case 2: /* SUB: Rd:= Op1 - Op2 */
@ -374,14 +335,11 @@ UnwResult UnwStartArm(UnwState * const state) {
* to specify the shift amount the PC will be 12 bytes * to specify the shift amount the PC will be 12 bytes
* ahead. * ahead.
*/ */
if (!I && (operand2 & 0x0010)) state->regData[rn].v += ((!I && (operand2 & 0x0010)) ? 12 : 8);
state->regData[rn].v += 12;
else
state->regData[rn].v += 8;
} }
/* Compute values */ /* Compute values */
switch(opcode) { switch (opcode) {
case 0: /* AND: Rd := Op1 AND Op2 */ case 0: /* AND: Rd := Op1 AND Op2 */
state->regData[rd].v = state->regData[rn].v & op2val; state->regData[rd].v = state->regData[rn].v & op2val;
break; break;
@ -429,12 +387,8 @@ UnwResult UnwStartArm(UnwState * const state) {
} }
/* Remove the prefetch offset from the PC */ /* Remove the prefetch offset from the PC */
if (rd != 15 && rn == 15) { if (rd != 15 && rn == 15)
if (!I && (operand2 & 0x0010)) state->regData[rn].v -= ((!I && (operand2 & 0x0010)) ? 12 : 8);
state->regData[rn].v -= 12;
else
state->regData[rn].v -= 8;
}
} }
/* Block Data Transfer /* Block Data Transfer
@ -442,26 +396,25 @@ UnwResult UnwStartArm(UnwState * const state) {
*/ */
else if ((instr & 0xFE000000) == 0xE8000000) { else if ((instr & 0xFE000000) == 0xE8000000) {
bool P = (instr & 0x01000000) ? true : false; bool P = !!(instr & 0x01000000),
bool U = (instr & 0x00800000) ? true : false; U = !!(instr & 0x00800000),
bool S = (instr & 0x00400000) ? true : false; S = !!(instr & 0x00400000),
bool W = (instr & 0x00200000) ? true : false; W = !!(instr & 0x00200000),
bool L = (instr & 0x00100000) ? true : false; L = !!(instr & 0x00100000);
uint16_t baseReg = (instr & 0x000F0000) >> 16; uint16_t baseReg = (instr & 0x000F0000) >> 16;
uint16_t regList = (instr & 0x0000FFFF); uint16_t regList = (instr & 0x0000FFFF);
uint32_t addr = state->regData[baseReg].v; uint32_t addr = state->regData[baseReg].v;
bool addrValid = M_IsOriginValid(state->regData[baseReg].o); bool addrValid = M_IsOriginValid(state->regData[baseReg].o);
int8_t r; int8_t r;
#ifdef UNW_DEBUG #ifdef UNW_DEBUG
/* Display the instruction */ /* Display the instruction */
if (L) { if (L)
UnwPrintd6("LDM%c%c r%d%s, {reglist}%s\n", P ? 'E' : 'F', U ? 'D' : 'A', baseReg, W ? "!" : "", S ? "^" : ""); UnwPrintd6("LDM%c%c r%d%s, {reglist}%s\n", P ? 'E' : 'F', U ? 'D' : 'A', baseReg, W ? "!" : "", S ? "^" : "");
} else
else { UnwPrintd6("STM%c%c r%d%s, {reglist}%s\n", !P ? 'E' : 'F', !U ? 'D' : 'A', baseReg, W ? "!" : "", S ? "^" : "");
UnwPrintd6("STM%c%c r%d%s, {reglist}%s\n", !P ? 'E' : 'F', !U ? 'D' : 'A', baseReg, W ? "!" : "", S ? "^" : ""); #endif
}
#endif
/* S indicates that banked registers (untracked) are used, unless /* S indicates that banked registers (untracked) are used, unless
* this is a load including the PC when the S-bit indicates that * this is a load including the PC when the S-bit indicates that
* that CPSR is loaded from SPSR (also untracked, but ignored). * that CPSR is loaded from SPSR (also untracked, but ignored).
@ -489,44 +442,35 @@ UnwResult UnwStartArm(UnwState * const state) {
/* Check if the register is to be transferred */ /* Check if the register is to be transferred */
if (regList & (0x01 << r)) { if (regList & (0x01 << r)) {
if (P) if (P) addr += U ? 4 : -4;
addr += U ? 4 : -4;
if (L) { if (L) {
if (addrValid) { if (addrValid) {
if (!UnwMemReadRegister(state, addr, &state->regData[r])) { if (!UnwMemReadRegister(state, addr, &state->regData[r]))
return UNWIND_DREAD_W_FAIL; return UNWIND_DREAD_W_FAIL;
}
/* Update the origin if read via the stack pointer */ /* Update the origin if read via the stack pointer */
if (M_IsOriginValid(state->regData[r].o) && baseReg == 13) { if (M_IsOriginValid(state->regData[r].o) && baseReg == 13)
state->regData[r].o = REG_VAL_FROM_STACK; state->regData[r].o = REG_VAL_FROM_STACK;
}
UnwPrintd5(" R%d = 0x%08x\t; r%d %s\n",r,state->regData[r].v,r, M_Origin2Str(state->regData[r].o)); UnwPrintd5(" R%d = 0x%08x\t; r%d %s\n",r,state->regData[r].v,r, M_Origin2Str(state->regData[r].o));
} }
else { else {
/* Invalidate the register as the base reg was invalid */ /* Invalidate the register as the base reg was invalid */
state->regData[r].o = REG_VAL_INVALID; state->regData[r].o = REG_VAL_INVALID;
UnwPrintd2(" R%d = ???\n", r); UnwPrintd2(" R%d = ???\n", r);
} }
} }
else { else {
if (addrValid) { if (addrValid && !UnwMemWriteRegister(state, state->regData[13].v, &state->regData[r]))
if (!UnwMemWriteRegister(state, state->regData[13].v, &state->regData[r])) { return UNWIND_DWRITE_W_FAIL;
return UNWIND_DWRITE_W_FAIL;
}
}
UnwPrintd2(" R%d = 0x%08x\n", r); UnwPrintd2(" R%d = 0x%08x\n", r);
} }
if (!P) if (!P) addr += U ? 4 : -4;
addr += U ? 4 : -4;
} }
/* Check the next register */ /* Check the next register */
@ -535,8 +479,7 @@ UnwResult UnwStartArm(UnwState * const state) {
} while (r >= 0 && r <= 15); } while (r >= 0 && r <= 15);
/* Check the writeback bit */ /* Check the writeback bit */
if (W) if (W) state->regData[baseReg].v = addr;
state->regData[baseReg].v = addr;
/* Check if the PC was loaded */ /* Check if the PC was loaded */
if (L && (regList & (0x01 << 15))) { if (L && (regList & (0x01 << 15))) {
@ -547,9 +490,8 @@ UnwResult UnwStartArm(UnwState * const state) {
} }
else { else {
/* Store the return address */ /* Store the return address */
if (!UnwReportRetAddr(state, state->regData[15].v)) { if (!UnwReportRetAddr(state, state->regData[15].v))
return UNWIND_TRUNCATED; return UNWIND_TRUNCATED;
}
UnwPrintd2(" Return PC=0x%x", state->regData[15].v); UnwPrintd2(" Return PC=0x%x", state->regData[15].v);
@ -585,9 +527,7 @@ UnwResult UnwStartArm(UnwState * const state) {
/* Garbage collect the memory hash (used only for the stack) */ /* Garbage collect the memory hash (used only for the stack) */
UnwMemHashGC(state); UnwMemHashGC(state);
t--; if (--t == 0) return UNWIND_EXHAUSTED;
if (t == 0)
return UNWIND_EXHAUSTED;
} while (!found); } while (!found);

@ -25,17 +25,11 @@
* \param value The value to sign extend. * \param value The value to sign extend.
* \return The signed-11 bit value stored in a 16bit data type. * \return The signed-11 bit value stored in a 16bit data type.
*/ */
static int32_t signExtend11(uint16_t value) { static int32_t signExtend11(const uint16_t value) {
return (value & 0x400) ? value | 0xFFFFF800 : value;
if(value & 0x400) {
value |= 0xFFFFF800;
}
return value;
} }
UnwResult UnwStartThumb(UnwState * const state) { UnwResult UnwStartThumb(UnwState * const state) {
bool found = false; bool found = false;
uint16_t t = UNW_MAX_INSTR_COUNT; uint16_t t = UNW_MAX_INSTR_COUNT;
uint32_t lastJumpAddr = 0; // Last JUMP address, to try to detect infinite loops uint32_t lastJumpAddr = 0; // Last JUMP address, to try to detect infinite loops
@ -45,20 +39,19 @@ UnwResult UnwStartThumb(UnwState * const state) {
uint16_t instr; uint16_t instr;
/* Attempt to read the instruction */ /* Attempt to read the instruction */
if(!state->cb->readH(state->regData[15].v & (~0x1), &instr)) { if (!state->cb->readH(state->regData[15].v & (~0x1), &instr))
return UNWIND_IREAD_H_FAIL; return UNWIND_IREAD_H_FAIL;
}
UnwPrintd4("T %x %x %04x:", state->regData[13].v, state->regData[15].v, instr); UnwPrintd4("T %x %x %04x:", state->regData[13].v, state->regData[15].v, instr);
/* Check that the PC is still on Thumb alignment */ /* Check that the PC is still on Thumb alignment */
if(!(state->regData[15].v & 0x1)) { if (!(state->regData[15].v & 0x1)) {
UnwPrintd1("\nError: PC misalignment\n"); UnwPrintd1("\nError: PC misalignment\n");
return UNWIND_INCONSISTENT; return UNWIND_INCONSISTENT;
} }
/* Check that the SP and PC have not been invalidated */ /* Check that the SP and PC have not been invalidated */
if(!M_IsOriginValid(state->regData[13].o) || !M_IsOriginValid(state->regData[15].o)) { if (!M_IsOriginValid(state->regData[13].o) || !M_IsOriginValid(state->regData[15].o)) {
UnwPrintd1("\nError: PC or SP invalidated\n"); UnwPrintd1("\nError: PC or SP invalidated\n");
return UNWIND_INCONSISTENT; return UNWIND_INCONSISTENT;
} }
@ -73,9 +66,8 @@ UnwResult UnwStartThumb(UnwState * const state) {
state->regData[15].v += 2; state->regData[15].v += 2;
/* Attempt to read the 2nd part of the instruction */ /* Attempt to read the 2nd part of the instruction */
if(!state->cb->readH(state->regData[15].v & (~0x1), &instr2)) { if (!state->cb->readH(state->regData[15].v & (~0x1), &instr2))
return UNWIND_IREAD_H_FAIL; return UNWIND_IREAD_H_FAIL;
}
UnwPrintd3(" %x %04x:", state->regData[15].v, instr2); UnwPrintd3(" %x %04x:", state->regData[15].v, instr2);
@ -84,26 +76,25 @@ UnwResult UnwStartThumb(UnwState * const state) {
* PUSH and POP * PUSH and POP
*/ */
if ((instr & 0xFE6F) == 0xE82D) { if ((instr & 0xFE6F) == 0xE82D) {
bool L = (instr & 0x10) ? true : false; bool L = !!(instr & 0x10);
uint16_t rList = instr2; uint16_t rList = instr2;
if(L) { if (L) {
uint8_t r; uint8_t r;
/* Load from memory: POP */ /* Load from memory: POP */
UnwPrintd1("POP {Rlist}\n"); UnwPrintd1("POP {Rlist}\n");
/* Load registers from stack */ /* Load registers from stack */
for(r = 0; r < 16; r++) { for (r = 0; r < 16; r++) {
if(rList & (0x1 << r)) { if (rList & (0x1 << r)) {
/* Read the word */ /* Read the word */
if(!UnwMemReadRegister(state, state->regData[13].v, &state->regData[r])) { if (!UnwMemReadRegister(state, state->regData[13].v, &state->regData[r]))
return UNWIND_DREAD_W_FAIL; return UNWIND_DREAD_W_FAIL;
}
/* Alter the origin to be from the stack if it was valid */ /* Alter the origin to be from the stack if it was valid */
if(M_IsOriginValid(state->regData[r].o)) { if (M_IsOriginValid(state->regData[r].o)) {
state->regData[r].o = REG_VAL_FROM_STACK; state->regData[r].o = REG_VAL_FROM_STACK;
@ -114,7 +105,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
* the caller was from Thumb. This would allow return * the caller was from Thumb. This would allow return
* by BX for interworking APCS. * by BX for interworking APCS.
*/ */
if((state->regData[15].v & 0x1) == 0) { if ((state->regData[15].v & 0x1) == 0) {
UnwPrintd2("Warning: Return address not to Thumb: 0x%08x\n", state->regData[15].v); UnwPrintd2("Warning: Return address not to Thumb: 0x%08x\n", state->regData[15].v);
/* Pop into the PC will not switch mode */ /* Pop into the PC will not switch mode */
@ -122,9 +113,8 @@ UnwResult UnwStartThumb(UnwState * const state) {
} }
/* Store the return address */ /* Store the return address */
if(!UnwReportRetAddr(state, state->regData[15].v)) { if (!UnwReportRetAddr(state, state->regData[15].v))
return UNWIND_TRUNCATED; return UNWIND_TRUNCATED;
}
/* Now have the return address */ /* Now have the return address */
UnwPrintd2(" Return PC=%x\n", state->regData[15].v); UnwPrintd2(" Return PC=%x\n", state->regData[15].v);
@ -155,15 +145,14 @@ UnwResult UnwStartThumb(UnwState * const state) {
/* Store to memory: PUSH */ /* Store to memory: PUSH */
UnwPrintd1("PUSH {Rlist}"); UnwPrintd1("PUSH {Rlist}");
for(r = 15; r >= 0; r--) { for (r = 15; r >= 0; r--) {
if(rList & (0x1 << r)) { if (rList & (0x1 << r)) {
UnwPrintd4("\n r%d = 0x%08x\t; %s", r, state->regData[r].v, M_Origin2Str(state->regData[r].o)); UnwPrintd4("\n r%d = 0x%08x\t; %s", r, state->regData[r].v, M_Origin2Str(state->regData[r].o));
state->regData[13].v -= 4; state->regData[13].v -= 4;
if(!UnwMemWriteRegister(state, state->regData[13].v, &state->regData[r])) { if (!UnwMemWriteRegister(state, state->regData[13].v, &state->regData[r]))
return UNWIND_DWRITE_W_FAIL; return UNWIND_DWRITE_W_FAIL;
}
} }
} }
} }
@ -180,9 +169,8 @@ UnwResult UnwStartThumb(UnwState * const state) {
state->regData[13].v -= 4; state->regData[13].v -= 4;
if(!UnwMemWriteRegister(state, state->regData[13].v, &state->regData[r])) { if (!UnwMemWriteRegister(state, state->regData[13].v, &state->regData[r]))
return UNWIND_DWRITE_W_FAIL; return UNWIND_DWRITE_W_FAIL;
}
} }
/* /*
* POP register * POP register
@ -194,12 +182,11 @@ UnwResult UnwStartThumb(UnwState * const state) {
UnwPrintd2("POP {R%d}\n", r); UnwPrintd2("POP {R%d}\n", r);
/* Read the word */ /* Read the word */
if(!UnwMemReadRegister(state, state->regData[13].v, &state->regData[r])) { if (!UnwMemReadRegister(state, state->regData[13].v, &state->regData[r]))
return UNWIND_DREAD_W_FAIL; return UNWIND_DREAD_W_FAIL;
}
/* Alter the origin to be from the stack if it was valid */ /* Alter the origin to be from the stack if it was valid */
if(M_IsOriginValid(state->regData[r].o)) { if (M_IsOriginValid(state->regData[r].o)) {
state->regData[r].o = REG_VAL_FROM_STACK; state->regData[r].o = REG_VAL_FROM_STACK;
@ -210,7 +197,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
* the caller was from Thumb. This would allow return * the caller was from Thumb. This would allow return
* by BX for interworking APCS. * by BX for interworking APCS.
*/ */
if((state->regData[15].v & 0x1) == 0) { if ((state->regData[15].v & 0x1) == 0) {
UnwPrintd2("Warning: Return address not to Thumb: 0x%08x\n", state->regData[15].v); UnwPrintd2("Warning: Return address not to Thumb: 0x%08x\n", state->regData[15].v);
/* Pop into the PC will not switch mode */ /* Pop into the PC will not switch mode */
@ -218,9 +205,8 @@ UnwResult UnwStartThumb(UnwState * const state) {
} }
/* Store the return address */ /* Store the return address */
if(!UnwReportRetAddr(state, state->regData[15].v)) { if (!UnwReportRetAddr(state, state->regData[15].v))
return UNWIND_TRUNCATED; return UNWIND_TRUNCATED;
}
/* Now have the return address */ /* Now have the return address */
UnwPrintd2(" Return PC=%x\n", state->regData[15].v); UnwPrintd2(" Return PC=%x\n", state->regData[15].v);
@ -255,7 +241,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
* the switch clauses * the switch clauses
*/ */
uint8_t rn = instr & 0xF; uint8_t rn = instr & 0xF;
bool H = (instr2 & 0x10) ? true : false; bool H = !!(instr2 & 0x10);
UnwPrintd5("TB%c [r%d,r%d%s]\n", H ? 'H' : 'B', rn, (instr2 & 0xF), H ? ",LSL #1" : ""); UnwPrintd5("TB%c [r%d,r%d%s]\n", H ? 'H' : 'B', rn, (instr2 & 0xF), H ? ",LSL #1" : "");
@ -263,15 +249,14 @@ UnwResult UnwStartThumb(UnwState * const state) {
if (rn == 15) { if (rn == 15) {
if (H) { if (H) {
uint16_t rv; uint16_t rv;
if(!state->cb->readH((state->regData[15].v & (~1)) + 2, &rv)) { if (!state->cb->readH((state->regData[15].v & (~1)) + 2, &rv))
return UNWIND_DREAD_H_FAIL; return UNWIND_DREAD_H_FAIL;
}
state->regData[15].v += rv * 2; state->regData[15].v += rv * 2;
} else { }
else {
uint8_t rv; uint8_t rv;
if(!state->cb->readB((state->regData[15].v & (~1)) + 2, &rv)) { if (!state->cb->readB((state->regData[15].v & (~1)) + 2, &rv))
return UNWIND_DREAD_B_FAIL; return UNWIND_DREAD_B_FAIL;
}
state->regData[15].v += rv * 2; state->regData[15].v += rv * 2;
} }
} }
@ -355,12 +340,11 @@ UnwResult UnwStartThumb(UnwState * const state) {
UnwPrintd2(" Return PC=%x", state->regData[15].v); UnwPrintd2(" Return PC=%x", state->regData[15].v);
/* Report the return address, including mode bit */ /* Report the return address, including mode bit */
if(!UnwReportRetAddr(state, state->regData[15].v)) { if (!UnwReportRetAddr(state, state->regData[15].v))
return UNWIND_TRUNCATED; return UNWIND_TRUNCATED;
}
/* Determine the new mode */ /* Determine the new mode */
if(state->regData[15].v & 0x1) { if (state->regData[15].v & 0x1) {
/* Branching to THUMB */ /* Branching to THUMB */
/* Account for the auto-increment which isn't needed */ /* Account for the auto-increment which isn't needed */
@ -411,10 +395,10 @@ UnwResult UnwStartThumb(UnwState * const state) {
* PC-relative load * PC-relative load
* LDR Rd,[PC, #+/-imm] * LDR Rd,[PC, #+/-imm]
*/ */
else if((instr & 0xFF7F) == 0xF85F) { else if ((instr & 0xFF7F) == 0xF85F) {
uint8_t rt = (instr2 & 0xF000) >> 12; uint8_t rt = (instr2 & 0xF000) >> 12;
uint8_t imm12 = (instr2 & 0x0FFF); uint8_t imm12 = (instr2 & 0x0FFF);
bool A = (instr & 0x80) ? true : false; bool A = !!(instr & 0x80);
uint32_t address; uint32_t address;
/* Compute load address, adding a word to account for prefetch */ /* Compute load address, adding a word to account for prefetch */
@ -424,9 +408,8 @@ UnwResult UnwStartThumb(UnwState * const state) {
UnwPrintd4("LDR r%d,[PC #%c0x%08x]", rt, A?'+':'-', address); UnwPrintd4("LDR r%d,[PC #%c0x%08x]", rt, A?'+':'-', address);
if(!UnwMemReadRegister(state, address, &state->regData[rt])) { if (!UnwMemReadRegister(state, address, &state->regData[rt]))
return UNWIND_DREAD_W_FAIL; return UNWIND_DREAD_W_FAIL;
}
} }
/* /*
* LDR immediate. * LDR immediate.
@ -441,11 +424,11 @@ UnwResult UnwStartThumb(UnwState * const state) {
/* If destination is PC and we don't know the source value, then fail */ /* If destination is PC and we don't know the source value, then fail */
if (!M_IsOriginValid(state->regData[rn].o)) { if (!M_IsOriginValid(state->regData[rn].o)) {
state->regData[rt].o = state->regData[rn].o; state->regData[rt].o = state->regData[rn].o;
} else { }
else {
uint32_t address = state->regData[rn].v + imm12; uint32_t address = state->regData[rn].v + imm12;
if(!UnwMemReadRegister(state, address, &state->regData[rt])) { if (!UnwMemReadRegister(state, address, &state->regData[rt]))
return UNWIND_DREAD_W_FAIL; return UNWIND_DREAD_W_FAIL;
}
} }
} }
/* /*
@ -459,31 +442,20 @@ UnwResult UnwStartThumb(UnwState * const state) {
uint8_t rn = (instr & 0xF); uint8_t rn = (instr & 0xF);
uint8_t rt = (instr2 & 0xF000) >> 12; uint8_t rt = (instr2 & 0xF000) >> 12;
uint16_t imm8 = (instr2 & 0xFF); uint16_t imm8 = (instr2 & 0xFF);
bool P = (instr2 & 0x400) ? true : false; bool P = !!(instr2 & 0x400);
bool U = (instr2 & 0x200) ? true : false; bool U = !!(instr2 & 0x200);
bool W = (instr2 & 0x100) ? true : false; bool W = !!(instr2 & 0x100);
if (!M_IsOriginValid(state->regData[rn].o)) { if (!M_IsOriginValid(state->regData[rn].o))
state->regData[rt].o = state->regData[rn].o; state->regData[rt].o = state->regData[rn].o;
} else { else {
uint32_t offaddress = state->regData[rn].v + imm8; uint32_t offaddress = state->regData[rn].v + (U ? imm8 + imm8 : 0),
if (U) offaddress += imm8; address = P ? offaddress : state->regData[rn].v;
else offaddress -= imm8;
uint32_t address;
if (P) {
address = offaddress;
} else {
address = state->regData[rn].v;
}
if(!UnwMemReadRegister(state, address, &state->regData[rt])) { if (!UnwMemReadRegister(state, address, &state->regData[rt]))
return UNWIND_DREAD_W_FAIL; return UNWIND_DREAD_W_FAIL;
}
if (W) { if (W) state->regData[rn].v = offaddress;
state->regData[rn].v = offaddress;
}
} }
} }
/* /*
@ -493,30 +465,28 @@ UnwResult UnwStartThumb(UnwState * const state) {
* Where Rt is PC, Rn value is known, Rm is not known or unknown * Where Rt is PC, Rn value is known, Rm is not known or unknown
*/ */
else if ((instr & 0xFFF0) == 0xF850 && (instr2 & 0x0FC0) == 0x0000) { else if ((instr & 0xFFF0) == 0xF850 && (instr2 & 0x0FC0) == 0x0000) {
uint8_t rn = (instr & 0xF); const uint8_t rn = (instr & 0xF),
uint8_t rt = (instr2 & 0xF000) >> 12; rt = (instr2 & 0xF000) >> 12,
uint8_t rm = (instr2 & 0xF); rm = (instr2 & 0xF),
uint8_t imm2 = (instr2 & 0x30) >> 4; imm2 = (instr2 & 0x30) >> 4;
if (!M_IsOriginValid(state->regData[rn].o) || if (!M_IsOriginValid(state->regData[rn].o) || !M_IsOriginValid(state->regData[rm].o)) {
!M_IsOriginValid(state->regData[rm].o)) {
/* If Rt is PC, and Rn is known, then do an exception and assume /* If Rt is PC, and Rn is known, then do an exception and assume
Rm equals 0 => This takes the first case in a switch() */ Rm equals 0 => This takes the first case in a switch() */
if (rt == 15 && M_IsOriginValid(state->regData[rn].o)) { if (rt == 15 && M_IsOriginValid(state->regData[rn].o)) {
uint32_t address = state->regData[rn].v; uint32_t address = state->regData[rn].v;
if(!UnwMemReadRegister(state, address, &state->regData[rt])) { if (!UnwMemReadRegister(state, address, &state->regData[rt]))
return UNWIND_DREAD_W_FAIL; return UNWIND_DREAD_W_FAIL;
}
} else {
/* Propagate unknown value */
state->regData[rt].o = state->regData[rn].o;
} }
} else { else /* Propagate unknown value */
state->regData[rt].o = state->regData[rn].o;
}
else {
uint32_t address = state->regData[rn].v + (state->regData[rm].v << imm2); uint32_t address = state->regData[rn].v + (state->regData[rm].v << imm2);
if(!UnwMemReadRegister(state, address, &state->regData[rt])) { if (!UnwMemReadRegister(state, address, &state->regData[rt]))
return UNWIND_DREAD_W_FAIL; return UNWIND_DREAD_W_FAIL;
}
} }
} }
else { else {
@ -533,14 +503,14 @@ UnwResult UnwStartThumb(UnwState * const state) {
* LSR Rd, Rs, #Offset5 * LSR Rd, Rs, #Offset5
* ASR Rd, Rs, #Offset5 * ASR Rd, Rs, #Offset5
*/ */
else if((instr & 0xE000) == 0x0000 && (instr & 0x1800) != 0x1800) { else if ((instr & 0xE000) == 0x0000 && (instr & 0x1800) != 0x1800) {
bool signExtend; bool signExtend;
uint8_t op = (instr & 0x1800) >> 11; const uint8_t op = (instr & 0x1800) >> 11,
uint8_t offset5 = (instr & 0x07C0) >> 6; offset5 = (instr & 0x07C0) >> 6,
uint8_t rs = (instr & 0x0038) >> 3; rs = (instr & 0x0038) >> 3,
uint8_t rd = (instr & 0x0007); rd = (instr & 0x0007);
switch(op) { switch (op) {
case 0: /* LSL */ case 0: /* LSL */
UnwPrintd6("LSL r%d, r%d, #%d\t; r%d %s", rd, rs, offset5, rs, M_Origin2Str(state->regData[rs].o)); UnwPrintd6("LSL r%d, r%d, #%d\t; r%d %s", rd, rs, offset5, rs, M_Origin2Str(state->regData[rs].o));
state->regData[rd].v = state->regData[rs].v << offset5; state->regData[rd].v = state->regData[rs].v << offset5;
@ -558,11 +528,9 @@ UnwResult UnwStartThumb(UnwState * const state) {
case 2: /* ASR */ case 2: /* ASR */
UnwPrintd6("ASL r%d, r%d, #%d\t; r%d %s", rd, rs, offset5, rs, M_Origin2Str(state->regData[rs].o)); UnwPrintd6("ASL r%d, r%d, #%d\t; r%d %s", rd, rs, offset5, rs, M_Origin2Str(state->regData[rs].o));
signExtend = (state->regData[rs].v & 0x8000) ? true : false; signExtend = !!(state->regData[rs].v & 0x8000);
state->regData[rd].v = state->regData[rs].v >> offset5; state->regData[rd].v = state->regData[rs].v >> offset5;
if(signExtend) { if (signExtend) state->regData[rd].v |= 0xFFFFFFFF << (32 - offset5);
state->regData[rd].v |= 0xFFFFFFFF << (32 - offset5);
}
state->regData[rd].o = state->regData[rs].o; state->regData[rd].o = state->regData[rs].o;
state->regData[rd].o |= REG_VAL_ARITHMETIC; state->regData[rd].o |= REG_VAL_ARITHMETIC;
break; break;
@ -574,9 +542,9 @@ UnwResult UnwStartThumb(UnwState * const state) {
* SUB Rd, Rs, Rn * SUB Rd, Rs, Rn
* SUB Rd, Rs, #Offset3 * SUB Rd, Rs, #Offset3
*/ */
else if((instr & 0xF800) == 0x1800) { else if ((instr & 0xF800) == 0x1800) {
bool I = (instr & 0x0400) ? true : false; bool I = !!(instr & 0x0400);
bool op = (instr & 0x0200) ? true : false; bool op = !!(instr & 0x0200);
uint8_t rn = (instr & 0x01C0) >> 6; uint8_t rn = (instr & 0x01C0) >> 6;
uint8_t rs = (instr & 0x0038) >> 3; uint8_t rs = (instr & 0x0038) >> 3;
uint8_t rd = (instr & 0x0007); uint8_t rd = (instr & 0x0007);
@ -584,36 +552,24 @@ UnwResult UnwStartThumb(UnwState * const state) {
/* Print decoding */ /* Print decoding */
UnwPrintd6("%s r%d, r%d, %c%d\t;",op ? "SUB" : "ADD",rd, rs,I ? '#' : 'r',rn); UnwPrintd6("%s r%d, r%d, %c%d\t;",op ? "SUB" : "ADD",rd, rs,I ? '#' : 'r',rn);
UnwPrintd5("r%d %s, r%d %s",rd, M_Origin2Str(state->regData[rd].o),rs, M_Origin2Str(state->regData[rs].o)); UnwPrintd5("r%d %s, r%d %s",rd, M_Origin2Str(state->regData[rd].o),rs, M_Origin2Str(state->regData[rs].o));
if(!I) { if (!I) {
UnwPrintd3(", r%d %s", rn, M_Origin2Str(state->regData[rn].o)); UnwPrintd3(", r%d %s", rn, M_Origin2Str(state->regData[rn].o));
/* Perform calculation */ /* Perform calculation */
if(op) { state->regData[rd].v = state->regData[rs].v + (op ? -state->regData[rn].v : state->regData[rn].v);
state->regData[rd].v = state->regData[rs].v - state->regData[rn].v;
}
else {
state->regData[rd].v = state->regData[rs].v + state->regData[rn].v;
}
/* Propagate the origin */ /* Propagate the origin */
if(M_IsOriginValid(state->regData[rs].o) && if (M_IsOriginValid(state->regData[rs].o) && M_IsOriginValid(state->regData[rn].o)) {
M_IsOriginValid(state->regData[rn].o)) {
state->regData[rd].o = state->regData[rs].o; state->regData[rd].o = state->regData[rs].o;
state->regData[rd].o |= REG_VAL_ARITHMETIC; state->regData[rd].o |= REG_VAL_ARITHMETIC;
} }
else { else
state->regData[rd].o = REG_VAL_INVALID; state->regData[rd].o = REG_VAL_INVALID;
}
} }
else { else {
/* Perform calculation */ /* Perform calculation */
if(op) { state->regData[rd].v = state->regData[rs].v + (op ? -rn : rn);
state->regData[rd].v = state->regData[rs].v - rn;
}
else {
state->regData[rd].v = state->regData[rs].v + rn;
}
/* Propagate the origin */ /* Propagate the origin */
state->regData[rd].o = state->regData[rs].o; state->regData[rd].o = state->regData[rs].o;
@ -626,13 +582,13 @@ UnwResult UnwStartThumb(UnwState * const state) {
* ADD Rd, #Offset8 * ADD Rd, #Offset8
* SUB Rd, #Offset8 * SUB Rd, #Offset8
*/ */
else if((instr & 0xE000) == 0x2000) { else if ((instr & 0xE000) == 0x2000) {
uint8_t op = (instr & 0x1800) >> 11; uint8_t op = (instr & 0x1800) >> 11;
uint8_t rd = (instr & 0x0700) >> 8; uint8_t rd = (instr & 0x0700) >> 8;
uint8_t offset8 = (instr & 0x00FF); uint8_t offset8 = (instr & 0x00FF);
switch(op) { switch (op) {
case 0: /* MOV */ case 0: /* MOV */
UnwPrintd3("MOV r%d, #0x%x", rd, offset8); UnwPrintd3("MOV r%d, #0x%x", rd, offset8);
state->regData[rd].v = offset8; state->regData[rd].v = offset8;
@ -675,7 +631,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
* BIC Rd, Rs * BIC Rd, Rs
* MVN Rd, Rs * MVN Rd, Rs
*/ */
else if((instr & 0xFC00) == 0x4000) { else if ((instr & 0xFC00) == 0x4000) {
uint8_t op = (instr & 0x03C0) >> 6; uint8_t op = (instr & 0x03C0) >> 6;
uint8_t rs = (instr & 0x0038) >> 3; uint8_t rs = (instr & 0x0038) >> 3;
uint8_t rd = (instr & 0x0007); uint8_t rd = (instr & 0x0007);
@ -688,7 +644,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
"ORR", "MUL", "BIC", "MVN" }; "ORR", "MUL", "BIC", "MVN" };
#endif #endif
/* Print the mnemonic and registers */ /* Print the mnemonic and registers */
switch(op) { switch (op) {
case 0: /* AND */ case 0: /* AND */
case 1: /* EOR */ case 1: /* EOR */
case 2: /* LSL */ case 2: /* LSL */
@ -720,7 +676,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
} }
/* Perform operation */ /* Perform operation */
switch(op) { switch (op) {
case 0: /* AND */ case 0: /* AND */
state->regData[rd].v &= state->regData[rs].v; state->regData[rd].v &= state->regData[rs].v;
break; break;
@ -738,7 +694,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
break; break;
case 4: /* ASR */ case 4: /* ASR */
if(state->regData[rd].v & 0x80000000) { if (state->regData[rd].v & 0x80000000) {
state->regData[rd].v >>= state->regData[rs].v; state->regData[rd].v >>= state->regData[rs].v;
state->regData[rd].v |= 0xFFFFFFFF << (32 - state->regData[rs].v); state->regData[rd].v |= 0xFFFFFFFF << (32 - state->regData[rs].v);
} }
@ -782,7 +738,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
} }
/* Propagate data origins */ /* Propagate data origins */
switch(op) { switch (op) {
case 0: /* AND */ case 0: /* AND */
case 1: /* EOR */ case 1: /* EOR */
case 2: /* LSL */ case 2: /* LSL */
@ -792,13 +748,12 @@ UnwResult UnwStartThumb(UnwState * const state) {
case 12: /* ORR */ case 12: /* ORR */
case 13: /* MUL */ case 13: /* MUL */
case 14: /* BIC */ case 14: /* BIC */
if(M_IsOriginValid(state->regData[rd].o) && M_IsOriginValid(state->regData[rs].o)) { if (M_IsOriginValid(state->regData[rd].o) && M_IsOriginValid(state->regData[rs].o)) {
state->regData[rd].o = state->regData[rs].o; state->regData[rd].o = state->regData[rs].o;
state->regData[rd].o |= REG_VAL_ARITHMETIC; state->regData[rd].o |= REG_VAL_ARITHMETIC;
} }
else { else
state->regData[rd].o = REG_VAL_INVALID; state->regData[rd].o = REG_VAL_INVALID;
}
break; break;
case 5: /* ADC */ case 5: /* ADC */
@ -825,7 +780,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
* CMP Hd, Rs * CMP Hd, Rs
* MOV Hd, Hs * MOV Hd, Hs
*/ */
else if((instr & 0xFC00) == 0x4400) { else if ((instr & 0xFC00) == 0x4400) {
uint8_t op = (instr & 0x0300) >> 8; uint8_t op = (instr & 0x0300) >> 8;
bool h1 = (instr & 0x0080) ? true: false; bool h1 = (instr & 0x0080) ? true: false;
bool h2 = (instr & 0x0040) ? true: false; bool h2 = (instr & 0x0040) ? true: false;
@ -833,12 +788,10 @@ UnwResult UnwStartThumb(UnwState * const state) {
uint8_t rhd = (instr & 0x0007); uint8_t rhd = (instr & 0x0007);
/* Adjust the register numbers */ /* Adjust the register numbers */
if(h2) if (h2) rhs += 8;
rhs += 8; if (h1) rhd += 8;
if(h1)
rhd += 8;
switch(op) { switch (op) {
case 0: /* ADD */ case 0: /* ADD */
UnwPrintd5("ADD r%d, r%d\t; r%d %s", rhd, rhs, rhs, M_Origin2Str(state->regData[rhs].o)); UnwPrintd5("ADD r%d, r%d\t; r%d %s", rhd, rhs, rhs, M_Origin2Str(state->regData[rhs].o));
state->regData[rhd].v += state->regData[rhs].v; state->regData[rhd].v += state->regData[rhs].v;
@ -861,28 +814,25 @@ UnwResult UnwStartThumb(UnwState * const state) {
UnwPrintd4("BX r%d\t; r%d %s\n", rhs, rhs, M_Origin2Str(state->regData[rhs].o)); UnwPrintd4("BX r%d\t; r%d %s\n", rhs, rhs, M_Origin2Str(state->regData[rhs].o));
/* Only follow BX if the data was from the stack or BX LR */ /* Only follow BX if the data was from the stack or BX LR */
if(rhs == 14 || state->regData[rhs].o == REG_VAL_FROM_STACK) { if (rhs == 14 || state->regData[rhs].o == REG_VAL_FROM_STACK) {
UnwPrintd2(" Return PC=0x%x\n", state->regData[rhs].v & (~0x1)); UnwPrintd2(" Return PC=0x%x\n", state->regData[rhs].v & (~0x1));
/* Report the return address, including mode bit */ /* Report the return address, including mode bit */
if(!UnwReportRetAddr(state, state->regData[rhs].v)) { if (!UnwReportRetAddr(state, state->regData[rhs].v))
return UNWIND_TRUNCATED; return UNWIND_TRUNCATED;
}
/* Update the PC */ /* Update the PC */
state->regData[15].v = state->regData[rhs].v; state->regData[15].v = state->regData[rhs].v;
/* Determine the new mode */ /* Determine the new mode */
if(state->regData[rhs].v & 0x1) { if (state->regData[rhs].v & 0x1) {
/* Branching to THUMB */ /* Branching to THUMB */
/* Account for the auto-increment which isn't needed */ /* Account for the auto-increment which isn't needed */
state->regData[15].v -= 2; state->regData[15].v -= 2;
} }
else { else /* Branch to ARM */
/* Branch to ARM */
return UnwStartArm(state); return UnwStartArm(state);
}
} }
else { else {
UnwPrintd4("\nError: BX to invalid register: r%d = 0x%x (%s)\n", rhs, state->regData[rhs].o, M_Origin2Str(state->regData[rhs].o)); UnwPrintd4("\nError: BX to invalid register: r%d = 0x%x (%s)\n", rhs, state->regData[rhs].o, M_Origin2Str(state->regData[rhs].o));
@ -893,7 +843,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
/* Format 9: PC-relative load /* Format 9: PC-relative load
* LDR Rd,[PC, #imm] * LDR Rd,[PC, #imm]
*/ */
else if((instr & 0xF800) == 0x4800) { else if ((instr & 0xF800) == 0x4800) {
uint8_t rd = (instr & 0x0700) >> 8; uint8_t rd = (instr & 0x0700) >> 8;
uint8_t word8 = (instr & 0x00FF); uint8_t word8 = (instr & 0x00FF);
uint32_t address; uint32_t address;
@ -903,19 +853,18 @@ UnwResult UnwStartThumb(UnwState * const state) {
UnwPrintd3("LDR r%d, 0x%08x", rd, address); UnwPrintd3("LDR r%d, 0x%08x", rd, address);
if(!UnwMemReadRegister(state, address, &state->regData[rd])) { if (!UnwMemReadRegister(state, address, &state->regData[rd]))
return UNWIND_DREAD_W_FAIL; return UNWIND_DREAD_W_FAIL;
}
} }
/* Format 13: add offset to Stack Pointer /* Format 13: add offset to Stack Pointer
* ADD sp,#+imm * ADD sp,#+imm
* ADD sp,#-imm * ADD sp,#-imm
*/ */
else if((instr & 0xFF00) == 0xB000) { else if ((instr & 0xFF00) == 0xB000) {
uint8_t value = (instr & 0x7F) * 4; uint8_t value = (instr & 0x7F) * 4;
/* Check the negative bit */ /* Check the negative bit */
if((instr & 0x80) != 0) { if ((instr & 0x80) != 0) {
UnwPrintd2("SUB sp,#0x%x", value); UnwPrintd2("SUB sp,#0x%x", value);
state->regData[13].v -= value; state->regData[13].v -= value;
} }
@ -930,29 +879,27 @@ UnwResult UnwStartThumb(UnwState * const state) {
* POP {Rlist} * POP {Rlist}
* POP {Rlist, PC} * POP {Rlist, PC}
*/ */
else if((instr & 0xF600) == 0xB400) { else if ((instr & 0xF600) == 0xB400) {
bool L = (instr & 0x0800) ? true : false; bool L = !!(instr & 0x0800);
bool R = (instr & 0x0100) ? true : false; bool R = !!(instr & 0x0100);
uint8_t rList = (instr & 0x00FF); uint8_t rList = (instr & 0x00FF);
if(L) { if (L) {
uint8_t r; uint8_t r;
/* Load from memory: POP */ /* Load from memory: POP */
UnwPrintd2("POP {Rlist%s}\n", R ? ", PC" : ""); UnwPrintd2("POP {Rlist%s}\n", R ? ", PC" : "");
for(r = 0; r < 8; r++) { for (r = 0; r < 8; r++) {
if(rList & (0x1 << r)) { if (rList & (0x1 << r)) {
/* Read the word */ /* Read the word */
if(!UnwMemReadRegister(state, state->regData[13].v, &state->regData[r])) { if (!UnwMemReadRegister(state, state->regData[13].v, &state->regData[r]))
return UNWIND_DREAD_W_FAIL; return UNWIND_DREAD_W_FAIL;
}
/* Alter the origin to be from the stack if it was valid */ /* Alter the origin to be from the stack if it was valid */
if(M_IsOriginValid(state->regData[r].o)) { if (M_IsOriginValid(state->regData[r].o))
state->regData[r].o = REG_VAL_FROM_STACK; state->regData[r].o = REG_VAL_FROM_STACK;
}
state->regData[13].v += 4; state->regData[13].v += 4;
@ -961,14 +908,13 @@ UnwResult UnwStartThumb(UnwState * const state) {
} }
/* Check if the PC is to be popped */ /* Check if the PC is to be popped */
if(R) { if (R) {
/* Get the return address */ /* Get the return address */
if(!UnwMemReadRegister(state, state->regData[13].v, &state->regData[15])) { if (!UnwMemReadRegister(state, state->regData[13].v, &state->regData[15]))
return UNWIND_DREAD_W_FAIL; return UNWIND_DREAD_W_FAIL;
}
/* Alter the origin to be from the stack if it was valid */ /* Alter the origin to be from the stack if it was valid */
if(!M_IsOriginValid(state->regData[15].o)) { if (!M_IsOriginValid(state->regData[15].o)) {
/* Return address is not valid */ /* Return address is not valid */
UnwPrintd1("PC popped with invalid address\n"); UnwPrintd1("PC popped with invalid address\n");
return UNWIND_FAILURE; return UNWIND_FAILURE;
@ -978,7 +924,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
* the caller was from Thumb. This would allow return * the caller was from Thumb. This would allow return
* by BX for interworking APCS. * by BX for interworking APCS.
*/ */
if((state->regData[15].v & 0x1) == 0) { if ((state->regData[15].v & 0x1) == 0) {
UnwPrintd2("Warning: Return address not to Thumb: 0x%08x\n", state->regData[15].v); UnwPrintd2("Warning: Return address not to Thumb: 0x%08x\n", state->regData[15].v);
/* Pop into the PC will not switch mode */ /* Pop into the PC will not switch mode */
@ -986,9 +932,8 @@ UnwResult UnwStartThumb(UnwState * const state) {
} }
/* Store the return address */ /* Store the return address */
if(!UnwReportRetAddr(state, state->regData[15].v)) { if (!UnwReportRetAddr(state, state->regData[15].v))
return UNWIND_TRUNCATED; return UNWIND_TRUNCATED;
}
/* Now have the return address */ /* Now have the return address */
UnwPrintd2(" Return PC=%x\n", state->regData[15].v); UnwPrintd2(" Return PC=%x\n", state->regData[15].v);
@ -1008,26 +953,24 @@ UnwResult UnwStartThumb(UnwState * const state) {
UnwPrintd2("PUSH {Rlist%s}", R ? ", LR" : ""); UnwPrintd2("PUSH {Rlist%s}", R ? ", LR" : "");
/* Check if the LR is to be pushed */ /* Check if the LR is to be pushed */
if(R) { if (R) {
UnwPrintd3("\n lr = 0x%08x\t; %s", state->regData[14].v, M_Origin2Str(state->regData[14].o)); UnwPrintd3("\n lr = 0x%08x\t; %s", state->regData[14].v, M_Origin2Str(state->regData[14].o));
state->regData[13].v -= 4; state->regData[13].v -= 4;
/* Write the register value to memory */ /* Write the register value to memory */
if(!UnwMemWriteRegister(state, state->regData[13].v, &state->regData[14])) { if (!UnwMemWriteRegister(state, state->regData[13].v, &state->regData[14]))
return UNWIND_DWRITE_W_FAIL; return UNWIND_DWRITE_W_FAIL;
}
} }
for(r = 7; r >= 0; r--) { for (r = 7; r >= 0; r--) {
if(rList & (0x1 << r)) { if (rList & (0x1 << r)) {
UnwPrintd4("\n r%d = 0x%08x\t; %s", r, state->regData[r].v, M_Origin2Str(state->regData[r].o)); UnwPrintd4("\n r%d = 0x%08x\t; %s", r, state->regData[r].v, M_Origin2Str(state->regData[r].o));
state->regData[13].v -= 4; state->regData[13].v -= 4;
if(!UnwMemWriteRegister(state, state->regData[13].v, &state->regData[r])) { if (!UnwMemWriteRegister(state, state->regData[13].v, &state->regData[r]))
return UNWIND_DWRITE_W_FAIL; return UNWIND_DWRITE_W_FAIL;
}
} }
} }
} }
@ -1037,7 +980,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
* Conditional branches * Conditional branches
* Bcond * Bcond
*/ */
else if((instr & 0xF000) == 0xD000) { else if ((instr & 0xF000) == 0xD000) {
int32_t branchValue = (instr & 0xFF); int32_t branchValue = (instr & 0xFF);
if (branchValue & 0x80) branchValue |= 0xFFFFFF00; if (branchValue & 0x80) branchValue |= 0xFFFFFF00;
@ -1066,7 +1009,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
/* Format 18: unconditional branch /* Format 18: unconditional branch
* B label * B label
*/ */
else if((instr & 0xF800) == 0xE000) { else if ((instr & 0xF800) == 0xE000) {
uint32_t v; uint32_t v;
int32_t branchValue = signExtend11(instr & 0x07FF); int32_t branchValue = signExtend11(instr & 0x07FF);
@ -1106,8 +1049,7 @@ UnwResult UnwStartThumb(UnwState * const state) {
UnwPrintd1("\n"); UnwPrintd1("\n");
/* Should never hit the reset vector */ /* Should never hit the reset vector */
if(state->regData[15].v == 0) if (state->regData[15].v == 0) return UNWIND_RESET;
return UNWIND_RESET;
/* Check next address */ /* Check next address */
state->regData[15].v += 2; state->regData[15].v += 2;
@ -1115,11 +1057,9 @@ UnwResult UnwStartThumb(UnwState * const state) {
/* Garbage collect the memory hash (used only for the stack) */ /* Garbage collect the memory hash (used only for the stack) */
UnwMemHashGC(state); UnwMemHashGC(state);
t--; if (--t == 0) return UNWIND_EXHAUSTED;
if(t == 0)
return UNWIND_EXHAUSTED;
} while(!found); } while (!found);
return UNWIND_SUCCESS; return UNWIND_SUCCESS;
} }

@ -19,7 +19,7 @@
#include "unwarmmem.h" #include "unwarmmem.h"
#include "unwarm.h" #include "unwarm.h"
#define M_IsIdxUsed(a, v) (((a)[v >> 3] & (1 << (v & 0x7))) ? true : false) #define M_IsIdxUsed(a, v) !!((a)[v >> 3] & (1 << (v & 0x7)))
#define M_SetIdxUsed(a, v) ((a)[v >> 3] |= (1 << (v & 0x7))) #define M_SetIdxUsed(a, v) ((a)[v >> 3] |= (1 << (v & 0x7)))
#define M_ClrIdxUsed(a, v) ((a)[v >> 3] &= ~(1 << (v & 0x7))) #define M_ClrIdxUsed(a, v) ((a)[v >> 3] &= ~(1 << (v & 0x7)))
@ -34,11 +34,9 @@ static int16_t memHashIndex(MemData * const memData, const uint32_t addr) {
do { do {
/* Check if the element is occupied */ /* Check if the element is occupied */
if(M_IsIdxUsed(memData->used, s)) { if (M_IsIdxUsed(memData->used, s)) {
/* Check if it is occupied with the sought data */ /* Check if it is occupied with the sought data */
if(memData->a[s] == addr) { if (memData->a[s] == addr) return s;
return s;
}
} }
else { else {
/* Item is free, this is where the item should be stored */ /* Item is free, this is where the item should be stored */
@ -47,10 +45,8 @@ static int16_t memHashIndex(MemData * const memData, const uint32_t addr) {
/* Search the next entry */ /* Search the next entry */
s++; s++;
if(s > MEM_HASH_SIZE) { if (s > MEM_HASH_SIZE) s = 0;
s = 0; } while (s != v);
}
} while(s != v);
/* Search failed, hash is full and the address not stored */ /* Search failed, hash is full and the address not stored */
return -1; return -1;
@ -58,9 +54,9 @@ static int16_t memHashIndex(MemData * const memData, const uint32_t addr) {
bool UnwMemHashRead(MemData * const memData, uint32_t addr,uint32_t * const data, bool * const tracked) { bool UnwMemHashRead(MemData * const memData, uint32_t addr,uint32_t * const data, bool * const tracked) {
int16_t i = memHashIndex(memData, addr); const int16_t i = memHashIndex(memData, addr);
if(i >= 0 && M_IsIdxUsed(memData->used, i) && memData->a[i] == addr) { if (i >= 0 && M_IsIdxUsed(memData->used, i) && memData->a[i] == addr) {
*data = memData->v[i]; *data = memData->v[i];
*tracked = M_IsIdxUsed(memData->tracked, i); *tracked = M_IsIdxUsed(memData->tracked, i);
return true; return true;
@ -72,44 +68,36 @@ bool UnwMemHashRead(MemData * const memData, uint32_t addr,uint32_t * const data
} }
bool UnwMemHashWrite(MemData * const memData, uint32_t addr, uint32_t val, bool valValid) { bool UnwMemHashWrite(MemData * const memData, uint32_t addr, uint32_t val, bool valValid) {
const int16_t i = memHashIndex(memData, addr);
if (i < 0) return false; /* Hash full */
int16_t i = memHashIndex(memData, addr); /* Store the item */
memData->a[i] = addr;
M_SetIdxUsed(memData->used, i);
if(i < 0){ if (valValid) {
/* Hash full */ memData->v[i] = val;
return false; M_SetIdxUsed(memData->tracked, i);
} }
else { else {
/* Store the item */ #ifdef UNW_DEBUG
memData->a[i] = addr; memData->v[i] = 0xDEADBEEF;
M_SetIdxUsed(memData->used, i); #endif
M_ClrIdxUsed(memData->tracked, i);
if(valValid)
{
memData->v[i] = val;
M_SetIdxUsed(memData->tracked, i);
}
else {
#ifdef UNW_DEBUG
memData->v[i] = 0xDEADBEEF;
#endif
M_ClrIdxUsed(memData->tracked, i);
}
return true;
} }
return true;
} }
void UnwMemHashGC(UnwState * const state) { void UnwMemHashGC(UnwState * const state) {
const uint32_t minValidAddr = state->regData[13].v; const uint32_t minValidAddr = state->regData[13].v;
MemData * const memData = &state->memData; MemData * const memData = &state->memData;
uint16_t t; uint16_t t;
for(t = 0; t < MEM_HASH_SIZE; t++) { for (t = 0; t < MEM_HASH_SIZE; t++) {
if(M_IsIdxUsed(memData->used, t) && (memData->a[t] < minValidAddr)) { if (M_IsIdxUsed(memData->used, t) && (memData->a[t] < minValidAddr)) {
UnwPrintd3("MemHashGC: Free elem %d, addr 0x%08x\n", t, memData->a[t]); UnwPrintd3("MemHashGC: Free elem %d, addr 0x%08x\n", t, memData->a[t]);
M_ClrIdxUsed(memData->used, t); M_ClrIdxUsed(memData->used, t);
} }
} }

@ -33,13 +33,11 @@ static int HasUnwindTableInfo(void) {
} }
UnwResult UnwindStart(UnwindFrame* frame, const UnwindCallbacks *cb, void *data) { UnwResult UnwindStart(UnwindFrame* frame, const UnwindCallbacks *cb, void *data) {
if (HasUnwindTableInfo()) { if (HasUnwindTableInfo()) {
/* We have unwind information tables */ /* We have unwind information tables */
return UnwindByTableStart(frame, cb, data); return UnwindByTableStart(frame, cb, data);
}
} else { else {
/* We don't have unwind information tables */ /* We don't have unwind information tables */
UnwState state; UnwState state;
@ -48,12 +46,7 @@ UnwResult UnwindStart(UnwindFrame* frame, const UnwindCallbacks *cb, void *data)
UnwInitState(&state, cb, data, frame->pc, frame->sp); UnwInitState(&state, cb, data, frame->pc, frame->sp);
/* Check the Thumb bit */ /* Check the Thumb bit */
if(frame->pc & 0x1) { return (frame->pc & 0x1) ? UnwStartThumb(&state) : UnwStartArm(&state);
return UnwStartThumb(&state);
}
else {
return UnwStartArm(&state);
}
} }
} }
#endif #endif

@ -143,7 +143,7 @@ public:
break; break;
case EP_M876: case EP_M876:
switch(c) { switch (c) {
case ' ': break; case ' ': break;
case 'S': state = EP_M876S; break; case 'S': state = EP_M876S; break;
default: state = EP_IGNORE; break; default: state = EP_IGNORE; break;

@ -557,7 +557,7 @@ void MMU2::toolChange(const char* special) {
set_runout_valid(false); set_runout_valid(false);
KEEPALIVE_STATE(IN_HANDLER); KEEPALIVE_STATE(IN_HANDLER);
switch(*special) { switch (*special) {
case '?': { case '?': {
uint8_t index = mmu2_chooseFilament(); uint8_t index = mmu2_chooseFilament();
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100);

@ -248,7 +248,7 @@ inline void probe_side(measurements_t &m, const float uncertainty, const side_t
park_above_object(m, uncertainty); park_above_object(m, uncertainty);
switch(side) { switch (side) {
case TOP: { case TOP: {
const float measurement = measure(Z_AXIS, -1, true, &m.backlash[TOP], uncertainty); const float measurement = measure(Z_AXIS, -1, true, &m.backlash[TOP], uncertainty);
m.obj_center[Z_AXIS] = measurement - dimensions[Z_AXIS] / 2; m.obj_center[Z_AXIS] = measurement - dimensions[Z_AXIS] / 2;

@ -112,7 +112,7 @@ static const uint8_t u8g_dev_sh1106_128x64_init_seq_2_wire[] PROGMEM = {
}; };
uint8_t u8g_dev_sh1106_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { uint8_t u8g_dev_sh1106_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) {
switch(msg) { switch (msg) {
case U8G_DEV_MSG_INIT: case U8G_DEV_MSG_INIT:
u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS);
u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_init_seq_2_wire); u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_sh1106_128x64_init_seq_2_wire);
@ -180,7 +180,7 @@ static const uint8_t u8g_dev_ssd1306_128x64_init_seq_2_wire[] PROGMEM = {
}; };
uint8_t u8g_dev_ssd1306_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { uint8_t u8g_dev_ssd1306_128x64_2x_2_wire_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) {
switch(msg) { switch (msg) {
case U8G_DEV_MSG_INIT: case U8G_DEV_MSG_INIT:
u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS);
u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_init_seq_2_wire); u8g_WriteEscSeqP_2_wire(u8g, dev, u8g_dev_ssd1306_128x64_init_seq_2_wire);
@ -227,7 +227,7 @@ u8g_dev_t u8g_dev_ssd1306_128x64_2x_i2c_2_wire = { u8g_dev_ssd1306_128x64_2x_2_w
uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_seq) { uint8_t u8g_WriteEscSeqP_2_wire(u8g_t *u8g, u8g_dev_t *dev, const uint8_t *esc_seq) {
uint8_t is_escape = 0; uint8_t is_escape = 0;
uint8_t value; uint8_t value;
for(;;) { for (;;) {
value = u8g_pgm_read(esc_seq); value = u8g_pgm_read(esc_seq);
if (is_escape == 0) { if (is_escape == 0) {
if (value != 255) { if (value != 255) {

@ -149,7 +149,7 @@ static const uint8_t u8g_dev_st7565_64128n_HAL_sleep_off[] PROGMEM = {
}; };
uint8_t u8g_dev_st7565_64128n_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, const uint8_t msg, void *arg) { uint8_t u8g_dev_st7565_64128n_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, const uint8_t msg, void *arg) {
switch(msg) { switch (msg) {
case U8G_DEV_MSG_INIT: case U8G_DEV_MSG_INIT:
u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS); u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS);
u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_init_seq); u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_init_seq);
@ -183,7 +183,7 @@ uint8_t u8g_dev_st7565_64128n_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, const uint8_t m
} }
uint8_t u8g_dev_st7565_64128n_HAL_2x_fn(u8g_t *u8g, u8g_dev_t *dev, const uint8_t msg, void *arg) { uint8_t u8g_dev_st7565_64128n_HAL_2x_fn(u8g_t *u8g, u8g_dev_t *dev, const uint8_t msg, void *arg) {
switch(msg) { switch (msg) {
case U8G_DEV_MSG_INIT: case U8G_DEV_MSG_INIT:
u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS); u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS);
u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_init_seq); u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7565_64128n_HAL_init_seq);

@ -106,7 +106,7 @@ void clear_graphics_DRAM(u8g_t *u8g, u8g_dev_t *dev) {
} }
uint8_t u8g_dev_st7920_128x64_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { uint8_t u8g_dev_st7920_128x64_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) {
switch(msg) { switch (msg) {
case U8G_DEV_MSG_INIT: case U8G_DEV_MSG_INIT:
u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS); u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS);
u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7920_128x64_HAL_init_seq); u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7920_128x64_HAL_init_seq);
@ -149,7 +149,7 @@ uint8_t u8g_dev_st7920_128x64_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, vo
} }
uint8_t u8g_dev_st7920_128x64_HAL_4x_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { uint8_t u8g_dev_st7920_128x64_HAL_4x_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) {
switch(msg) { switch (msg) {
case U8G_DEV_MSG_INIT: case U8G_DEV_MSG_INIT:
u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS); u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_400NS);
u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7920_128x64_HAL_init_seq); u8g_WriteEscSeqP(u8g, dev, u8g_dev_st7920_128x64_HAL_init_seq);

@ -125,7 +125,7 @@ uint8_t u8g_dev_tft_320x240_upscale_from_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, u
uint16_t buffer[256]; uint16_t buffer[256];
uint32_t i, j, k; uint32_t i, j, k;
switch(msg) { switch (msg) {
case U8G_DEV_MSG_INIT: case U8G_DEV_MSG_INIT:
dev->com_fn(u8g, U8G_COM_MSG_INIT, U8G_SPI_CLK_CYCLE_NONE, &lcd_id); dev->com_fn(u8g, U8G_COM_MSG_INIT, U8G_SPI_CLK_CYCLE_NONE, &lcd_id);
if (lcd_id == 0x040404) return 0; // No connected display on FSMC if (lcd_id == 0x040404) return 0; // No connected display on FSMC

@ -109,7 +109,7 @@ static const uint8_t u8g_dev_uc1701_mini12864_HAL_data_start[] PROGMEM = {
}; };
uint8_t u8g_dev_uc1701_mini12864_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { uint8_t u8g_dev_uc1701_mini12864_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) {
switch(msg) { switch (msg) {
case U8G_DEV_MSG_INIT: case U8G_DEV_MSG_INIT:
u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS);
u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_init_seq); u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_init_seq);
@ -138,7 +138,7 @@ uint8_t u8g_dev_uc1701_mini12864_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg,
} }
uint8_t u8g_dev_uc1701_mini12864_HAL_2x_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { uint8_t u8g_dev_uc1701_mini12864_HAL_2x_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) {
switch(msg) { switch (msg) {
case U8G_DEV_MSG_INIT: case U8G_DEV_MSG_INIT:
u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS); u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS);
u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_init_seq); u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_init_seq);

@ -339,7 +339,7 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
#if ENABLED(SD_CHECK_AND_RETRY) #if ENABLED(SD_CHECK_AND_RETRY)
uint8_t retryCnt = 3; uint8_t retryCnt = 3;
for(;;) { for (;;) {
if (cardCommand(CMD17, blockNumber)) if (cardCommand(CMD17, blockNumber))
error(SD_CARD_ERROR_CMD17); error(SD_CARD_ERROR_CMD17);
else if (readData(dst, 512)) else if (readData(dst, 512))

File diff suppressed because it is too large Load Diff

@ -22,8 +22,9 @@
* Web : http://www.circuitsathome.com * Web : http://www.circuitsathome.com
* e-mail : support@circuitsathome.com * e-mail : support@circuitsathome.com
*/ */
#pragma once
/* USB functions */ /* USB functions */
#ifndef _usb_h_
#define _usb_h_ #define _usb_h_
#include "../../../inc/MarlinConfigPre.h" #include "../../../inc/MarlinConfigPre.h"
@ -50,4 +51,4 @@
#include "parsetools.h" #include "parsetools.h"
#include "confdescparser.h" #include "confdescparser.h"
#endif //_usb_h_ #undef _usb_h_

@ -231,8 +231,8 @@ public:
}; };
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) { uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) {
for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { for (uint8_t i = 0; i < USB_NUMDEVICES; i++) {
if(!devConfig[i]) { if (!devConfig[i]) {
devConfig[i] = pdev; devConfig[i] = pdev;
return 0; return 0;
} }

@ -22,13 +22,11 @@
* Web : http://www.circuitsathome.com * Web : http://www.circuitsathome.com
* e-mail : support@circuitsathome.com * e-mail : support@circuitsathome.com
*/ */
#pragma once
#if !defined(_usb_h_) || defined(__ADDRESS_H__) #ifndef _usb_h_
#error "Never include address.h directly; include Usb.h instead" #error "Never include address.h directly; include Usb.h instead"
#else #endif
#define __ADDRESS_H__
/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */ /* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */
/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */ /* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */
@ -38,18 +36,18 @@
#define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout #define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout
struct EpInfo { struct EpInfo {
uint8_t epAddr; // Endpoint address uint8_t epAddr; // Endpoint address
uint8_t maxPktSize; // Maximum packet size uint8_t maxPktSize; // Maximum packet size
union { union {
uint8_t epAttribs; uint8_t epAttribs;
struct { struct {
uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
} __attribute__((packed)); } __attribute__((packed));
}; };
} __attribute__((packed)); } __attribute__((packed));
// 7 6 5 4 3 2 1 0 // 7 6 5 4 3 2 1 0
@ -63,17 +61,15 @@ struct EpInfo {
// //
struct UsbDeviceAddress { struct UsbDeviceAddress {
union {
union { struct {
uint8_t bmAddress : 3; // device address/port number
struct { uint8_t bmParent : 3; // parent hub address
uint8_t bmAddress : 3; // device address/port number uint8_t bmHub : 1; // hub flag
uint8_t bmParent : 3; // parent hub address uint8_t bmReserved : 1; // reserved, must be zero
uint8_t bmHub : 1; // hub flag } __attribute__((packed));
uint8_t bmReserved : 1; // reserved, must be zero uint8_t devAddress;
} __attribute__((packed)); };
uint8_t devAddress;
};
} __attribute__((packed)); } __attribute__((packed));
#define bmUSB_DEV_ADDR_ADDRESS 0x07 #define bmUSB_DEV_ADDR_ADDRESS 0x07
@ -81,18 +77,18 @@ struct UsbDeviceAddress {
#define bmUSB_DEV_ADDR_HUB 0x40 #define bmUSB_DEV_ADDR_HUB 0x40
struct UsbDevice { struct UsbDevice {
EpInfo *epinfo; // endpoint info pointer EpInfo *epinfo; // endpoint info pointer
UsbDeviceAddress address; UsbDeviceAddress address;
uint8_t epcount; // number of endpoints uint8_t epcount; // number of endpoints
bool lowspeed; // indicates if a device is the low speed one bool lowspeed; // indicates if a device is the low speed one
// uint8_t devclass; // device class // uint8_t devclass; // device class
} __attribute__((packed)); } __attribute__((packed));
class AddressPool { class AddressPool {
public: public:
virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0; virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0;
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0; virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0;
virtual void FreeAddress(uint8_t addr) = 0; virtual void FreeAddress(uint8_t addr) = 0;
}; };
typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev); typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);
@ -102,190 +98,174 @@ typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);
template <const uint8_t MAX_DEVICES_ALLOWED> template <const uint8_t MAX_DEVICES_ALLOWED>
class AddressPoolImpl : public AddressPool { class AddressPoolImpl : public AddressPool {
EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device
uint8_t hubCounter; // hub counter is kept
// in order to avoid hub address duplication
uint8_t hubCounter; // hub counter is kept UsbDevice thePool[MAX_DEVICES_ALLOWED];
// in order to avoid hub address duplication
UsbDevice thePool[MAX_DEVICES_ALLOWED]; // Initialize address pool entry
// Initializes address pool entry void InitEntry(uint8_t index) {
thePool[index].address.devAddress = 0;
thePool[index].epcount = 1;
thePool[index].lowspeed = 0;
thePool[index].epinfo = &dev0ep;
}
void InitEntry(uint8_t index) { // Return thePool index for a given address
thePool[index].address.devAddress = 0;
thePool[index].epcount = 1;
thePool[index].lowspeed = 0;
thePool[index].epinfo = &dev0ep;
};
// Returns thePool index for a given address uint8_t FindAddressIndex(uint8_t address = 0) {
for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
if (thePool[i].address.devAddress == address)
return i;
uint8_t FindAddressIndex(uint8_t address = 0) { return 0;
for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) { }
if(thePool[i].address.devAddress == address)
return i;
}
return 0;
};
// Returns thePool child index for a given parent // Return thePool child index for a given parent
uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) { uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) {
for(uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) { for (uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) {
if(thePool[i].address.bmParent == addr.bmAddress) if (thePool[i].address.bmParent == addr.bmAddress)
return i; return i;
} }
return 0; return 0;
}; }
// Frees address entry specified by index parameter // Frees address entry specified by index parameter
void FreeAddressByIndex(uint8_t index) { void FreeAddressByIndex(uint8_t index) {
// Zero field is reserved and should not be affected // Zero field is reserved and should not be affected
if(index == 0) if (index == 0) return;
return;
UsbDeviceAddress uda = thePool[index].address; UsbDeviceAddress uda = thePool[index].address;
// If a hub was switched off all port addresses should be freed // If a hub was switched off all port addresses should be freed
if(uda.bmHub == 1) { if (uda.bmHub == 1) {
for(uint8_t i = 1; (i = FindChildIndex(uda, i));) for (uint8_t i = 1; (i = FindChildIndex(uda, i));)
FreeAddressByIndex(i); FreeAddressByIndex(i);
// If the hub had the last allocated address, hubCounter should be decremented // If the hub had the last allocated address, hubCounter should be decremented
if(hubCounter == uda.bmAddress) if (hubCounter == uda.bmAddress) hubCounter--;
hubCounter--; }
} InitEntry(index);
InitEntry(index); }
}
// Initializes the whole address pool at once // Initialize the whole address pool at once
void InitAllAddresses() { void InitAllAddresses() {
for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
InitEntry(i); InitEntry(i);
hubCounter = 0; hubCounter = 0;
}; }
public: public:
AddressPoolImpl() : hubCounter(0) { AddressPoolImpl() : hubCounter(0) {
// Zero address is reserved // Zero address is reserved
InitEntry(0); InitEntry(0);
thePool[0].address.devAddress = 0; thePool[0].address.devAddress = 0;
thePool[0].epinfo = &dev0ep; thePool[0].epinfo = &dev0ep;
dev0ep.epAddr = 0; dev0ep.epAddr = 0;
dev0ep.maxPktSize = 8; dev0ep.maxPktSize = 8;
dev0ep.bmSndToggle = 0; // Set DATA0/1 toggles to 0 dev0ep.bmSndToggle = 0; // Set DATA0/1 toggles to 0
dev0ep.bmRcvToggle = 0; dev0ep.bmRcvToggle = 0;
dev0ep.bmNakPower = USB_NAK_MAX_POWER; dev0ep.bmNakPower = USB_NAK_MAX_POWER;
InitAllAddresses(); InitAllAddresses();
}; }
// Returns a pointer to a specified address entry // Return a pointer to a specified address entry
virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) { virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) {
if(!addr) if (!addr) return thePool;
return thePool; uint8_t index = FindAddressIndex(addr);
return index ? thePool + index : NULL;
uint8_t index = FindAddressIndex(addr); }
return (!index) ? NULL : thePool + index; // Perform an operation specified by pfunc for each addressed device
};
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
// Performs an operation specified by pfunc for each addressed device if (pfunc) {
for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { if (thePool[i].address.devAddress)
if(!pfunc) pfunc(thePool + i);
return; }
}
for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
if(thePool[i].address.devAddress) // Allocate new address
pfunc(thePool + i);
}; virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) {
/* if (parent != 0 && port == 0)
// Allocates new address USB_HOST_SERIAL.println("PRT:0"); */
UsbDeviceAddress _parent;
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) { _parent.devAddress = parent;
/* if (parent != 0 && port == 0) if (_parent.bmReserved || port > 7)
USB_HOST_SERIAL.println("PRT:0"); */ //if(parent > 127 || port > 7)
UsbDeviceAddress _parent; return 0;
_parent.devAddress = parent;
if(_parent.bmReserved || port > 7) if (is_hub && hubCounter == 7) return 0;
//if(parent > 127 || port > 7)
return 0; // finds first empty address entry starting from one
uint8_t index = FindAddressIndex(0);
if(is_hub && hubCounter == 7)
return 0; if (!index) return 0; // if empty entry is not found
// finds first empty address entry starting from one if (_parent.devAddress == 0) {
uint8_t index = FindAddressIndex(0); if (is_hub) {
thePool[index].address.devAddress = 0x41;
if(!index) // if empty entry is not found hubCounter++;
return 0; }
else
if(_parent.devAddress == 0) { thePool[index].address.devAddress = 1;
if(is_hub) {
thePool[index].address.devAddress = 0x41; return thePool[index].address.devAddress;
hubCounter++; }
} else
thePool[index].address.devAddress = 1; UsbDeviceAddress addr;
addr.devAddress = 0; // Ensure all bits are zero
return thePool[index].address.devAddress; addr.bmParent = _parent.bmAddress;
} if (is_hub) {
addr.bmHub = 1;
UsbDeviceAddress addr; addr.bmAddress = ++hubCounter;
addr.devAddress = 0; // Ensure all bits are zero }
addr.bmParent = _parent.bmAddress; else {
if(is_hub) { addr.bmHub = 0;
addr.bmHub = 1; addr.bmAddress = port;
addr.bmAddress = ++hubCounter; }
} else { thePool[index].address = addr;
addr.bmHub = 0; /*
addr.bmAddress = port; USB_HOST_SERIAL.print("Addr:");
} USB_HOST_SERIAL.print(addr.bmHub, HEX);
thePool[index].address = addr; USB_HOST_SERIAL.print(".");
/* USB_HOST_SERIAL.print(addr.bmParent, HEX);
USB_HOST_SERIAL.print("Addr:"); USB_HOST_SERIAL.print(".");
USB_HOST_SERIAL.print(addr.bmHub, HEX); USB_HOST_SERIAL.println(addr.bmAddress, HEX);
USB_HOST_SERIAL.print("."); */
USB_HOST_SERIAL.print(addr.bmParent, HEX); return thePool[index].address.devAddress;
USB_HOST_SERIAL.print("."); }
USB_HOST_SERIAL.println(addr.bmAddress, HEX);
*/ // Empty the pool entry
return thePool[index].address.devAddress;
}; virtual void FreeAddress(uint8_t addr) {
// if the root hub is disconnected all the addresses should be initialized
// Empties pool entry if (addr == 0x41) {
InitAllAddresses();
virtual void FreeAddress(uint8_t addr) { return;
// if the root hub is disconnected all the addresses should be initialized }
if(addr == 0x41) { FreeAddressByIndex(FindAddressIndex(addr));
InitAllAddresses(); }
return;
} // Return number of hubs attached
uint8_t index = FindAddressIndex(addr); // It can be helpful to find out if hubs are attached when getting the exact number of hubs.
FreeAddressByIndex(index); //uint8_t GetNumHubs() { return hubCounter; }
}; //uint8_t GetNumDevices() {
// uint8_t counter = 0;
// Returns number of hubs attached // for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
// It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs. // if (thePool[i].address != 0); counter++;
//uint8_t GetNumHubs() // return counter;
//{ //}
// return hubCounter;
//};
//uint8_t GetNumDevices()
//{
// uint8_t counter = 0;
// for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
// if (thePool[i].address != 0);
// counter ++;
// return counter;
//};
}; };
#endif // __ADDRESS_H__

@ -22,197 +22,180 @@
* Web : http://www.circuitsathome.com * Web : http://www.circuitsathome.com
* e-mail : support@circuitsathome.com * e-mail : support@circuitsathome.com
*/ */
#if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__) #pragma once
#error "Never include confdescparser.h directly; include Usb.h instead"
#else
#define __CONFDESCPARSER_H__ #ifndef _usb_h_
#error "Never include confdescparser.h directly; include Usb.h instead"
#endif
class UsbConfigXtracter { class UsbConfigXtracter {
public: public:
//virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0; //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;
//virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0; //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0;
virtual void EndpointXtract(uint8_t conf __attribute__((unused)), uint8_t iface __attribute__((unused)), uint8_t alt __attribute__((unused)), uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *ep __attribute__((unused))) { virtual void EndpointXtract(uint8_t conf __attribute__((unused)), uint8_t iface __attribute__((unused)), uint8_t alt __attribute__((unused)), uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *ep __attribute__((unused))) {
}; }
}; };
#define CP_MASK_COMPARE_CLASS 1 #define CP_MASK_COMPARE_CLASS 1
#define CP_MASK_COMPARE_SUBCLASS 2 #define CP_MASK_COMPARE_SUBCLASS 2
#define CP_MASK_COMPARE_PROTOCOL 4 #define CP_MASK_COMPARE_PROTOCOL 4
#define CP_MASK_COMPARE_ALL 7 #define CP_MASK_COMPARE_ALL 7
// Configuration Descriptor Parser Class Template // Configuration Descriptor Parser Class Template
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
class ConfigDescParser : public USBReadParser { class ConfigDescParser : public USBReadParser {
UsbConfigXtracter *theXtractor; UsbConfigXtracter *theXtractor;
MultiValueBuffer theBuffer; MultiValueBuffer theBuffer;
MultiByteValueParser valParser; MultiByteValueParser valParser;
ByteSkipper theSkipper; ByteSkipper theSkipper;
uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/]; uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/];
uint8_t stateParseDescr; // ParseDescriptor state uint8_t stateParseDescr; // ParseDescriptor state
uint8_t dscrLen; // Descriptor length uint8_t dscrLen; // Descriptor length
uint8_t dscrType; // Descriptor type uint8_t dscrType; // Descriptor type
bool isGoodInterface; // Apropriate interface flag bool isGoodInterface; // Apropriate interface flag
uint8_t confValue; // Configuration value uint8_t confValue; // Configuration value
uint8_t protoValue; // Protocol value uint8_t protoValue; // Protocol value
uint8_t ifaceNumber; // Interface number uint8_t ifaceNumber; // Interface number
uint8_t ifaceAltSet; // Interface alternate settings uint8_t ifaceAltSet; // Interface alternate settings
bool UseOr; bool UseOr;
bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn);
void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
public: public:
void SetOR(void) { void SetOR(void) { UseOr = true; }
UseOr = true; ConfigDescParser(UsbConfigXtracter *xtractor);
} void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
ConfigDescParser(UsbConfigXtracter *xtractor);
void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
}; };
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) : ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :
theXtractor(xtractor), theXtractor(xtractor),
stateParseDescr(0), stateParseDescr(0),
dscrLen(0), dscrLen(0),
dscrType(0), dscrType(0),
UseOr(false) { UseOr(false) {
theBuffer.pValue = varBuffer; theBuffer.pValue = varBuffer;
valParser.Initialize(&theBuffer); valParser.Initialize(&theBuffer);
theSkipper.Initialize(&theBuffer); theSkipper.Initialize(&theBuffer);
}; };
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset __attribute__((unused))) { void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset __attribute__((unused))) {
uint16_t cntdn = (uint16_t)len; uint16_t cntdn = (uint16_t)len;
uint8_t *p = (uint8_t*)pbuf; uint8_t *p = (uint8_t*)pbuf;
while (cntdn) if (!ParseDescriptor(&p, &cntdn)) return;
while(cntdn)
if(!ParseDescriptor(&p, &cntdn))
return;
} }
/* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and /* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and
compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */ compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) { bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) {
USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer); USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer); USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);
switch(stateParseDescr) { switch (stateParseDescr) {
case 0: case 0:
theBuffer.valueSize = 2; theBuffer.valueSize = 2;
valParser.Initialize(&theBuffer); valParser.Initialize(&theBuffer);
stateParseDescr = 1; stateParseDescr = 1;
case 1: case 1:
if(!valParser.Parse(pp, pcntdn)) if (!valParser.Parse(pp, pcntdn)) return false;
return false; dscrLen = *((uint8_t*)theBuffer.pValue);
dscrLen = *((uint8_t*)theBuffer.pValue); dscrType = *((uint8_t*)theBuffer.pValue + 1);
dscrType = *((uint8_t*)theBuffer.pValue + 1); stateParseDescr = 2;
stateParseDescr = 2; case 2:
case 2: // This is a sort of hack. Assuming that two bytes are all ready in the buffer
// This is a sort of hack. Assuming that two bytes are all ready in the buffer // the pointer is positioned two bytes ahead in order for the rest of descriptor
// the pointer is positioned two bytes ahead in order for the rest of descriptor // to be read right after the size and the type fields.
// to be read right after the size and the type fields. // This should be used carefully. varBuffer should be used directly to handle data
// This should be used carefully. varBuffer should be used directly to handle data // in the buffer.
// in the buffer. theBuffer.pValue = varBuffer + 2;
theBuffer.pValue = varBuffer + 2; stateParseDescr = 3;
stateParseDescr = 3; case 3:
case 3: switch (dscrType) {
switch(dscrType) { case USB_DESCRIPTOR_INTERFACE:
case USB_DESCRIPTOR_INTERFACE: isGoodInterface = false;
isGoodInterface = false; break;
break; case USB_DESCRIPTOR_CONFIGURATION:
case USB_DESCRIPTOR_CONFIGURATION: case USB_DESCRIPTOR_ENDPOINT:
case USB_DESCRIPTOR_ENDPOINT: case HID_DESCRIPTOR_HID:
case HID_DESCRIPTOR_HID: break;
break; }
} theBuffer.valueSize = dscrLen - 2;
theBuffer.valueSize = dscrLen - 2; valParser.Initialize(&theBuffer);
valParser.Initialize(&theBuffer); stateParseDescr = 4;
stateParseDescr = 4; case 4:
case 4: switch (dscrType) {
switch(dscrType) { case USB_DESCRIPTOR_CONFIGURATION:
case USB_DESCRIPTOR_CONFIGURATION: if (!valParser.Parse(pp, pcntdn)) return false;
if(!valParser.Parse(pp, pcntdn)) confValue = ucd->bConfigurationValue;
return false; break;
confValue = ucd->bConfigurationValue; case USB_DESCRIPTOR_INTERFACE:
break; if (!valParser.Parse(pp, pcntdn)) return false;
case USB_DESCRIPTOR_INTERFACE: if ((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)
if(!valParser.Parse(pp, pcntdn)) break;
return false; if ((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID)
if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID) break;
break; if (UseOr) {
if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID) if ((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol))) break;
break; }
if(UseOr) { else if ((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)
if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol))) break;
break; isGoodInterface = true;
} else { ifaceNumber = uid->bInterfaceNumber;
if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID) ifaceAltSet = uid->bAlternateSetting;
break; protoValue = uid->bInterfaceProtocol;
} break;
isGoodInterface = true; case USB_DESCRIPTOR_ENDPOINT:
ifaceNumber = uid->bInterfaceNumber; if (!valParser.Parse(pp, pcntdn)) return false;
ifaceAltSet = uid->bAlternateSetting; if (isGoodInterface && theXtractor)
protoValue = uid->bInterfaceProtocol; theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
break; break;
case USB_DESCRIPTOR_ENDPOINT: //case HID_DESCRIPTOR_HID:
if(!valParser.Parse(pp, pcntdn)) // if (!valParser.Parse(pp, pcntdn)) return false;
return false; // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
if(isGoodInterface) // break;
if(theXtractor) default:
theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer); if (!theSkipper.Skip(pp, pcntdn, dscrLen - 2)) return false;
break; }
//case HID_DESCRIPTOR_HID: theBuffer.pValue = varBuffer;
// if (!valParser.Parse(pp, pcntdn)) stateParseDescr = 0;
// return false; }
// PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); return true;
// break;
default:
if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2))
return false;
}
theBuffer.pValue = varBuffer;
stateParseDescr = 0;
}
return true;
} }
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) { void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {
Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80); Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
Notify(PSTR("bDescLength:\t\t"), 0x80); Notify(PSTR("bDescLength:\t\t"), 0x80);
PrintHex<uint8_t > (pDesc->bLength, 0x80); PrintHex<uint8_t > (pDesc->bLength, 0x80);
Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80); PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
PrintHex<uint16_t > (pDesc->bcdHID, 0x80); PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
PrintHex<uint8_t > (pDesc->bCountryCode, 0x80); PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80); PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) { for (uint8_t i = 0; i < pDesc->bNumDescriptors; i++) {
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType); HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
PrintHex<uint8_t > (pLT[i].bDescrType, 0x80); PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);
Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80); PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);
} }
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
} }
#endif // __CONFDESCPARSER_H__

@ -22,49 +22,47 @@
* Web : http://www.circuitsathome.com * Web : http://www.circuitsathome.com
* e-mail : support@circuitsathome.com * e-mail : support@circuitsathome.com
*/ */
#pragma once
#if !defined(_usb_h_) || defined(__HEXDUMP_H__) #ifndef _usb_h_
#error "Never include hexdump.h directly; include Usb.h instead" #error "Never include hexdump.h directly; include Usb.h instead"
#else #endif
#define __HEXDUMP_H__
extern int UsbDEBUGlvl; extern int UsbDEBUGlvl;
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE> template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
class HexDumper : public BASE_CLASS { class HexDumper : public BASE_CLASS {
uint8_t byteCount; uint8_t byteCount;
OFFSET_TYPE byteTotal; OFFSET_TYPE byteTotal;
public: public:
HexDumper() : byteCount(0), byteTotal(0) { HexDumper() : byteCount(0), byteTotal(0) {
}; };
void Initialize() { void Initialize() {
byteCount = 0; byteCount = 0;
byteTotal = 0; byteTotal = 0;
}; };
void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset); void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset);
}; };
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE> template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset __attribute__((unused))) { void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset __attribute__((unused))) {
if(UsbDEBUGlvl >= 0x80) { // Fully bypass this block of code if we do not debug. if (UsbDEBUGlvl >= 0x80) { // Fully bypass this block of code if we do not debug.
for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) { for (LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) {
if(!byteCount) { if (!byteCount) {
PrintHex<OFFSET_TYPE > (byteTotal, 0x80); PrintHex<OFFSET_TYPE > (byteTotal, 0x80);
E_Notify(PSTR(": "), 0x80); E_Notify(PSTR(": "), 0x80);
} }
PrintHex<uint8_t > (pbuf[j], 0x80); PrintHex<uint8_t > (pbuf[j], 0x80);
E_Notify(PSTR(" "), 0x80); E_Notify(PSTR(" "), 0x80);
if(byteCount == 15) { if (byteCount == 15) {
E_Notify(PSTR("\r\n"), 0x80); E_Notify(PSTR("\r\n"), 0x80);
byteCount = 0xFF; byteCount = 0xFF;
} }
} }
} }
} }
#endif // __HEXDUMP_H__

@ -22,13 +22,12 @@
* Web : http://www.circuitsathome.com * Web : http://www.circuitsathome.com
* e-mail : support@circuitsathome.com * e-mail : support@circuitsathome.com
*/ */
#pragma once
#ifndef _usb_h_ #ifndef _usb_h_
#error "Never include macros.h directly; include Usb.h instead" #error "Never include macros.h directly; include Usb.h instead"
#endif #endif
#pragma once
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// HANDY MACROS // HANDY MACROS
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -36,7 +35,7 @@
#define VALUE_BETWEEN(v,l,h) (((v)>(l)) && ((v)<(h))) #define VALUE_BETWEEN(v,l,h) (((v)>(l)) && ((v)<(h)))
#define VALUE_WITHIN(v,l,h) (((v)>=(l)) && ((v)<=(h))) #define VALUE_WITHIN(v,l,h) (((v)>=(l)) && ((v)<=(h)))
#define output_pgm_message(wa,fp,mp,el) wa = &mp, fp((char *)pgm_read_pointer(wa), el) #define output_pgm_message(wa,fp,mp,el) wa = &mp, fp((char *)pgm_read_pointer(wa), el)
#define output_if_between(v,l,h,wa,fp,mp,el) if(VALUE_BETWEEN(v,l,h)) output_pgm_message(wa,fp,mp[v-(l+1)],el); #define output_if_between(v,l,h,wa,fp,mp,el) if (VALUE_BETWEEN(v,l,h)) output_pgm_message(wa,fp,mp[v-(l+1)],el);
#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) #define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
#ifndef __BYTE_GRABBING_DEFINED__ #ifndef __BYTE_GRABBING_DEFINED__

File diff suppressed because it is too large Load Diff

@ -408,7 +408,7 @@ public:
CommandBlockWrapper() : CommandBlockWrapper() :
CommandBlockWrapperBase(0, 0, 0), bmReserved1(0), bmReserved2(0) { CommandBlockWrapperBase(0, 0, 0), bmReserved1(0), bmReserved2(0) {
for(int i = 0; i < 16; i++) CBWCB[i] = 0; for (int i = 0; i < 16; i++) CBWCB[i] = 0;
} }
// Generic Wrap, CDB zeroed. // Generic Wrap, CDB zeroed.
@ -416,7 +416,7 @@ public:
CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) : CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) :
CommandBlockWrapperBase(tag, xflen, flgs), CommandBlockWrapperBase(tag, xflen, flgs),
bmCBWLUN(lu), bmReserved1(0), bmCBWCBLength(cmdlen), bmReserved2(0) { bmCBWLUN(lu), bmReserved1(0), bmCBWCBLength(cmdlen), bmReserved2(0) {
for(int i = 0; i < 16; i++) CBWCB[i] = 0; for (int i = 0; i < 16; i++) CBWCB[i] = 0;
// Type punning can cause optimization problems and bugs. // Type punning can cause optimization problems and bugs.
// Using reinterpret_cast to a dreinterpretifferent object is the proper way to do this. // Using reinterpret_cast to a dreinterpretifferent object is the proper way to do this.
//(((BASICCDB_t *) CBWCB)->LUN) = cmd; //(((BASICCDB_t *) CBWCB)->LUN) = cmd;
@ -493,27 +493,17 @@ protected:
bool WriteOk[MASS_MAX_SUPPORTED_LUN]; bool WriteOk[MASS_MAX_SUPPORTED_LUN];
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
// Additional Initialization Method for Subclasses // Additional Initialization Method for Subclasses
virtual uint8_t OnInit() { virtual uint8_t OnInit() { return 0; }
return 0;
};
public: public:
BulkOnly(USB *p); BulkOnly(USB *p);
uint8_t GetLastUsbError() { uint8_t GetLastUsbError() { return bLastUsbError; };
return bLastUsbError;
};
uint8_t GetbMaxLUN() { uint8_t GetbMaxLUN() { return bMaxLUN; } // Max LUN
return bMaxLUN; // Max LUN uint8_t GetbTheLUN() { return bTheLUN; } // Active LUN
}
uint8_t GetbTheLUN() {
return bTheLUN; // Active LUN
}
bool WriteProtected(uint8_t lun); bool WriteProtected(uint8_t lun);
uint8_t MediaCTL(uint8_t lun, uint8_t ctl); uint8_t MediaCTL(uint8_t lun, uint8_t ctl);
@ -533,16 +523,12 @@ public:
uint8_t Release(); uint8_t Release();
uint8_t Poll(); uint8_t Poll();
virtual uint8_t GetAddress() { virtual uint8_t GetAddress() { return bAddress; }
return bAddress;
};
// UsbConfigXtracter implementation // UsbConfigXtracter implementation
void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
virtual bool DEVCLASSOK(uint8_t klass) { virtual bool DEVCLASSOK(uint8_t klass) { return klass == USB_CLASS_MASS_STORAGE; }
return (klass == USB_CLASS_MASS_STORAGE);
}
uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);
uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir); uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);
@ -573,5 +559,4 @@ private:
uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf); uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf);
uint8_t HandleUsbError(uint8_t error, uint8_t index); uint8_t HandleUsbError(uint8_t error, uint8_t index);
uint8_t HandleSCSIError(uint8_t status); uint8_t HandleSCSIError(uint8_t status);
}; };

@ -22,11 +22,11 @@
* Web : http://www.circuitsathome.com * Web : http://www.circuitsathome.com
* e-mail : support@circuitsathome.com * e-mail : support@circuitsathome.com
*/ */
#if !defined(_usb_h_) || defined(_max3421e_h_) #pragma once
#error "Never include max3421e.h directly; include Usb.h instead"
#else
#define _max3421e_h_ #ifndef _usb_h_
#error "Never include max3421e.h directly; include Usb.h instead"
#endif
/* MAX3421E register/bit names and bitmasks */ /* MAX3421E register/bit names and bitmasks */
@ -231,6 +231,3 @@
#define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB) #define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB)
#define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB) #define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB)
#endif //_max3421e_h_

@ -35,97 +35,94 @@
int UsbDEBUGlvl = 0x80; int UsbDEBUGlvl = 0x80;
void E_Notifyc(char c, int lvl) { void E_Notifyc(char c, int lvl) {
if(UsbDEBUGlvl < lvl) return; if (UsbDEBUGlvl < lvl) return;
#if defined(ARDUINO) && ARDUINO >=100 USB_HOST_SERIAL.print(c
USB_HOST_SERIAL.print(c); #if !defined(ARDUINO) || ARDUINO < 100
#else , BYTE
USB_HOST_SERIAL.print(c, BYTE); #endif
#endif );
//USB_HOST_SERIAL.flush(); //USB_HOST_SERIAL.flush();
} }
void E_Notify(char const * msg, int lvl) { void E_Notify(char const * msg, int lvl) {
if(UsbDEBUGlvl < lvl) return; if (UsbDEBUGlvl < lvl) return;
if(!msg) return; if (!msg) return;
char c; while (const char c = pgm_read_byte(msg++)) E_Notifyc(c, lvl);
while((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl);
} }
void E_NotifyStr(char const * msg, int lvl) { void E_NotifyStr(char const * msg, int lvl) {
if(UsbDEBUGlvl < lvl) return; if (UsbDEBUGlvl < lvl) return;
if(!msg) return; if (!msg) return;
char c; while (const char c = *msg++) E_Notifyc(c, lvl);
while((c = *msg++)) E_Notifyc(c, lvl);
} }
void E_Notify(uint8_t b, int lvl) { void E_Notify(uint8_t b, int lvl) {
if(UsbDEBUGlvl < lvl) return; if (UsbDEBUGlvl < lvl) return;
#if defined(ARDUINO) && ARDUINO >=100 USB_HOST_SERIAL.print(b
USB_HOST_SERIAL.print(b); #if !defined(ARDUINO) || ARDUINO < 100
#else , DEC
USB_HOST_SERIAL.print(b, DEC); #endif
#endif );
//USB_HOST_SERIAL.flush(); //USB_HOST_SERIAL.flush();
} }
void E_Notify(double d, int lvl) { void E_Notify(double d, int lvl) {
if(UsbDEBUGlvl < lvl) return; if (UsbDEBUGlvl < lvl) return;
USB_HOST_SERIAL.print(d); USB_HOST_SERIAL.print(d);
//USB_HOST_SERIAL.flush(); //USB_HOST_SERIAL.flush();
} }
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
void NotifyFailGetDevDescr(void) { void NotifyFailGetDevDescr(void) {
Notify(PSTR("\r\ngetDevDescr "), 0x80); Notify(PSTR("\r\ngetDevDescr "), 0x80);
} }
void NotifyFailSetDevTblEntry(void) { void NotifyFailSetDevTblEntry(void) {
Notify(PSTR("\r\nsetDevTblEn "), 0x80); Notify(PSTR("\r\nsetDevTblEn "), 0x80);
} }
void NotifyFailGetConfDescr(void) { void NotifyFailGetConfDescr(void) {
Notify(PSTR("\r\ngetConf "), 0x80); Notify(PSTR("\r\ngetConf "), 0x80);
} }
void NotifyFailSetConfDescr(void) { void NotifyFailSetConfDescr(void) {
Notify(PSTR("\r\nsetConf "), 0x80); Notify(PSTR("\r\nsetConf "), 0x80);
} }
void NotifyFailGetDevDescr(uint8_t reason) { void NotifyFailGetDevDescr(uint8_t reason) {
NotifyFailGetDevDescr(); NotifyFailGetDevDescr();
NotifyFail(reason); NotifyFail(reason);
} }
void NotifyFailSetDevTblEntry(uint8_t reason) { void NotifyFailSetDevTblEntry(uint8_t reason) {
NotifyFailSetDevTblEntry(); NotifyFailSetDevTblEntry();
NotifyFail(reason); NotifyFail(reason);
} }
void NotifyFailGetConfDescr(uint8_t reason) { void NotifyFailGetConfDescr(uint8_t reason) {
NotifyFailGetConfDescr(); NotifyFailGetConfDescr();
NotifyFail(reason); NotifyFail(reason);
} }
void NotifyFailSetConfDescr(uint8_t reason) { void NotifyFailSetConfDescr(uint8_t reason) {
NotifyFailSetConfDescr(); NotifyFailSetConfDescr();
NotifyFail(reason); NotifyFail(reason);
} }
void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) { void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) {
Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80);
D_PrintHex<uint16_t > (VID, 0x80); D_PrintHex<uint16_t > (VID, 0x80);
Notify(PSTR(" PID: "), 0x80); Notify(PSTR(" PID: "), 0x80);
D_PrintHex<uint16_t > (PID, 0x80); D_PrintHex<uint16_t > (PID, 0x80);
} }
void NotifyFail(uint8_t rcode) {
D_PrintHex<uint8_t > (rcode, 0x80);
Notify(PSTR("\r\n"), 0x80);
}
void NotifyFail(uint8_t rcode) {
D_PrintHex<uint8_t > (rcode, 0x80);
Notify(PSTR("\r\n"), 0x80);
}
#endif // DEBUG_USB_HOST #endif // DEBUG_USB_HOST
#endif // USB_FLASH_DRIVE_SUPPORT #endif // USB_FLASH_DRIVE_SUPPORT

@ -22,10 +22,11 @@
* Web : http://www.circuitsathome.com * Web : http://www.circuitsathome.com
* e-mail : support@circuitsathome.com * e-mail : support@circuitsathome.com
*/ */
#if !defined(_usb_h_) || defined(__MESSAGE_H__) #pragma once
#error "Never include message.h directly; include Usb.h instead"
#else #ifndef _usb_h_
#define __MESSAGE_H__ #error "Never include message.h directly; include Usb.h instead"
#endif
extern int UsbDEBUGlvl; extern int UsbDEBUGlvl;
@ -35,52 +36,50 @@ void E_NotifyStr(char const * msg, int lvl);
void E_Notifyc(char c, int lvl); void E_Notifyc(char c, int lvl);
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
#define Notify E_Notify #define Notify E_Notify
#define NotifyStr E_NotifyStr #define NotifyStr E_NotifyStr
#define Notifyc E_Notifyc #define Notifyc E_Notifyc
void NotifyFailGetDevDescr(uint8_t reason); void NotifyFailGetDevDescr(uint8_t reason);
void NotifyFailSetDevTblEntry(uint8_t reason); void NotifyFailSetDevTblEntry(uint8_t reason);
void NotifyFailGetConfDescr(uint8_t reason); void NotifyFailGetConfDescr(uint8_t reason);
void NotifyFailSetConfDescr(uint8_t reason); void NotifyFailSetConfDescr(uint8_t reason);
void NotifyFailGetDevDescr(void); void NotifyFailGetDevDescr(void);
void NotifyFailSetDevTblEntry(void); void NotifyFailSetDevTblEntry(void);
void NotifyFailGetConfDescr(void); void NotifyFailGetConfDescr(void);
void NotifyFailSetConfDescr(void); void NotifyFailSetConfDescr(void);
void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID); void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID);
void NotifyFail(uint8_t rcode); void NotifyFail(uint8_t rcode);
#else #else
#define Notify(...) ((void)0) #define Notify(...) ((void)0)
#define NotifyStr(...) ((void)0) #define NotifyStr(...) ((void)0)
#define Notifyc(...) ((void)0) #define Notifyc(...) ((void)0)
#define NotifyFailGetDevDescr(...) ((void)0) #define NotifyFailGetDevDescr(...) ((void)0)
#define NotifyFailSetDevTblEntry(...) ((void)0) #define NotifyFailSetDevTblEntry(...) ((void)0)
#define NotifyFailGetConfDescr(...) ((void)0) #define NotifyFailGetConfDescr(...) ((void)0)
#define NotifyFailGetDevDescr(...) ((void)0) #define NotifyFailGetDevDescr(...) ((void)0)
#define NotifyFailSetDevTblEntry(...) ((void)0) #define NotifyFailSetDevTblEntry(...) ((void)0)
#define NotifyFailGetConfDescr(...) ((void)0) #define NotifyFailGetConfDescr(...) ((void)0)
#define NotifyFailSetConfDescr(...) ((void)0) #define NotifyFailSetConfDescr(...) ((void)0)
#define NotifyFailUnknownDevice(...) ((void)0) #define NotifyFailUnknownDevice(...) ((void)0)
#define NotifyFail(...) ((void)0) #define NotifyFail(...) ((void)0)
#endif #endif
template <class ERROR_TYPE> template <class ERROR_TYPE>
void ErrorMessage(uint8_t level, char const * msg, ERROR_TYPE rcode = 0) { void ErrorMessage(uint8_t level, char const * msg, ERROR_TYPE rcode = 0) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(msg, level); Notify(msg, level);
Notify(PSTR(": "), level); Notify(PSTR(": "), level);
D_PrintHex<ERROR_TYPE > (rcode, level); D_PrintHex<ERROR_TYPE > (rcode, level);
Notify(PSTR("\r\n"), level); Notify(PSTR("\r\n"), level);
#endif #endif
} }
template <class ERROR_TYPE> template <class ERROR_TYPE>
void ErrorMessage(char const * msg __attribute__((unused)), ERROR_TYPE rcode __attribute__((unused)) = 0) { void ErrorMessage(char const * msg __attribute__((unused)), ERROR_TYPE rcode __attribute__((unused)) = 0) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(msg, 0x80); Notify(msg, 0x80);
Notify(PSTR(": "), 0x80); Notify(PSTR(": "), 0x80);
D_PrintHex<ERROR_TYPE > (rcode, 0x80); D_PrintHex<ERROR_TYPE > (rcode, 0x80);
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
#endif #endif
} }
#endif // __MESSAGE_H__

@ -30,53 +30,48 @@
#include "Usb.h" #include "Usb.h"
bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) { bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) {
if(!pBuf) { if (!pBuf) {
Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80); Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80);
return false; return false;
} }
for(; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++) for (; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++)
pBuf[valueSize - countDown] = (**pp); pBuf[valueSize - countDown] = (**pp);
if(countDown) if (countDown) return false;
return false;
countDown = valueSize; countDown = valueSize;
return true; return true;
} }
bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) { bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) {
switch(nStage) { switch (nStage) {
case 0: case 0:
pBuf->valueSize = lenSize; pBuf->valueSize = lenSize;
theParser.Initialize(pBuf); theParser.Initialize(pBuf);
nStage = 1; nStage = 1;
case 1: case 1:
if(!theParser.Parse(pp, pcntdn)) if (!theParser.Parse(pp, pcntdn)) return false;
return false;
arLen = 0; arLen = 0;
arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue)); arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue));
arLenCntdn = arLen; arLenCntdn = arLen;
nStage = 2; nStage = 2;
case 2: case 2:
pBuf->valueSize = valSize; pBuf->valueSize = valSize;
theParser.Initialize(pBuf); theParser.Initialize(pBuf);
nStage = 3; nStage = 3;
case 3: case 3:
for(; arLenCntdn; arLenCntdn--) { for (; arLenCntdn; arLenCntdn--) {
if(!theParser.Parse(pp, pcntdn)) if (!theParser.Parse(pp, pcntdn)) return false;
return false; if (pf) pf(pBuf, (arLen - arLenCntdn), me);
}
if(pf) nStage = 0;
pf(pBuf, (arLen - arLenCntdn), me); }
} return true;
nStage = 0;
}
return true;
} }
#endif // USB_FLASH_DRIVE_SUPPORT #endif // USB_FLASH_DRIVE_SUPPORT

@ -22,67 +22,65 @@
* Web : http://www.circuitsathome.com * Web : http://www.circuitsathome.com
* e-mail : support@circuitsathome.com * e-mail : support@circuitsathome.com
*/ */
#pragma once
#if !defined(_usb_h_) || defined(__PARSETOOLS_H__) #ifndef _usb_h_
#error "Never include parsetools.h directly; include Usb.h instead" #error "Never include parsetools.h directly; include Usb.h instead"
#else #endif
#define __PARSETOOLS_H__
struct MultiValueBuffer { struct MultiValueBuffer {
uint8_t valueSize; uint8_t valueSize;
void *pValue; void *pValue;
} __attribute__((packed)); } __attribute__((packed));
class MultiByteValueParser { class MultiByteValueParser {
uint8_t * pBuf; uint8_t * pBuf;
uint8_t countDown; uint8_t countDown;
uint8_t valueSize; uint8_t valueSize;
public: public:
MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) { MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {
}; };
const uint8_t* GetBuffer() { const uint8_t* GetBuffer() { return pBuf; }
return pBuf;
};
void Initialize(MultiValueBuffer * const pbuf) { void Initialize(MultiValueBuffer * const pbuf) {
pBuf = (uint8_t*)pbuf->pValue; pBuf = (uint8_t*)pbuf->pValue;
countDown = valueSize = pbuf->valueSize; countDown = valueSize = pbuf->valueSize;
}; }
bool Parse(uint8_t **pp, uint16_t *pcntdn); bool Parse(uint8_t **pp, uint16_t *pcntdn);
}; };
class ByteSkipper { class ByteSkipper {
uint8_t *pBuf; uint8_t *pBuf;
uint8_t nStage; uint8_t nStage;
uint16_t countDown; uint16_t countDown;
public: public:
ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) { ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {
}; }
void Initialize(MultiValueBuffer *pbuf) { void Initialize(MultiValueBuffer *pbuf) {
pBuf = (uint8_t*)pbuf->pValue; pBuf = (uint8_t*)pbuf->pValue;
countDown = 0; countDown = 0;
}; }
bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) { bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) {
switch(nStage) { switch (nStage) {
case 0: case 0:
countDown = bytes_to_skip; countDown = bytes_to_skip;
nStage++; nStage++;
case 1: case 1:
for(; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--); for (; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--);
if(!countDown) if (!countDown)
nStage = 0; nStage = 0;
}; }
return (!countDown); return (!countDown);
}; }
}; };
// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser // Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser
@ -91,58 +89,57 @@ typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t cou
class PTPListParser { class PTPListParser {
public: public:
enum ParseMode { enum ParseMode {
modeArray, modeRange/*, modeEnum*/ modeArray, modeRange/*, modeEnum*/
}; };
private: private:
uint8_t nStage; uint8_t nStage;
uint8_t enStage; uint8_t enStage;
uint32_t arLen; uint32_t arLen;
uint32_t arLenCntdn; uint32_t arLenCntdn;
uint8_t lenSize; // size of the array length field in bytes uint8_t lenSize; // size of the array length field in bytes
uint8_t valSize; // size of the array element in bytes uint8_t valSize; // size of the array element in bytes
MultiValueBuffer *pBuf; MultiValueBuffer *pBuf;
// The only parser for both size and array element parsing // The only parser for both size and array element parsing
MultiByteValueParser theParser; MultiByteValueParser theParser;
uint8_t /*ParseMode*/ prsMode; uint8_t /*ParseMode*/ prsMode;
public: public:
PTPListParser() : PTPListParser() :
nStage(0), nStage(0),
enStage(0), enStage(0),
arLen(0), arLen(0),
arLenCntdn(0), arLenCntdn(0),
lenSize(0), lenSize(0),
valSize(0), valSize(0),
pBuf(NULL), pBuf(NULL),
prsMode(modeArray) { prsMode(modeArray) { }
}; ;
void Initialize(const uint8_t len_size, const uint8_t val_size, MultiValueBuffer * const p, const uint8_t mode = modeArray) { void Initialize(const uint8_t len_size, const uint8_t val_size, MultiValueBuffer * const p, const uint8_t mode = modeArray) {
pBuf = p; pBuf = p;
lenSize = len_size; lenSize = len_size;
valSize = val_size; valSize = val_size;
prsMode = mode; prsMode = mode;
if(prsMode == modeRange) { if (prsMode == modeRange) {
arLenCntdn = arLen = 3; arLenCntdn = arLen = 3;
nStage = 2; nStage = 2;
} else { }
arLenCntdn = arLen = 0; else {
nStage = 0; arLenCntdn = arLen = 0;
} nStage = 0;
enStage = 0; }
theParser.Initialize(p); enStage = 0;
}; theParser.Initialize(p);
}
bool Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL);
bool Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL);
}; };
#endif // __PARSETOOLS_H__

@ -22,71 +22,59 @@
* Web : http://www.circuitsathome.com * Web : http://www.circuitsathome.com
* e-mail : support@circuitsathome.com * e-mail : support@circuitsathome.com
*/ */
#pragma once
#if !defined(_usb_h_) || defined(__PRINTHEX_H__) #ifndef _usb_h_
#error "Never include printhex.h directly; include Usb.h instead" #error "Never include printhex.h directly; include Usb.h instead"
#else #endif
#define __PRINTHEX_H__
void E_Notifyc(char c, int lvl); void E_Notifyc(char c, int lvl);
template <class T> template <class T>
void PrintHex(T val, int lvl) { void PrintHex(T val, int lvl) {
int num_nibbles = sizeof (T) * 2; int num_nibbles = sizeof (T) * 2;
do {
do { char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); if (v > 57) v += 7;
if(v > 57) v += 7; E_Notifyc(v, lvl);
E_Notifyc(v, lvl); } while (--num_nibbles);
} while(--num_nibbles);
} }
template <class T> template <class T>
void PrintBin(T val, int lvl) { void PrintBin(T val, int lvl) {
for(T mask = (((T)1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1) for (T mask = (((T)1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1)
if(val & mask) E_Notifyc(val & mask ? '1' : '0', lvl);
E_Notifyc('1', lvl);
else
E_Notifyc('0', lvl);
} }
template <class T> template <class T>
void SerialPrintHex(T val) { void SerialPrintHex(T val) {
int num_nibbles = sizeof (T) * 2; int num_nibbles = sizeof (T) * 2;
do {
do { char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); if (v > 57) v += 7;
if(v > 57) v += 7; USB_HOST_SERIAL.print(v);
USB_HOST_SERIAL.print(v); } while (--num_nibbles);
} while(--num_nibbles);
} }
template <class T> template <class T>
void PrintHex2(Print *prn, T val) { void PrintHex2(Print *prn, T val) {
T mask = (((T)1) << (((sizeof (T) << 1) - 1) << 2)); T mask = (((T)1) << (((sizeof (T) << 1) - 1) << 2));
while (mask > 1) {
while(mask > 1) { if (val < mask) prn->print("0");
if(val < mask) mask >>= 4;
prn->print("0"); }
prn->print((T)val, HEX);
mask >>= 4;
}
prn->print((T)val, HEX);
} }
template <class T> void D_PrintHex(T val __attribute__((unused)), int lvl __attribute__((unused))) { template <class T> void D_PrintHex(T val __attribute__((unused)), int lvl __attribute__((unused))) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
PrintHex<T > (val, lvl); PrintHex<T > (val, lvl);
#endif #endif
} }
template <class T> template <class T>
void D_PrintBin(T val, int lvl) { void D_PrintBin(T val, int lvl) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
PrintBin<T > (val, lvl); PrintBin<T > (val, lvl);
#endif #endif
} }
#endif // __PRINTHEX_H__

@ -35,7 +35,7 @@
* flash drives and simple USB hard drives. * flash drives and simple USB hard drives.
* Disable this by defining DELAY(x) to be delay(x). * Disable this by defining DELAY(x) to be delay(x).
*/ */
#define delay(x) if((x) < 200) safe_delay(x) #define delay(x) if ((x) < 200) safe_delay(x)
/* Almost all USB flash drives and simple USB hard drives fail the write /* Almost all USB flash drives and simple USB hard drives fail the write
* protect test and add 20 - 30 seconds to USB init. Set SKIP_WRITE_PROTECT * protect test and add 20 - 30 seconds to USB init. Set SKIP_WRITE_PROTECT
* to nonzero to skip the test and assume the drive is writable. * to nonzero to skip the test and assume the drive is writable.

@ -23,12 +23,11 @@
* e-mail : support@circuitsathome.com * e-mail : support@circuitsathome.com
*/ */
#if !defined(_usb_h_) || defined(_ch9_h_) #ifndef _usb_h_
#error "Never include usb_ch9.h directly; include Usb.h instead" #error "Never include usb_ch9.h directly; include Usb.h instead"
#else #endif
/* USB chapter 9 structures */ /* USB chapter 9 structures */
#define _ch9_h_
/* Misc.USB constants */ /* Misc.USB constants */
#define DEV_DESCR_LEN 18 //device descriptor length #define DEV_DESCR_LEN 18 //device descriptor length
@ -81,7 +80,6 @@
#define HID_DESCRIPTOR_HID 0x21 #define HID_DESCRIPTOR_HID 0x21
/* OTG SET FEATURE Constants */ /* OTG SET FEATURE Constants */
#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP #define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP
#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP #define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP
@ -170,5 +168,3 @@ typedef struct {
uint8_t bDescrType; // Type of class descriptor uint8_t bDescrType; // Type of class descriptor
uint16_t wDescriptorLength; // Total size of the Report descriptor uint16_t wDescriptorLength; // Total size of the Report descriptor
} __attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; } __attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE;
#endif // _ch9_h_

Loading…
Cancel
Save