Coding standards

This commit is contained in:
Scott Lahteine 2019-02-12 16:25:49 -06:00
parent 19af90face
commit 3a1b6fe8c1
43 changed files with 2033 additions and 2344 deletions

View file

@ -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) {

View file

@ -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;

View file

@ -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" {

View file

@ -45,7 +45,6 @@
#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);
@ -63,7 +62,7 @@ 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);
@ -77,8 +76,7 @@ void pinMode_LCD(uint8_t pin, uint8_t mode) {
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

View file

@ -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);

View file

@ -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);

View file

@ -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];

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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) {
return false;
}
else if (!S && opcode >= 8 && opcode <= 11) {
/* TST, TEQ, CMP and CMN all require S to be set */ /* 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
return true; 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 */ /* Branch to ARM */
/* Account for the auto-increment which isn't needed */ /* Account for the auto-increment which isn't needed */
state->regData[15].v -= 4; 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
op2val = (state->regData[rm].v >> shiftDist) | (0xFFFFFFFF << (32 - shiftDist));
} }
else { else
op2val = state->regData[rm].v >> shiftDist; op2val = state->regData[rm].v >> shiftDist;
op2val |= 0xFFFFFFFF << (32 - shiftDist);
}
}
else {
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);

View file

@ -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,19 +145,18 @@ 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;
} }
} }
} }
} }
}
/* /*
* PUSH register * PUSH register
*/ */
@ -180,10 +169,9 @@ 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 {
uint8_t rv;
if(!state->cb->readB((state->regData[15].v & (~1)) + 2, &rv)) {
return UNWIND_DREAD_B_FAIL;
} }
else {
uint8_t rv;
if (!state->cb->readB((state->regData[15].v & (~1)) + 2, &rv))
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,10 +408,9 @@ 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.
* We are only interested when destination is PC. * We are only interested when destination is PC.
@ -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 {
uint32_t address = state->regData[rn].v + imm12;
if(!UnwMemReadRegister(state, address, &state->regData[rt])) {
return UNWIND_DREAD_W_FAIL;
} }
else {
uint32_t address = state->regData[rn].v + imm12;
if (!UnwMemReadRegister(state, address, &state->regData[rt]))
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 (!UnwMemReadRegister(state, address, &state->regData[rt]))
if (P) {
address = offaddress;
} else {
address = state->regData[rn].v;
}
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,32 +465,30 @@ 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 { else /* Propagate unknown value */
/* Propagate unknown value */
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 + (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 {
UnwPrintd1("???? (32)"); UnwPrintd1("???? (32)");
@ -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,29 +814,26 @@ 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));
return UNWIND_FAILURE; return UNWIND_FAILURE;
@ -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,36 +953,34 @@ 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;
} }
} }
} }
} }
}
/* /*
* 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;
} }

View file

@ -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,20 +68,14 @@ 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);
if(i < 0){
/* Hash full */
return false;
}
else {
/* Store the item */ /* Store the item */
memData->a[i] = addr; memData->a[i] = addr;
M_SetIdxUsed(memData->used, i); M_SetIdxUsed(memData->used, i);
if(valValid) if (valValid) {
{
memData->v[i] = val; memData->v[i] = val;
M_SetIdxUsed(memData->tracked, i); M_SetIdxUsed(memData->tracked, i);
} }
@ -97,7 +87,6 @@ bool UnwMemHashWrite(MemData * const memData, uint32_t addr, uint32_t val, bool
} }
return true; return true;
}
} }
void UnwMemHashGC(UnwState * const state) { void UnwMemHashGC(UnwState * const state) {
@ -106,10 +95,9 @@ void UnwMemHashGC(UnwState * const state) {
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);
} }
} }

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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) {

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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))

View file

@ -56,13 +56,13 @@ void USB::setUsbTaskState(uint8_t state) {
EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) { EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {
UsbDevice *p = addrPool.GetUsbDevicePtr(addr); UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
if(!p || !p->epinfo) if (!p || !p->epinfo)
return NULL; return NULL;
EpInfo *pep = p->epinfo; EpInfo *pep = p->epinfo;
for(uint8_t i = 0; i < p->epcount; i++) { for (uint8_t i = 0; i < p->epcount; i++) {
if((pep)->epAddr == ep) if ((pep)->epAddr == ep)
return pep; return pep;
pep++; pep++;
@ -74,12 +74,12 @@ EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {
/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */ /* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) { uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) {
if(!eprecord_ptr) if (!eprecord_ptr)
return USB_ERROR_INVALID_ARGUMENT; return USB_ERROR_INVALID_ARGUMENT;
UsbDevice *p = addrPool.GetUsbDevicePtr(addr); UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
if(!p) if (!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->address.devAddress = addr; p->address.devAddress = addr;
@ -92,15 +92,15 @@ uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr)
uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) { uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) {
UsbDevice *p = addrPool.GetUsbDevicePtr(addr); UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
if(!p) if (!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if(!p->epinfo) if (!p->epinfo)
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
*ppep = getEpInfoEntry(addr, ep); *ppep = getEpInfoEntry(addr, ep);
if(!*ppep) if (!*ppep)
return USB_ERROR_EP_NOT_FOUND_IN_TBL; return USB_ERROR_EP_NOT_FOUND_IN_TBL;
*nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower)); *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
@ -145,9 +145,7 @@ uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bReque
uint16_t nak_limit = 0; uint16_t nak_limit = 0;
rcode = SetAddress(addr, ep, &pep, &nak_limit); rcode = SetAddress(addr, ep, &pep, &nak_limit);
if (rcode) return rcode;
if(rcode)
return rcode;
direction = ((bmReqType & 0x80) > 0); direction = ((bmReqType & 0x80) > 0);
@ -162,49 +160,40 @@ uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bReque
bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO
rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet
if (rcode) return rcode; // Return HRSLT if not zero
if(rcode) //return HRSLT if not zero if (dataptr != NULL) { //data stage, if present
return ( rcode); if (direction) { //IN transfer
if(dataptr != NULL) //data stage, if present
{
if(direction) //IN transfer
{
uint16_t left = total; uint16_t left = total;
pep->bmRcvToggle = 1; //bmRCVTOG1; pep->bmRcvToggle = 1; //bmRCVTOG1;
while(left) { while (left) {
// Bytes read into buffer // Bytes read into buffer
uint16_t read = nbytes; uint16_t read = nbytes;
//uint16_t read = (left<nbytes) ? left : nbytes; //uint16_t read = (left<nbytes) ? left : nbytes;
rcode = InTransfer(pep, nak_limit, &read, dataptr); rcode = InTransfer(pep, nak_limit, &read, dataptr);
if(rcode == hrTOGERR) { if (rcode == hrTOGERR) {
// yes, we flip it wrong here so that next time it is actually correct! // yes, we flip it wrong here so that next time it is actually correct!
pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
continue; continue;
} }
if(rcode) if (rcode) return rcode;
return rcode;
// Invoke callback function if inTransfer completed successfully and callback function pointer is specified // Invoke callback function if inTransfer completed successfully and callback function pointer is specified
if(!rcode && p) if (!rcode && p) ((USBReadParser*)p)->Parse(read, dataptr, total - left);
((USBReadParser*)p)->Parse(read, dataptr, total - left);
left -= read; left -= read;
if(read < nbytes) if (read < nbytes) break;
break;
} }
} else //OUT transfer }
{ else { //OUT transfer
pep->bmSndToggle = 1; //bmSNDTOG1; pep->bmSndToggle = 1; //bmSNDTOG1;
rcode = OutTransfer(pep, nak_limit, nbytes, dataptr); rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
} }
if(rcode) //return error if (rcode) return rcode; // return error
return ( rcode);
} }
// Status stage // Status stage
return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction
@ -220,8 +209,7 @@ uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t*
uint16_t nak_limit = 0; uint16_t nak_limit = 0;
uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit); uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
if (rcode) {
if(rcode) {
USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81); USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81); USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81);
USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81); USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
@ -242,30 +230,30 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
// use a 'break' to exit this loop // use a 'break' to exit this loop
while(1) { for (;;) {
rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS. rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
if(rcode == hrTOGERR) { if (rcode == hrTOGERR) {
// yes, we flip it wrong here so that next time it is actually correct! // yes, we flip it wrong here so that next time it is actually correct!
pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1; pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1;
regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
continue; continue;
} }
if(rcode) { if (rcode) {
//printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode); //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode);
break; //should be 0, indicating ACK. Else return error code. break; //should be 0, indicating ACK. Else return error code.
} }
/* check for RCVDAVIRQ and generate error if not present */ /* check for RCVDAVIRQ and generate error if not present */
/* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */ /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */
if((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) { if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) {
//printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n"); //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n");
rcode = 0xf0; //receive error rcode = 0xF0; //receive error
break; break;
} }
pktsize = regRd(rRCVBC); //number of received bytes pktsize = regRd(rRCVBC); //number of received bytes
//printf("Got %i bytes \r\n", pktsize); //printf("Got %i bytes \r\n", pktsize);
// This would be OK, but... // This would be OK, but...
//assert(pktsize <= nbytes); //assert(pktsize <= nbytes);
if(pktsize > nbytes) { if (pktsize > nbytes) {
// This can happen. Use of assert on Arduino locks up the Arduino. // This can happen. Use of assert on Arduino locks up the Arduino.
// So I will trim the value, and hope for the best. // So I will trim the value, and hope for the best.
//printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize); //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize);
@ -273,9 +261,7 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
} }
int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
if (mem_left < 0) mem_left = 0;
if(mem_left < 0)
mem_left = 0;
data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data); data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);
@ -285,17 +271,17 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
/* The transfer is complete under two conditions: */ /* The transfer is complete under two conditions: */
/* 1. The device sent a short packet (L.T. maxPacketSize) */ /* 1. The device sent a short packet (L.T. maxPacketSize) */
/* 2. 'nbytes' have been transferred. */ /* 2. 'nbytes' have been transferred. */
if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes? if (pktsize < maxpktsize || *nbytesptr >= nbytes) { // Transferred 'nbytes' bytes?
{
// Save toggle value // Save toggle value
pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0; pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
//printf("\r\n"); //printf("\r\n");
rcode = 0; rcode = 0;
break; break;
} else if(bInterval > 0) }
else if (bInterval > 0)
delay(bInterval); // Delay according to polling interval delay(bInterval); // Delay according to polling interval
} //while( 1 ) }
return ( rcode); return rcode;
} }
/* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */ /* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
@ -307,9 +293,7 @@ uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dat
uint16_t nak_limit = 0; uint16_t nak_limit = 0;
uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit); uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
if (rcode) return rcode;
if(rcode)
return rcode;
return OutTransfer(pep, nak_limit, nbytes, data); return OutTransfer(pep, nak_limit, nbytes, data);
} }
@ -322,35 +306,35 @@ uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8
uint8_t maxpktsize = pep->maxPktSize; uint8_t maxpktsize = pep->maxPktSize;
if(maxpktsize < 1 || maxpktsize > 64) if (maxpktsize < 1 || maxpktsize > 64)
return USB_ERROR_INVALID_MAX_PKT_SIZE; return USB_ERROR_INVALID_MAX_PKT_SIZE;
uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT; uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;
regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
while(bytes_left) { while (bytes_left) {
retry_count = 0; retry_count = 0;
nak_count = 0; nak_count = 0;
bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left; bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
regWr(rSNDBC, bytes_tosend); //set number of bytes regWr(rSNDBC, bytes_tosend); //set number of bytes
regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
rcode = (regRd(rHRSL) & 0x0f); rcode = (regRd(rHRSL) & 0x0F);
while(rcode && ((int32_t)((uint32_t)millis() - timeout) < 0L)) { while (rcode && ((int32_t)((uint32_t)millis() - timeout) < 0L)) {
switch(rcode) { switch (rcode) {
case hrNAK: case hrNAK:
nak_count++; nak_count++;
if(nak_limit && (nak_count == nak_limit)) if (nak_limit && (nak_count == nak_limit))
goto breakout; goto breakout;
//return ( rcode); //return ( rcode);
break; break;
case hrTIMEOUT: case hrTIMEOUT:
retry_count++; retry_count++;
if(retry_count == USB_RETRY_LIMIT) if (retry_count == USB_RETRY_LIMIT)
goto breakout; goto breakout;
//return ( rcode); //return ( rcode);
break; break;
@ -361,31 +345,32 @@ uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8
break; break;
default: default:
goto breakout; goto breakout;
}//switch( rcode }
/* process NAK according to Host out NAK bug */ /* process NAK according to Host out NAK bug */
regWr(rSNDBC, 0); regWr(rSNDBC, 0);
regWr(rSNDFIFO, *data_p); regWr(rSNDFIFO, *data_p);
regWr(rSNDBC, bytes_tosend); regWr(rSNDBC, bytes_tosend);
regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
rcode = (regRd(rHRSL) & 0x0f); rcode = (regRd(rHRSL) & 0x0F);
}//while( rcode && .... } // while rcode && ....
bytes_left -= bytes_tosend; bytes_left -= bytes_tosend;
data_p += bytes_tosend; data_p += bytes_tosend;
}//while( bytes_left... } // while bytes_left...
breakout: breakout:
pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle
return ( rcode); //should be 0 in all cases return ( rcode); //should be 0 in all cases
} }
/* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */ /* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
/* If NAK, tries to re-send up to nak_limit times */ /* If NAK, tries to re-send up to nak_limit times */
/* If nak_limit == 0, do not count NAKs, exit after timeout */ /* If nak_limit == 0, do not count NAKs, exit after timeout */
/* If bus timeout, re-sends up to USB_RETRY_LIMIT times */ /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */ /* return codes 0x00-0x0F are HRSLT( 0x00 being success ), 0xFF means timeout */
uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) { uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT; uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;
uint8_t tmpdata; uint8_t tmpdata;
@ -393,55 +378,53 @@ uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
uint8_t retry_count = 0; uint8_t retry_count = 0;
uint16_t nak_count = 0; uint16_t nak_count = 0;
while((int32_t)((uint32_t)millis() - timeout) < 0L) { while ((int32_t)((uint32_t)millis() - timeout) < 0L) {
#if defined(ESP8266) || defined(ESP32) #if defined(ESP8266) || defined(ESP32)
yield(); // needed in order to reset the watchdog timer on the ESP8266 yield(); // needed in order to reset the watchdog timer on the ESP8266
#endif #endif
regWr(rHXFR, (token | ep)); //launch the transfer regWr(rHXFR, (token | ep)); //launch the transfer
rcode = USB_ERROR_TRANSFER_TIMEOUT; rcode = USB_ERROR_TRANSFER_TIMEOUT;
while((int32_t)((uint32_t)millis() - timeout) < 0L) //wait for transfer completion while ((int32_t)((uint32_t)millis() - timeout) < 0L) { //wait for transfer completion
{ #if defined(ESP8266) || defined(ESP32)
#if defined(ESP8266) || defined(ESP32) yield(); // needed to reset the watchdog timer on the ESP8266
yield(); // needed in order to reset the watchdog timer on the ESP8266 #endif
#endif
tmpdata = regRd(rHIRQ); tmpdata = regRd(rHIRQ);
if(tmpdata & bmHXFRDNIRQ) { if (tmpdata & bmHXFRDNIRQ) {
regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
rcode = 0x00; rcode = 0x00;
break; break;
}//if( tmpdata & bmHXFRDNIRQ }
}//while ( millis() < timeout } // while millis() < timeout
//if (rcode != 0x00) //exit if timeout //if (rcode != 0x00) //exit if timeout
// return ( rcode); // return ( rcode);
rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result rcode = (regRd(rHRSL) & 0x0F); //analyze transfer result
switch(rcode) { switch (rcode) {
case hrNAK: case hrNAK:
nak_count++; nak_count++;
if(nak_limit && (nak_count == nak_limit)) if (nak_limit && (nak_count == nak_limit))
return (rcode); return (rcode);
break; break;
case hrTIMEOUT: case hrTIMEOUT:
retry_count++; retry_count++;
if(retry_count == USB_RETRY_LIMIT) if (retry_count == USB_RETRY_LIMIT)
return (rcode); return (rcode);
break; break;
default: default:
return (rcode); return (rcode);
}//switch( rcode }
}//while( timeout > millis() } // while timeout > millis()
return ( rcode); return rcode;
} }
/* USB main task. Performs enumeration/cleanup */ /* USB main task. Performs enumeration/cleanup */
void USB::Task(void) //USB state machine void USB::Task(void) { //USB state machine
{
uint8_t rcode; uint8_t rcode;
uint8_t tmpdata; uint8_t tmpdata;
static uint32_t delay = 0; static uint32_t delay = 0;
@ -453,38 +436,36 @@ void USB::Task(void) //USB state machine
tmpdata = getVbusState(); tmpdata = getVbusState();
/* modify USB task state if Vbus changed */ /* modify USB task state if Vbus changed */
switch(tmpdata) { switch (tmpdata) {
case SE1: //illegal state case SE1: //illegal state
usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL; usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
lowspeed = false; lowspeed = false;
break; break;
case SE0: //disconnected case SE0: //disconnected
if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED) if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
lowspeed = false; lowspeed = false;
break; break;
case LSHOST: case LSHOST:
lowspeed = true; lowspeed = true;
//intentional fallthrough //intentional fallthrough
case FSHOST: //attached case FSHOST: //attached
if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) { if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
delay = (uint32_t)millis() + USB_SETTLE_DELAY; delay = (uint32_t)millis() + USB_SETTLE_DELAY;
usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE; usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
} }
break; break;
}// switch( tmpdata }
for(uint8_t i = 0; i < USB_NUMDEVICES; i++) for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
if(devConfig[i]) if (devConfig[i]) rcode = devConfig[i]->Poll();
rcode = devConfig[i]->Poll();
switch(usb_task_state) { switch (usb_task_state) {
case USB_DETACHED_SUBSTATE_INITIALIZE: case USB_DETACHED_SUBSTATE_INITIALIZE:
init(); init();
for(uint8_t i = 0; i < USB_NUMDEVICES; i++) for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
if(devConfig[i]) if (devConfig[i])
rcode = devConfig[i]->Release(); rcode = devConfig[i]->Release();
usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE; usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
@ -494,7 +475,7 @@ void USB::Task(void) //USB state machine
case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
break; break;
case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
if((int32_t)((uint32_t)millis() - delay) >= 0L) if ((int32_t)((uint32_t)millis() - delay) >= 0L)
usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE; usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
else break; // don't fall through else break; // don't fall through
case USB_ATTACHED_SUBSTATE_RESET_DEVICE: case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
@ -502,7 +483,7 @@ void USB::Task(void) //USB state machine
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE; usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
break; break;
case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE: case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
if((regRd(rHCTL) & bmBUSRST) == 0) { if ((regRd(rHCTL) & bmBUSRST) == 0) {
tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
regWr(rMODE, tmpdata); regWr(rMODE, tmpdata);
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF; usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
@ -510,7 +491,7 @@ void USB::Task(void) //USB state machine
} }
break; break;
case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
if(regRd(rHIRQ) & bmFRAMEIRQ) { if (regRd(rHIRQ) & bmFRAMEIRQ) {
//when first SOF received _and_ 20ms has passed we can continue //when first SOF received _and_ 20ms has passed we can continue
/* /*
if (delay < (uint32_t)millis()) //20ms passed if (delay < (uint32_t)millis()) //20ms passed
@ -521,7 +502,7 @@ void USB::Task(void) //USB state machine
} }
break; break;
case USB_ATTACHED_SUBSTATE_WAIT_RESET: case USB_ATTACHED_SUBSTATE_WAIT_RESET:
if((int32_t)((uint32_t)millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING; if ((int32_t)((uint32_t)millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;
else break; // don't fall through else break; // don't fall through
case USB_STATE_CONFIGURING: case USB_STATE_CONFIGURING:
@ -530,20 +511,19 @@ void USB::Task(void) //USB state machine
rcode = Configuring(0, 0, lowspeed); rcode = Configuring(0, 0, lowspeed);
if(rcode) { if (!rcode)
if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) { usb_task_state = USB_STATE_RUNNING;
else if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) {
usb_error = rcode; usb_error = rcode;
usb_task_state = USB_STATE_ERROR; usb_task_state = USB_STATE_ERROR;
} }
} else
usb_task_state = USB_STATE_RUNNING;
break; break;
case USB_STATE_RUNNING: case USB_STATE_RUNNING:
break; break;
case USB_STATE_ERROR: case USB_STATE_ERROR:
//MAX3421E::Init(); //MAX3421E::Init();
break; break;
} // switch( usb_task_state ) }
} }
uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) { uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
@ -553,38 +533,28 @@ uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p0 = addrPool.GetUsbDevicePtr(0); p0 = addrPool.GetUsbDevicePtr(0);
if (!p0) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p0->epinfo) return USB_ERROR_EPINFO_IS_NULL;
if(!p0) p0->lowspeed = lowspeed;
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if(!p0->epinfo)
return USB_ERROR_EPINFO_IS_NULL;
p0->lowspeed = (lowspeed) ? true : false;
// Allocate new address according to device class // Allocate new address according to device class
uint8_t bAddress = addrPool.AllocAddress(parent, false, port); uint8_t bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Assign new address to the device // Assign new address to the device
rcode = setAddr(0, 0, bAddress); rcode = setAddr(0, 0, bAddress);
if (rcode) {
if(rcode) {
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
return rcode;
} }
return 0; return rcode;
}; }
uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) { uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) {
//printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port); //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port);
@ -592,35 +562,40 @@ uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lo
again: again:
uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed); uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
if(rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) { if (rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) {
if(parent == 0) { if (parent == 0) {
// Send a bus reset on the root interface. // Send a bus reset on the root interface.
regWr(rHCTL, bmBUSRST); //issue bus reset regWr(rHCTL, bmBUSRST); //issue bus reset
delay(102); // delay 102ms, compensate for clock inaccuracy. delay(102); // delay 102ms, compensate for clock inaccuracy.
} else { }
else {
// reset parent port // reset parent port
devConfig[parent]->ResetHubPort(port); devConfig[parent]->ResetHubPort(port);
} }
} else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works }
delay(100); else if (rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
retries++;
goto again;
} else if(rcode)
return rcode;
rcode = devConfig[driver]->Init(parent, port, lowspeed);
if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
delay(100); delay(100);
retries++; retries++;
goto again; goto again;
} }
if(rcode) { else if (rcode)
return rcode;
rcode = devConfig[driver]->Init(parent, port, lowspeed);
if (rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
delay(100);
retries++;
goto again;
}
if (rcode) {
// Issue a bus reset, because the device may be in a limbo state // Issue a bus reset, because the device may be in a limbo state
if(parent == 0) { if (parent == 0) {
// Send a bus reset on the root interface. // Send a bus reset on the root interface.
regWr(rHCTL, bmBUSRST); //issue bus reset regWr(rHCTL, bmBUSRST); //issue bus reset
delay(102); // delay 102ms, compensate for clock inaccuracy. delay(102); // delay 102ms, compensate for clock inaccuracy.
} else { }
else {
// reset parent port // reset parent port
devConfig[parent]->ResetHubPort(port); devConfig[parent]->ResetHubPort(port);
} }
@ -628,11 +603,10 @@ again:
return rcode; return rcode;
} }
/* /**
* This is broken. We need to enumerate differently. * This is broken. It needs to enumerate differently.
* It causes major problems with several devices if detected in an unexpected order. * It causes major problems with several devices if detected in an unexpected order.
* *
*
* Oleg - I wouldn't do anything before the newly connected device is considered sane. * Oleg - I wouldn't do anything before the newly connected device is considered sane.
* i.e.(delays are not indicated for brevity): * i.e.(delays are not indicated for brevity):
* 1. reset * 1. reset
@ -649,7 +623,7 @@ again:
* 4: set address * 4: set address
* 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
* 6: while (configurations) { * 6: while (configurations) {
* for(each configuration) { * for (each configuration) {
* for (each driver) { * for (each driver) {
* 6a: Ask device if it likes configuration. Returns 0 on OK. * 6a: Ask device if it likes configuration. Returns 0 on OK.
* If successful, the driver configured device. * If successful, the driver configured device.
@ -663,7 +637,7 @@ again:
* } * }
* } * }
* } * }
* 7: for(each driver) { * 7: for (each driver) {
* 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
* 8: if we get here, no driver likes the device plugged in, so exit failure. * 8: if we get here, no driver likes the device plugged in, so exit failure.
* *
@ -689,7 +663,7 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
AddressPool &addrPool = GetAddressPool(); AddressPool &addrPool = GetAddressPool();
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if(!p) { if (!p) {
//printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n"); //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
@ -709,7 +683,7 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if(rcode) { if (rcode) {
//printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n"); //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
return rcode; return rcode;
} }
@ -718,40 +692,36 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
// Allocate new address according to device class // Allocate new address according to device class
//bAddress = addrPool.AllocAddress(parent, false, port); //bAddress = addrPool.AllocAddress(parent, false, port);
uint16_t vid = udd->idVendor; uint16_t vid = udd->idVendor, pid = udd->idProduct;
uint16_t pid = udd->idProduct; uint8_t klass = udd->bDeviceClass, subklass = udd->bDeviceSubClass;
uint8_t klass = udd->bDeviceClass;
uint8_t subklass = udd->bDeviceSubClass;
// Attempt to configure if VID/PID or device class matches with a driver // Attempt to configure if VID/PID or device class matches with a driver
// Qualify with subclass too. // Qualify with subclass too.
// //
// VID/PID & class tests default to false for drivers not yet ported // VID/PID & class tests default to false for drivers not yet ported
// subclass defaults to true, so you don't have to define it if you don't have to. // subclass defaults to true, so you don't have to define it if you don't have to.
// //
for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
if(!devConfig[devConfigIndex]) continue; // no driver if (!devConfig[devConfigIndex]) continue; // no driver
if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed
if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) { if (devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) {
rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED) if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)
break; break;
} }
} }
if(devConfigIndex < USB_NUMDEVICES) { if (devConfigIndex < USB_NUMDEVICES) return rcode;
return rcode;
}
// blindly attempt to configure // blindly attempt to configure
for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) { for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
if(!devConfig[devConfigIndex]) continue; if (!devConfig[devConfigIndex]) continue;
if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed if (devConfig[devConfigIndex]->GetAddress()) continue; // consumed
if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above if (devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above
rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed); rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
//printf("ERROR ENUMERATING %2.2x\r\n", rcode); //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
if(!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) { if (!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) {
// in case of an error dev_index should be reset to 0 // in case of an error dev_index should be reset to 0
// in order to start from the very beginning the // in order to start from the very beginning the
// next time the program gets here // next time the program gets here
@ -760,21 +730,18 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
return rcode; return rcode;
} }
} }
// if we get here that means that the device class is not supported by any of registered classes // Arriving here means the device class is unsupported by registered classes
rcode = DefaultAddressing(parent, port, lowspeed); return DefaultAddressing(parent, port, lowspeed);
return rcode;
} }
uint8_t USB::ReleaseDevice(uint8_t addr) { uint8_t USB::ReleaseDevice(uint8_t addr) {
if(!addr) if (addr) {
return 0; for (uint8_t i = 0; i < USB_NUMDEVICES; i++) {
if (!devConfig[i]) continue;
for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { if (devConfig[i]->GetAddress() == addr)
if(!devConfig[i]) continue;
if(devConfig[i]->GetAddress() == addr)
return devConfig[i]->Release(); return devConfig[i]->Release();
} }
}
return 0; return 0;
} }
@ -782,12 +749,12 @@ uint8_t USB::ReleaseDevice(uint8_t addr) {
//get device descriptor //get device descriptor
uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) { uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL)); return ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL);
} }
//get configuration descriptor //get configuration descriptor
uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) { uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL)); return ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL);
} }
/* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this /* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this
@ -798,21 +765,19 @@ uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser
USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf); USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf);
uint8_t ret = getConfDescr(addr, ep, 9, conf, buf); uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);
if (ret) return ret;
if(ret)
return ret;
uint16_t total = ucd->wTotalLength; uint16_t total = ucd->wTotalLength;
//USBTRACE2("\r\ntotal conf.size:", total); //USBTRACE2("\r\ntotal conf.size:", total);
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p)); return ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p);
} }
//get string descriptor //get string descriptor
uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) { uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) {
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL)); return ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL);
} }
//set address //set address
@ -821,12 +786,12 @@ uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
//delay(2); //per USB 2.0 sect.9.2.6.3 //delay(2); //per USB 2.0 sect.9.2.6.3
delay(300); // Older spec says you should wait at least 200ms delay(300); // Older spec says you should wait at least 200ms
return rcode; return rcode;
//return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL)); //return ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);
} }
//set configuration //set configuration
uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) { uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL)); return ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);
} }
#endif // defined(USB_METHODS_INLINE) #endif // defined(USB_METHODS_INLINE)

View file

@ -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_

View file

@ -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;
} }

View file

@ -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) */
@ -63,9 +61,7 @@ struct EpInfo {
// //
struct UsbDeviceAddress { struct UsbDeviceAddress {
union { union {
struct { struct {
uint8_t bmAddress : 3; // device address/port number uint8_t bmAddress : 3; // device address/port number
uint8_t bmParent : 3; // parent hub address uint8_t bmParent : 3; // parent hub address
@ -89,7 +85,7 @@ struct UsbDevice {
} __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;
@ -109,63 +105,61 @@ class AddressPoolImpl : public AddressPool {
UsbDevice thePool[MAX_DEVICES_ALLOWED]; UsbDevice thePool[MAX_DEVICES_ALLOWED];
// Initializes address pool entry // Initialize address pool entry
void InitEntry(uint8_t index) { void InitEntry(uint8_t index) {
thePool[index].address.devAddress = 0; thePool[index].address.devAddress = 0;
thePool[index].epcount = 1; thePool[index].epcount = 1;
thePool[index].lowspeed = 0; thePool[index].lowspeed = 0;
thePool[index].epinfo = &dev0ep; thePool[index].epinfo = &dev0ep;
}; }
// Returns thePool index for a given address // Return thePool index for a given address
uint8_t FindAddressIndex(uint8_t address = 0) { uint8_t FindAddressIndex(uint8_t address = 0) {
for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) { for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
if(thePool[i].address.devAddress == address) if (thePool[i].address.devAddress == address)
return i; return i;
}
return 0;
};
// Returns thePool child index for a given parent return 0;
}
// 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:
@ -182,55 +176,50 @@ public:
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); uint8_t index = FindAddressIndex(addr);
return index ? thePool + index : NULL;
}
return (!index) ? NULL : thePool + index; // Perform an operation specified by pfunc for each addressed device
};
// Performs an operation specified by pfunc for each addressed device
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
if(!pfunc) if (pfunc) {
return; for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
if (thePool[i].address.devAddress)
for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
if(thePool[i].address.devAddress)
pfunc(thePool + i); pfunc(thePool + i);
}; }
}
// Allocates new address // Allocate new address
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) { virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) {
/* if (parent != 0 && port == 0) /* if (parent != 0 && port == 0)
USB_HOST_SERIAL.println("PRT:0"); */ USB_HOST_SERIAL.println("PRT:0"); */
UsbDeviceAddress _parent; UsbDeviceAddress _parent;
_parent.devAddress = parent; _parent.devAddress = parent;
if(_parent.bmReserved || port > 7) if (_parent.bmReserved || port > 7)
//if(parent > 127 || port > 7) //if(parent > 127 || port > 7)
return 0; return 0;
if(is_hub && hubCounter == 7) if (is_hub && hubCounter == 7) return 0;
return 0;
// finds first empty address entry starting from one // finds first empty address entry starting from one
uint8_t index = FindAddressIndex(0); uint8_t index = FindAddressIndex(0);
if(!index) // if empty entry is not found if (!index) return 0; // if empty entry is not found
return 0;
if(_parent.devAddress == 0) { if (_parent.devAddress == 0) {
if(is_hub) { if (is_hub) {
thePool[index].address.devAddress = 0x41; thePool[index].address.devAddress = 0x41;
hubCounter++; hubCounter++;
} else }
else
thePool[index].address.devAddress = 1; thePool[index].address.devAddress = 1;
return thePool[index].address.devAddress; return thePool[index].address.devAddress;
@ -239,10 +228,11 @@ public:
UsbDeviceAddress addr; UsbDeviceAddress addr;
addr.devAddress = 0; // Ensure all bits are zero addr.devAddress = 0; // Ensure all bits are zero
addr.bmParent = _parent.bmAddress; addr.bmParent = _parent.bmAddress;
if(is_hub) { if (is_hub) {
addr.bmHub = 1; addr.bmHub = 1;
addr.bmAddress = ++hubCounter; addr.bmAddress = ++hubCounter;
} else { }
else {
addr.bmHub = 0; addr.bmHub = 0;
addr.bmAddress = port; addr.bmAddress = port;
} }
@ -256,36 +246,26 @@ public:
USB_HOST_SERIAL.println(addr.bmAddress, HEX); USB_HOST_SERIAL.println(addr.bmAddress, HEX);
*/ */
return thePool[index].address.devAddress; return thePool[index].address.devAddress;
}; }
// Empties pool entry // Empty the pool entry
virtual void FreeAddress(uint8_t addr) { virtual void FreeAddress(uint8_t addr) {
// if the root hub is disconnected all the addresses should be initialized // if the root hub is disconnected all the addresses should be initialized
if(addr == 0x41) { if (addr == 0x41) {
InitAllAddresses(); InitAllAddresses();
return; return;
} }
uint8_t index = FindAddressIndex(addr); FreeAddressByIndex(FindAddressIndex(addr));
FreeAddressByIndex(index); }
};
// Returns number of hubs attached // Return number of hubs attached
// It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs. // It can be helpful to find out if hubs are attached when getting the exact number of hubs.
//uint8_t GetNumHubs() //uint8_t GetNumHubs() { return hubCounter; }
//{ //uint8_t GetNumDevices() {
// return hubCounter;
//};
//uint8_t GetNumDevices()
//{
// uint8_t counter = 0; // uint8_t counter = 0;
// for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
// for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++) // if (thePool[i].address != 0); counter++;
// if (thePool[i].address != 0);
// counter ++;
// return counter; // return counter;
//}; //}
}; };
#endif // __ADDRESS_H__

View file

@ -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(__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:
@ -34,7 +34,7 @@ public:
//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
@ -69,33 +69,28 @@ class ConfigDescParser : public USBReadParser {
public: public:
void SetOR(void) { void SetOR(void) { UseOr = true; }
UseOr = true;
}
ConfigDescParser(UsbConfigXtracter *xtractor); ConfigDescParser(UsbConfigXtracter *xtractor);
void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); 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
@ -104,14 +99,13 @@ template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTO
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;
@ -124,7 +118,7 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
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;
@ -137,46 +131,38 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
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)) if (!valParser.Parse(pp, pcntdn)) return false;
return false;
confValue = ucd->bConfigurationValue; confValue = ucd->bConfigurationValue;
break; break;
case USB_DESCRIPTOR_INTERFACE: case USB_DESCRIPTOR_INTERFACE:
if(!valParser.Parse(pp, pcntdn)) if (!valParser.Parse(pp, pcntdn)) return false;
return false; if ((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)
if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)
break; break;
if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID) if ((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID)
break;
if(UseOr) {
if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol)))
break;
} else {
if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)
break; break;
if (UseOr) {
if ((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol))) break;
} }
else if ((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)
break;
isGoodInterface = true; isGoodInterface = true;
ifaceNumber = uid->bInterfaceNumber; ifaceNumber = uid->bInterfaceNumber;
ifaceAltSet = uid->bAlternateSetting; ifaceAltSet = uid->bAlternateSetting;
protoValue = uid->bInterfaceProtocol; protoValue = uid->bInterfaceProtocol;
break; break;
case USB_DESCRIPTOR_ENDPOINT: case USB_DESCRIPTOR_ENDPOINT:
if(!valParser.Parse(pp, pcntdn)) if (!valParser.Parse(pp, pcntdn)) return false;
return false; if (isGoodInterface && theXtractor)
if(isGoodInterface)
if(theXtractor)
theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer); theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
break; break;
//case HID_DESCRIPTOR_HID: //case HID_DESCRIPTOR_HID:
// if (!valParser.Parse(pp, pcntdn)) // if (!valParser.Parse(pp, pcntdn)) return false;
// return false;
// PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
// break; // break;
default: default:
if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2)) if (!theSkipper.Skip(pp, pcntdn, dscrLen - 2)) return false;
return false;
} }
theBuffer.pValue = varBuffer; theBuffer.pValue = varBuffer;
stateParseDescr = 0; stateParseDescr = 0;
@ -202,7 +188,7 @@ void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescrip
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);
@ -213,6 +199,3 @@ void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescrip
} }
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
} }
#endif // __CONFDESCPARSER_H__

View file

@ -22,11 +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(__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;
@ -50,21 +50,19 @@ public:
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__

View file

@ -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__

View file

@ -44,9 +44,7 @@ const uint8_t BulkOnly::epInterruptInIndex = 3;
* @return media capacity * @return media capacity
*/ */
uint32_t BulkOnly::GetCapacity(uint8_t lun) { uint32_t BulkOnly::GetCapacity(uint8_t lun) {
if(LUNOk[lun]) return LUNOk[lun] ? CurrentCapacity[lun] : 0UL;
return CurrentCapacity[lun];
return 0LU;
} }
/** /**
@ -56,9 +54,7 @@ uint32_t BulkOnly::GetCapacity(uint8_t lun) {
* @return media sector size * @return media sector size
*/ */
uint16_t BulkOnly::GetSectorSize(uint8_t lun) { uint16_t BulkOnly::GetSectorSize(uint8_t lun) {
if(LUNOk[lun]) return LUNOk[lun] ? CurrentSectorSize[lun] : 0U;
return CurrentSectorSize[lun];
return 0U;
} }
/** /**
@ -67,9 +63,7 @@ uint16_t BulkOnly::GetSectorSize(uint8_t lun) {
* @param lun Logical Unit Number * @param lun Logical Unit Number
* @return true if LUN is ready for use * @return true if LUN is ready for use
*/ */
bool BulkOnly::LUNIsGood(uint8_t lun) { bool BulkOnly::LUNIsGood(uint8_t lun) { return LUNOk[lun]; }
return LUNOk[lun];
}
/** /**
* Test if LUN is write protected * Test if LUN is write protected
@ -77,9 +71,7 @@ bool BulkOnly::LUNIsGood(uint8_t lun) {
* @param lun Logical Unit Number * @param lun Logical Unit Number
* @return cached status of write protect switch * @return cached status of write protect switch
*/ */
bool BulkOnly::WriteProtected(uint8_t lun) { bool BulkOnly::WriteProtected(uint8_t lun) { return WriteOk[lun]; }
return WriteOk[lun];
}
/** /**
* Wrap and execute a SCSI CDB with length of 6 * Wrap and execute a SCSI CDB with length of 6
@ -142,12 +134,13 @@ uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
Notify(PSTR("-----------------\r\n"), 0x80); Notify(PSTR("-----------------\r\n"), 0x80);
uint8_t rcode = MASS_ERR_UNIT_NOT_READY; uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
if(bAddress) { if (bAddress) {
CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0); CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0);
rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT); rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT);
} else {
SetCurLUN(lun);
} }
else
SetCurLUN(lun);
return rcode; return rcode;
} }
@ -162,25 +155,25 @@ uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
* @return 0 on success * @return 0 on success
*/ */
uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) { uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
Notify(PSTR("\r\nRead LUN:\t"), 0x80); Notify(PSTR("\r\nRead LUN:\t"), 0x80);
D_PrintHex<uint8_t > (lun, 0x90); D_PrintHex<uint8_t> (lun, 0x90);
Notify(PSTR("\r\nLBA:\t\t"), 0x90); Notify(PSTR("\r\nLBA:\t\t"), 0x90);
D_PrintHex<uint32_t > (addr, 0x90); D_PrintHex<uint32_t> (addr, 0x90);
Notify(PSTR("\r\nblocks:\t\t"), 0x90); Notify(PSTR("\r\nblocks:\t\t"), 0x90);
D_PrintHex<uint8_t > (blocks, 0x90); D_PrintHex<uint8_t> (blocks, 0x90);
Notify(PSTR("\r\nblock size:\t"), 0x90); Notify(PSTR("\r\nblock size:\t"), 0x90);
D_PrintHex<uint16_t > (bsize, 0x90); D_PrintHex<uint16_t> (bsize, 0x90);
Notify(PSTR("\r\n---------\r\n"), 0x80); Notify(PSTR("\r\n---------\r\n"), 0x80);
CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr); CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr);
again: again:
uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN); uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN);
if(er == MASS_ERR_STALL) { if (er == MASS_ERR_STALL) {
MediaCTL(lun, 1); MediaCTL(lun, 1);
delay(150); delay(150);
if(!TestUnitReady(lun)) goto again; if (!TestUnitReady(lun)) goto again;
} }
return er; return er;
} }
@ -196,26 +189,26 @@ again:
* @return 0 on success * @return 0 on success
*/ */
uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) { uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {
if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
if(!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED; if (!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED;
Notify(PSTR("\r\nWrite LUN:\t"), 0x80); Notify(PSTR("\r\nWrite LUN:\t"), 0x80);
D_PrintHex<uint8_t > (lun, 0x90); D_PrintHex<uint8_t> (lun, 0x90);
Notify(PSTR("\r\nLBA:\t\t"), 0x90); Notify(PSTR("\r\nLBA:\t\t"), 0x90);
D_PrintHex<uint32_t > (addr, 0x90); D_PrintHex<uint32_t> (addr, 0x90);
Notify(PSTR("\r\nblocks:\t\t"), 0x90); Notify(PSTR("\r\nblocks:\t\t"), 0x90);
D_PrintHex<uint8_t > (blocks, 0x90); D_PrintHex<uint8_t> (blocks, 0x90);
Notify(PSTR("\r\nblock size:\t"), 0x90); Notify(PSTR("\r\nblock size:\t"), 0x90);
D_PrintHex<uint16_t > (bsize, 0x90); D_PrintHex<uint16_t> (bsize, 0x90);
Notify(PSTR("\r\n---------\r\n"), 0x80); Notify(PSTR("\r\n---------\r\n"), 0x80);
CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr); CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr);
again: again:
uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT); uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT);
if(er == MASS_ERR_WRITE_STALL) { if (er == MASS_ERR_WRITE_STALL) {
MediaCTL(lun, 1); MediaCTL(lun, 1);
delay(150); delay(150);
if(!TestUnitReady(lun)) goto again; if (!TestUnitReady(lun)) goto again;
} }
return er; return er;
} }
@ -238,8 +231,7 @@ bPollEnable(false),
bLastUsbError(0) { bLastUsbError(0) {
ClearAllEP(); ClearAllEP();
dCBWTag = 0; dCBWTag = 0;
if(pUsb) if (pUsb) pUsb->RegisterDeviceClass(this);
pUsb->RegisterDeviceClass(this);
} }
/** /**
@ -269,18 +261,14 @@ uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
ClearAllEP(); ClearAllEP();
AddressPool &addrPool = pUsb->GetAddressPool(); AddressPool &addrPool = pUsb->GetAddressPool();
if (bAddress) return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
if(bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
// <TECHNICAL> // <TECHNICAL>
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if(!p) { if (!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
}
if(!p->epinfo) { if (!p->epinfo) {
USBTRACE("epinfo\r\n"); USBTRACE("epinfo\r\n");
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
} }
@ -298,14 +286,12 @@ uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if(rcode) { if (rcode) goto FailGetDevDescr;
goto FailGetDevDescr;
}
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if(!bAddress) if (!bAddress) return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
epInfo[0].maxPktSize = udd->bMaxPacketSize0; epInfo[0].maxPktSize = udd->bMaxPacketSize0;
@ -315,14 +301,15 @@ uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
FailGetDevDescr: FailGetDevDescr:
#ifdef DEBUG_USB_HOST
#ifdef DEBUG_USB_HOST
NotifyFailGetDevDescr(rcode); NotifyFailGetDevDescr(rcode);
#endif #endif
rcode = USB_ERROR_FailGetDevDescr; rcode = USB_ERROR_FailGetDevDescr;
Release(); Release();
return rcode; return rcode;
}; }
/** /**
* @param parent (not used) * @param parent (not used)
@ -339,14 +326,13 @@ uint8_t BulkOnly::Init(uint8_t parent __attribute__((unused)), uint8_t port __at
AddressPool &addrPool = pUsb->GetAddressPool(); AddressPool &addrPool = pUsb->GetAddressPool();
UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);
if(!p) if (!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
// Assign new address to the device // Assign new address to the device
delay(2000); delay(2000);
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if(rcode) { if (rcode) {
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -360,20 +346,18 @@ uint8_t BulkOnly::Init(uint8_t parent __attribute__((unused)), uint8_t port __at
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if(!p) if (!p) return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if(rcode) if (rcode) goto FailSetDevTblEntry;
goto FailSetDevTblEntry;
USBTRACE2("NC:", num_of_conf); USBTRACE2("NC:", num_of_conf);
for(uint8_t i = 0; i < num_of_conf; i++) { for (uint8_t i = 0; i < num_of_conf; i++) {
ConfigDescParser< USB_CLASS_MASS_STORAGE, ConfigDescParser< USB_CLASS_MASS_STORAGE,
MASS_SUBCLASS_SCSI, MASS_SUBCLASS_SCSI,
MASS_PROTO_BBB, MASS_PROTO_BBB,
@ -383,15 +367,12 @@ uint8_t BulkOnly::Init(uint8_t parent __attribute__((unused)), uint8_t port __at
rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);
if(rcode) if (rcode) goto FailGetConfDescr;
goto FailGetConfDescr;
if(bNumEP > 1) if (bNumEP > 1) break;
break;
} }
if(bNumEP < 3) if (bNumEP < 3) return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
@ -401,38 +382,37 @@ uint8_t BulkOnly::Init(uint8_t parent __attribute__((unused)), uint8_t port __at
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum); rcode = pUsb->setConf(bAddress, 0, bConfNum);
if(rcode) if (rcode) goto FailSetConfDescr;
goto FailSetConfDescr;
//Linux does a 1sec delay after this. //Linux does a 1sec delay after this.
delay(1000); delay(1000);
rcode = GetMaxLUN(&bMaxLUN); rcode = GetMaxLUN(&bMaxLUN);
if(rcode) if (rcode) goto FailGetMaxLUN;
goto FailGetMaxLUN;
if(bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1; if (bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1;
ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN); ErrorMessage<uint8_t> (PSTR("MaxLUN"), bMaxLUN);
delay(1000); // Delay a bit for slow firmware. delay(1000); // Delay a bit for slow firmware.
for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
InquiryResponse response; InquiryResponse response;
rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response); rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
if(rcode) { if (rcode) {
ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode); ErrorMessage<uint8_t> (PSTR("Inquiry"), rcode);
} else { }
#if 0 else {
#if 0
printf("LUN %i `", lun); printf("LUN %i `", lun);
uint8_t *buf = response.VendorID; uint8_t *buf = response.VendorID;
for(int i = 0; i < 28; i++) printf("%c", buf[i]); for (int i = 0; i < 28; i++) printf("%c", buf[i]);
printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier); printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier);
printf("Device type %2.2X ", response.DeviceType); printf("Device type %2.2X ", response.DeviceType);
printf("RMB %1.1X ", response.Removable); printf("RMB %1.1X ", response.Removable);
printf("SSCS %1.1X ", response.SCCS); printf("SSCS %1.1X ", response.SCCS);
uint8_t sv = response.Version; uint8_t sv = response.Version;
printf("SCSI version %2.2X\r\nDevice conforms to ", sv); printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
switch(sv) { switch (sv) {
case 0: case 0:
printf("No specific"); printf("No specific");
break; break;
@ -454,86 +434,88 @@ uint8_t BulkOnly::Init(uint8_t parent __attribute__((unused)), uint8_t port __at
case 6: case 6:
printf("T10/1731-D (SPC-4)"); printf("T10/1731-D (SPC-4)");
break; break;
default: default: printf("unknown");
printf("unknown");
} }
printf(" standards.\r\n"); printf(" standards.\r\n");
#endif #endif
uint8_t tries = 0xf0; uint8_t tries = 0xf0;
while((rcode = TestUnitReady(lun))) { while ((rcode = TestUnitReady(lun))) {
if(rcode == 0x08) break; // break on no media, this is OK to do. if (rcode == 0x08) break; // break on no media, this is OK to do.
// try to lock media and spin up // try to lock media and spin up
if(tries < 14) { if (tries < 14) {
LockMedia(lun, 1); LockMedia(lun, 1);
MediaCTL(lun, 1); // I actually have a USB stick that needs this! MediaCTL(lun, 1); // I actually have a USB stick that needs this!
} else delay(2 * (tries + 1)); } else
delay(2 * (tries + 1));
tries++; tries++;
if(!tries) break; if (!tries) break;
} }
if(!rcode) { if (!rcode) {
delay(1000); delay(1000);
LUNOk[lun] = CheckLUN(lun); LUNOk[lun] = CheckLUN(lun);
if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun); if (!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
} }
} }
} }
CheckMedia(); CheckMedia();
rcode = OnInit(); rcode = OnInit();
if(rcode) if (rcode) goto FailOnInit;
goto FailOnInit;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
USBTRACE("MS configured\r\n\r\n"); USBTRACE("MS configured\r\n\r\n");
#endif #endif
bPollEnable = true; bPollEnable = true;
//USBTRACE("Poll enabled\r\n"); //USBTRACE("Poll enabled\r\n");
return 0; return 0;
FailSetConfDescr: FailSetConfDescr:
#ifdef DEBUG_USB_HOST
#ifdef DEBUG_USB_HOST
NotifyFailSetConfDescr(); NotifyFailSetConfDescr();
goto Fail; goto Fail;
#endif #endif
FailOnInit: FailOnInit:
#ifdef DEBUG_USB_HOST
#ifdef DEBUG_USB_HOST
USBTRACE("OnInit:"); USBTRACE("OnInit:");
goto Fail; goto Fail;
#endif #endif
FailGetMaxLUN: FailGetMaxLUN:
#ifdef DEBUG_USB_HOST
#ifdef DEBUG_USB_HOST
USBTRACE("GetMaxLUN:"); USBTRACE("GetMaxLUN:");
goto Fail; goto Fail;
#endif #endif
//#ifdef DEBUG_USB_HOST //#ifdef DEBUG_USB_HOST
//FailInvalidSectorSize: // FailInvalidSectorSize:
// USBTRACE("Sector Size is NOT VALID: "); // USBTRACE("Sector Size is NOT VALID: ");
// goto Fail; // goto Fail;
//#endif //#endif
FailSetDevTblEntry: FailSetDevTblEntry:
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
NotifyFailSetDevTblEntry(); NotifyFailSetDevTblEntry();
goto Fail; goto Fail;
#endif #endif
FailGetConfDescr: FailGetConfDescr:
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
NotifyFailGetConfDescr(); NotifyFailGetConfDescr();
#endif #endif
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Fail: Fail:
NotifyFail(rcode); NotifyFail(rcode);
#endif #endif
Release(); Release();
return rcode; return rcode;
} }
@ -548,16 +530,16 @@ Fail:
* @param pep * @param pep
*/ */
void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR * pep) { void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR * pep) {
ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf); ErrorMessage<uint8_t> (PSTR("Conf.Val"), conf);
ErrorMessage<uint8_t > (PSTR("Iface Num"), iface); ErrorMessage<uint8_t> (PSTR("Iface Num"), iface);
ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt); ErrorMessage<uint8_t> (PSTR("Alt.Set"), alt);
bConfNum = conf; bConfNum = conf;
uint8_t index; uint8_t index;
#if 1 #if 1
if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) { if ((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) {
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
// Fill in the endpoint info structure // Fill in the endpoint info structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
@ -568,12 +550,11 @@ void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t
bNumEP++; bNumEP++;
PrintEndpointDescriptor(pep); PrintEndpointDescriptor(pep);
} }
#else #else
if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80) if ((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80)
index = epInterruptInIndex; index = epInterruptInIndex;
else if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK) else if ((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK)
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex; index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
else else
return; return;
@ -587,7 +568,7 @@ void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t
bNumEP++; bNumEP++;
PrintEndpointDescriptor(pep); PrintEndpointDescriptor(pep);
#endif #endif
} }
/** /**
@ -610,36 +591,35 @@ uint8_t BulkOnly::Release() {
bool BulkOnly::CheckLUN(uint8_t lun) { bool BulkOnly::CheckLUN(uint8_t lun) {
uint8_t rcode; uint8_t rcode;
Capacity capacity; Capacity capacity;
for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0; for (uint8_t i = 0; i < 8; i++) capacity.data[i] = 0;
rcode = ReadCapacity10(lun, (uint8_t*)capacity.data); rcode = ReadCapacity10(lun, (uint8_t*)capacity.data);
if(rcode) { if (rcode) {
//printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode); //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode);
return false; return false;
} }
ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun); ErrorMessage<uint8_t> (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++) for (uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++)
D_PrintHex<uint8_t > (capacity.data[i], 0x80); D_PrintHex<uint8_t> (capacity.data[i], 0x80);
Notify(PSTR("\r\n\r\n"), 0x80); Notify(PSTR("\r\n\r\n"), 0x80);
// Only 512/1024/2048/4096 are valid values! // Only 512/1024/2048/4096 are valid values!
uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]); uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]);
if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) { if (c != 0x0200UL && c != 0x0400UL && c != 0x0800UL && c != 0x1000UL) return false;
return false;
}
// Store capacity information. // Store capacity information.
CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF); CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF);
CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1; CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1;
if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) { if (CurrentCapacity[lun] == /*0xFFFFFFFFUL */ 0x01UL || CurrentCapacity[lun] == 0x00UL) {
// Buggy firmware will report 0xffffffff or 0 for no media // Buggy firmware will report 0xFFFFFFFF or 0 for no media
if(CurrentCapacity[lun]) if (CurrentCapacity[lun])
ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun); ErrorMessage<uint8_t> (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
return false; return false;
} }
delay(20); delay(20);
Page3F(lun); Page3F(lun);
if(!TestUnitReady(lun)) return true; return !TestUnitReady(lun);
return false;
} }
/** /**
@ -648,23 +628,19 @@ bool BulkOnly::CheckLUN(uint8_t lun) {
* Scan for media change on all LUNs * Scan for media change on all LUNs
*/ */
void BulkOnly::CheckMedia() { void BulkOnly::CheckMedia() {
for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { for (uint8_t lun = 0; lun <= bMaxLUN; lun++) {
if(TestUnitReady(lun)) { if (TestUnitReady(lun)) {
LUNOk[lun] = false; LUNOk[lun] = false;
continue; continue;
} }
if(!LUNOk[lun]) if (!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
LUNOk[lun] = CheckLUN(lun);
} }
#if 0 #if 0
printf("}}}}}}}}}}}}}}}}STATUS "); printf("}}}}}}}}}}}}}}}}STATUS ");
for(uint8_t lun = 0; lun <= bMaxLUN; lun++) { for (uint8_t lun = 0; lun <= bMaxLUN; lun++)
if(LUNOk[lun]) printf(LUNOk[lun] ? "#" : ".");
printf("#");
else printf(".");
}
printf("\r\n"); printf("\r\n");
#endif #endif
qNextPollTime = (uint32_t)millis() + 2000; qNextPollTime = (uint32_t)millis() + 2000;
} }
@ -675,15 +651,9 @@ void BulkOnly::CheckMedia() {
*/ */
uint8_t BulkOnly::Poll() { uint8_t BulkOnly::Poll() {
//uint8_t rcode = 0; //uint8_t rcode = 0;
if (!bPollEnable) return 0;
if(!bPollEnable) if ((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) CheckMedia();
return 0;
if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) {
CheckMedia();
}
//rcode = 0; //rcode = 0;
return 0; return 0;
} }
@ -700,7 +670,7 @@ uint8_t BulkOnly::Poll() {
uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) { uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL); uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL);
if(ret == hrSTALL) if (ret == hrSTALL)
*plun = 0; *plun = 0;
return 0; return 0;
@ -718,7 +688,7 @@ uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
Notify(PSTR("\r\nInquiry\r\n"), 0x80); Notify(PSTR("\r\nInquiry\r\n"), 0x80);
Notify(PSTR("---------\r\n"), 0x80); Notify(PSTR("---------\r\n"), 0x80);
CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0); CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0UL, (uint8_t)bsize, 0);
uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN); uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN);
return rc; return rc;
@ -732,7 +702,7 @@ uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
*/ */
uint8_t BulkOnly::TestUnitReady(uint8_t lun) { uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
//SetCurLUN(lun); //SetCurLUN(lun);
if(!bAddress) if (!bAddress)
return MASS_ERR_UNIT_NOT_READY; return MASS_ERR_UNIT_NOT_READY;
Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80); Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
@ -788,7 +758,7 @@ uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) {
*/ */
uint8_t BulkOnly::Page3F(uint8_t lun) { uint8_t BulkOnly::Page3F(uint8_t lun) {
uint8_t buf[192]; uint8_t buf[192];
for(int i = 0; i < 192; i++) { for (int i = 0; i < 192; i++) {
buf[i] = 0x00; buf[i] = 0x00;
} }
WriteOk[lun] = true; WriteOk[lun] = true;
@ -796,11 +766,11 @@ uint8_t BulkOnly::Page3F(uint8_t lun) {
return 0; return 0;
#endif #endif
uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf); uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf);
if(!rc) { if (!rc) {
WriteOk[lun] = ((buf[2] & 0x80) == 0); WriteOk[lun] = ((buf[2] & 0x80) == 0);
Notify(PSTR("Mode Sense: "), 0x80); Notify(PSTR("Mode Sense: "), 0x80);
for(int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
D_PrintHex<uint8_t > (buf[i], 0x80); D_PrintHex<uint8_t> (buf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
@ -820,7 +790,7 @@ uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
Notify(PSTR("\r\nRequestSense\r\n"), 0x80); Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
Notify(PSTR("----------------\r\n"), 0x80); Notify(PSTR("----------------\r\n"), 0x80);
CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0); CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0UL, (uint8_t)size, 0);
CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN); CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN);
//SetCurLUN(lun); //SetCurLUN(lun);
return Transaction(&cbw, size, buf); return Transaction(&cbw, size, buf);
@ -838,17 +808,17 @@ uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
* @return * @return
*/ */
uint8_t BulkOnly::ClearEpHalt(uint8_t index) { uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
if(index == 0) if (index == 0)
return 0; return 0;
uint8_t ret = 0; uint8_t ret = 0;
while((ret = (pUsb->ctrlReq(bAddress, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT, USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL)) == 0x01)) while ((ret = (pUsb->ctrlReq(bAddress, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT, USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL)) == 0x01))
delay(6); delay(6);
if(ret) { if (ret) {
ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret); ErrorMessage<uint8_t> (PSTR("ClearEpHalt"), ret);
ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr)); ErrorMessage<uint8_t> (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
return ret; return ret;
} }
epInfo[index].bmSndToggle = 0; epInfo[index].bmSndToggle = 0;
@ -861,7 +831,7 @@ uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
* *
*/ */
void BulkOnly::Reset() { void BulkOnly::Reset() {
while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6); while (pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6);
} }
/** /**
@ -889,7 +859,7 @@ uint8_t BulkOnly::ResetRecovery() {
* Clear all EP data and clear all LUN status * Clear all EP data and clear all LUN status
*/ */
void BulkOnly::ClearAllEP() { void BulkOnly::ClearAllEP() {
for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) { for (uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].bmSndToggle = 0; epInfo[i].bmSndToggle = 0;
@ -897,10 +867,10 @@ void BulkOnly::ClearAllEP() {
epInfo[i].bmNakPower = USB_NAK_DEFAULT; epInfo[i].bmNakPower = USB_NAK_DEFAULT;
} }
for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) { for (uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) {
LUNOk[i] = false; LUNOk[i] = false;
WriteOk[i] = false; WriteOk[i] = false;
CurrentCapacity[i] = 0lu; CurrentCapacity[i] = 0UL;
CurrentSectorSize[i] = 0; CurrentSectorSize[i] = 0;
} }
@ -922,11 +892,11 @@ void BulkOnly::ClearAllEP() {
* @return * @return
*/ */
bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) { bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {
if(pcsw->dCSWSignature != MASS_CSW_SIGNATURE) { if (pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
Notify(PSTR("CSW:Sig error\r\n"), 0x80); Notify(PSTR("CSW:Sig error\r\n"), 0x80);
return false; return false;
} }
if(pcsw->dCSWTag != pcbw->dCBWTag) { if (pcsw->dCSWTag != pcbw->dCBWTag) {
Notify(PSTR("CSW:Wrong tag\r\n"), 0x80); Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
return false; return false;
} }
@ -946,47 +916,39 @@ uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
bLastUsbError = error; bLastUsbError = error;
//if (error) //if (error)
//ClearEpHalt(index); //ClearEpHalt(index);
while(error && count) { while (error && count) {
if(error != hrSUCCESS) { if (error != hrSUCCESS) {
ErrorMessage<uint8_t > (PSTR("USB Error"), error); ErrorMessage<uint8_t> (PSTR("USB Error"), error);
ErrorMessage<uint8_t > (PSTR("Index"), index); ErrorMessage<uint8_t> (PSTR("Index"), index);
} }
switch(error) { switch (error) {
// case hrWRONGPID: // case hrWRONGPID:
case hrSUCCESS: case hrSUCCESS: return MASS_ERR_SUCCESS;
return MASS_ERR_SUCCESS; case hrBUSY: return MASS_ERR_UNIT_BUSY; // SIE is busy, just hang out and try again.
case hrBUSY:
// SIE is busy, just hang out and try again.
return MASS_ERR_UNIT_BUSY;
case hrTIMEOUT: case hrTIMEOUT:
case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED; case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED;
case hrSTALL: case hrSTALL:
if(index == 0) if (index) {
return MASS_ERR_STALL;
ClearEpHalt(index); ClearEpHalt(index);
if(index != epDataInIndex) return (index == epDataInIndex) ? MASS_ERR_STALL : MASS_ERR_WRITE_STALL;
return MASS_ERR_WRITE_STALL; }
return MASS_ERR_STALL; return MASS_ERR_STALL;
case hrNAK: case hrNAK:
if(index == 0) return index ? MASS_ERR_UNIT_BUSY : MASS_ERR_UNIT_BUSY;
return MASS_ERR_UNIT_BUSY;
return MASS_ERR_UNIT_BUSY;
case hrTOGERR: case hrTOGERR:
// Handle a very super rare corner case, where toggles become de-synched. // Handle a super rare corner case, where toggles become de-synced.
// I have only ran into one device that has this firmware bug, and this is // I've only run into one device that has this firmware bug, and this is
// the only clean way to get back into sync with the buggy device firmware. // the only clean way to get back into sync with the buggy device firmware.
// --AJK // --AJK
if(bAddress && bConfNum) { if (bAddress && bConfNum) {
error = pUsb->setConf(bAddress, 0, bConfNum); error = pUsb->setConf(bAddress, 0, bConfNum);
if (error) break;
if(error)
break;
} }
return MASS_ERR_SUCCESS; return MASS_ERR_SUCCESS;
default: default:
ErrorMessage<uint8_t > (PSTR("\r\nUSB"), error); ErrorMessage<uint8_t> (PSTR("\r\nUSB"), error);
return MASS_ERR_GENERAL_USB_ERROR; return MASS_ERR_GENERAL_USB_ERROR;
} }
count--; count--;
@ -996,10 +958,9 @@ uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
} }
#if MS_WANT_PARSER #if MS_WANT_PARSER
uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {
uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {
return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0); return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0);
} }
#endif #endif
/** /**
@ -1012,88 +973,88 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
* @return * @return
*/ */
uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf
#if MS_WANT_PARSER #if MS_WANT_PARSER
, uint8_t flags , uint8_t flags
#endif #endif
) { ) {
#if MS_WANT_PARSER
#if MS_WANT_PARSER
uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength; uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
printf("Transfersize %i\r\n", bytes); printf("Transfersize %i\r\n", bytes);
delay(1000); delay(1000);
bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK; bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
#else #else
uint16_t bytes = buf_size; uint16_t bytes = buf_size;
#endif #endif
bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN; bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
uint8_t ret = 0; uint8_t ret = 0;
uint8_t usberr; uint8_t usberr;
CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles. CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
SetCurLUN(pcbw->bmCBWLUN); SetCurLUN(pcbw->bmCBWLUN);
ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag); ErrorMessage<uint32_t> (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1); while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
ret = HandleUsbError(usberr, epDataOutIndex); ret = HandleUsbError(usberr, epDataOutIndex);
//ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex); //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
if(ret) { if (ret)
ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret); ErrorMessage<uint8_t> (PSTR("============================ CBW"), ret);
} else { else {
if(bytes) { if (bytes) {
if(!write) { if (!write) {
#if MS_WANT_PARSER #if MS_WANT_PARSER
if(callback) { if (callback) {
uint8_t rbuf[bytes]; uint8_t rbuf[bytes];
while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1); while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0); if (usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
} else { }
#endif else
while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1); #endif
#if MS_WANT_PARSER {
while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
} }
#endif
ret = HandleUsbError(usberr, epDataInIndex); ret = HandleUsbError(usberr, epDataInIndex);
} else { }
while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1); else {
while ((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
ret = HandleUsbError(usberr, epDataOutIndex); ret = HandleUsbError(usberr, epDataOutIndex);
} }
if(ret) { if (ret) ErrorMessage<uint8_t> (PSTR("============================ DAT"), ret);
ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret);
}
} }
} }
{
bytes = sizeof (CommandStatusWrapper); bytes = sizeof (CommandStatusWrapper);
int tries = 2; int tries = 2;
while(tries--) { while (tries--) {
while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1); while ((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
if(!usberr) break; if (!usberr) break;
ClearEpHalt(epDataInIndex); ClearEpHalt(epDataInIndex);
if(tries) ResetRecovery(); if (tries) ResetRecovery();
} }
if(!ret) {
if (!ret) {
Notify(PSTR("CBW:\t\tOK\r\n"), 0x80); Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
Notify(PSTR("Data Stage:\tOK\r\n"), 0x80); Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
} else { }
else {
// Throw away csw, IT IS NOT OF ANY USE. // Throw away csw, IT IS NOT OF ANY USE.
ResetRecovery(); ResetRecovery();
return ret; return ret;
} }
ret = HandleUsbError(usberr, epDataInIndex); ret = HandleUsbError(usberr, epDataInIndex);
if(ret) { if (ret) ErrorMessage<uint8_t> (PSTR("============================ CSW"), ret);
ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret);
} if (usberr == hrSUCCESS) {
if(usberr == hrSUCCESS) { if (IsValidCSW(&csw, pcbw)) {
if(IsValidCSW(&csw, pcbw)) { //ErrorMessage<uint32_t> (PSTR("CSW.dCBWTag"), csw.dCSWTag);
//ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag); //ErrorMessage<uint8_t> (PSTR("bCSWStatus"), csw.bCSWStatus);
//ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus); //ErrorMessage<uint32_t> (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
//ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80); Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
return csw.bCSWStatus; return csw.bCSWStatus;
} else { }
else {
// NOTE! Sometimes this is caused by the reported residue being wrong. // NOTE! Sometimes this is caused by the reported residue being wrong.
// Get a different device. It isn't compliant, and should have never passed Q&A. // Get a different device. It isn't compliant, and should have never passed Q&A.
// I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter. // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter.
@ -1105,7 +1066,6 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
return MASS_ERR_INVALID_CSW; return MASS_ERR_INVALID_CSW;
} }
} }
}
return ret; return ret;
} }
@ -1116,11 +1076,10 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
* @return * @return
*/ */
uint8_t BulkOnly::SetCurLUN(uint8_t lun) { uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
if(lun > bMaxLUN) if (lun > bMaxLUN) return MASS_ERR_INVALID_LUN;
return MASS_ERR_INVALID_LUN;
bTheLUN = lun; bTheLUN = lun;
return MASS_ERR_SUCCESS; return MASS_ERR_SUCCESS;
}; }
/** /**
* For driver use only. * For driver use only.
@ -1131,55 +1090,54 @@ uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
uint8_t BulkOnly::HandleSCSIError(uint8_t status) { uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
uint8_t ret = 0; uint8_t ret = 0;
switch(status) { switch (status) {
case 0: return MASS_ERR_SUCCESS; case 0: return MASS_ERR_SUCCESS;
case 2: case 2:
ErrorMessage<uint8_t > (PSTR("Phase Error"), status); ErrorMessage<uint8_t> (PSTR("Phase Error"), status);
ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN); ErrorMessage<uint8_t> (PSTR("LUN"), bTheLUN);
ResetRecovery(); ResetRecovery();
return MASS_ERR_GENERAL_SCSI_ERROR; return MASS_ERR_GENERAL_SCSI_ERROR;
case 1: case 1:
ErrorMessage<uint8_t > (PSTR("SCSI Error"), status); ErrorMessage<uint8_t> (PSTR("SCSI Error"), status);
ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN); ErrorMessage<uint8_t> (PSTR("LUN"), bTheLUN);
RequestSenseResponce rsp; RequestSenseResponce rsp;
ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp); ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
if(ret) { if (ret) return MASS_ERR_GENERAL_SCSI_ERROR;
return MASS_ERR_GENERAL_SCSI_ERROR;
} ErrorMessage<uint8_t> (PSTR("Response Code"), rsp.bResponseCode);
ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode); if (rsp.bResponseCode & 0x80) {
if(rsp.bResponseCode & 0x80) {
Notify(PSTR("Information field: "), 0x80); Notify(PSTR("Information field: "), 0x80);
for(int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80); D_PrintHex<uint8_t> (rsp.CmdSpecificInformation[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
} }
ErrorMessage<uint8_t > (PSTR("Sense Key"), rsp.bmSenseKey); ErrorMessage<uint8_t> (PSTR("Sense Key"), rsp.bmSenseKey);
ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode); ErrorMessage<uint8_t> (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier); ErrorMessage<uint8_t> (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
// warning, this is not testing ASQ, only SK and ASC. // warning, this is not testing ASQ, only SK and ASC.
switch(rsp.bmSenseKey) { switch (rsp.bmSenseKey) {
case SCSI_S_UNIT_ATTENTION: case SCSI_S_UNIT_ATTENTION:
switch(rsp.bAdditionalSenseCode) { switch (rsp.bAdditionalSenseCode) {
case SCSI_ASC_MEDIA_CHANGED: case SCSI_ASC_MEDIA_CHANGED:
return MASS_ERR_MEDIA_CHANGED; return MASS_ERR_MEDIA_CHANGED;
default: default:
return MASS_ERR_UNIT_NOT_READY; return MASS_ERR_UNIT_NOT_READY;
} }
case SCSI_S_NOT_READY: case SCSI_S_NOT_READY:
switch(rsp.bAdditionalSenseCode) { switch (rsp.bAdditionalSenseCode) {
case SCSI_ASC_MEDIUM_NOT_PRESENT: case SCSI_ASC_MEDIUM_NOT_PRESENT:
return MASS_ERR_NO_MEDIA; return MASS_ERR_NO_MEDIA;
default: default:
return MASS_ERR_UNIT_NOT_READY; return MASS_ERR_UNIT_NOT_READY;
} }
case SCSI_S_ILLEGAL_REQUEST: case SCSI_S_ILLEGAL_REQUEST:
switch(rsp.bAdditionalSenseCode) { switch (rsp.bAdditionalSenseCode) {
case SCSI_ASC_LBA_OUT_OF_RANGE: case SCSI_ASC_LBA_OUT_OF_RANGE:
return MASS_ERR_BAD_LBA; return MASS_ERR_BAD_LBA;
default: default:
@ -1193,19 +1151,15 @@ uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
// case 0x05/0x14: we stalled out // case 0x05/0x14: we stalled out
// case 0x15/0x16: we naked out. // case 0x15/0x16: we naked out.
default: default:
ErrorMessage<uint8_t > (PSTR("Gen SCSI Err"), status); ErrorMessage<uint8_t> (PSTR("Gen SCSI Err"), status);
ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN); ErrorMessage<uint8_t> (PSTR("LUN"), bTheLUN);
return status; return status;
} // switch } // switch
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Debugging code // Debugging code
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/** /**
@ -1215,17 +1169,17 @@ uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) { void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) {
Notify(PSTR("Endpoint descriptor:"), 0x80); Notify(PSTR("Endpoint descriptor:"), 0x80);
Notify(PSTR("\r\nLength:\t\t"), 0x80); Notify(PSTR("\r\nLength:\t\t"), 0x80);
D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80); D_PrintHex<uint8_t> (ep_ptr->bLength, 0x80);
Notify(PSTR("\r\nType:\t\t"), 0x80); Notify(PSTR("\r\nType:\t\t"), 0x80);
D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80); D_PrintHex<uint8_t> (ep_ptr->bDescriptorType, 0x80);
Notify(PSTR("\r\nAddress:\t"), 0x80); Notify(PSTR("\r\nAddress:\t"), 0x80);
D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80); D_PrintHex<uint8_t> (ep_ptr->bEndpointAddress, 0x80);
Notify(PSTR("\r\nAttributes:\t"), 0x80); Notify(PSTR("\r\nAttributes:\t"), 0x80);
D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80); D_PrintHex<uint8_t> (ep_ptr->bmAttributes, 0x80);
Notify(PSTR("\r\nMaxPktSize:\t"), 0x80); Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80); D_PrintHex<uint16_t> (ep_ptr->wMaxPacketSize, 0x80);
Notify(PSTR("\r\nPoll Intrv:\t"), 0x80); Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80); D_PrintHex<uint8_t> (ep_ptr->bInterval, 0x80);
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
} }
@ -1235,8 +1189,8 @@ void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) {
/* We won't be needing this... */ /* We won't be needing this... */
uint8_t BulkOnly::Read(uint8_t lun __attribute__((unused)), uint32_t addr __attribute__((unused)), uint16_t bsize __attribute__((unused)), uint8_t blocks __attribute__((unused)), USBReadParser * prs __attribute__((unused))) { uint8_t BulkOnly::Read(uint8_t lun __attribute__((unused)), uint32_t addr __attribute__((unused)), uint16_t bsize __attribute__((unused)), uint8_t blocks __attribute__((unused)), USBReadParser * prs __attribute__((unused))) {
#if MS_WANT_PARSER #if MS_WANT_PARSER
if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA; if (!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80); Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
Notify(PSTR("---------\r\n"), 0x80); Notify(PSTR("---------\r\n"), 0x80);
@ -1257,9 +1211,9 @@ uint8_t BulkOnly::Read(uint8_t lun __attribute__((unused)), uint32_t addr __attr
cbw.CBWCB[5] = (addr & 0xff); cbw.CBWCB[5] = (addr & 0xff);
return HandleSCSIError(Transaction(&cbw, bsize, prs, 1)); return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
#else #else
return MASS_ERR_NOT_IMPLEMENTED; return MASS_ERR_NOT_IMPLEMENTED;
#endif #endif
} }
#endif // USB_FLASH_DRIVE_SUPPORT #endif // USB_FLASH_DRIVE_SUPPORT

View file

@ -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);
}; };

View file

@ -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_

View file

@ -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) { void NotifyFail(uint8_t rcode) {
D_PrintHex<uint8_t > (rcode, 0x80); D_PrintHex<uint8_t > (rcode, 0x80);
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
} }
#endif // DEBUG_USB_HOST #endif // DEBUG_USB_HOST
#endif // USB_FLASH_DRIVE_SUPPORT #endif // USB_FLASH_DRIVE_SUPPORT

View file

@ -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__

View file

@ -30,30 +30,28 @@
#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));
@ -66,12 +64,9 @@ bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf,
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)
pf(pBuf, (arLen - arLenCntdn), me);
} }
nStage = 0; nStage = 0;

View file

@ -22,11 +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(__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;
@ -43,14 +43,12 @@ 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);
}; };
@ -63,26 +61,26 @@ class ByteSkipper {
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
@ -122,8 +120,8 @@ public:
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;
@ -131,18 +129,17 @@ public:
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 { }
else {
arLenCntdn = arLen = 0; arLenCntdn = arLen = 0;
nStage = 0; nStage = 0;
} }
enStage = 0; enStage = 0;
theParser.Initialize(p); 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__

View file

@ -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)
prn->print("0");
mask >>= 4; mask >>= 4;
} }
prn->print((T)val, HEX); 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__

View file

@ -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.

View file

@ -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_