parent
e5929ea3d8
commit
9dfd5e6009
@ -0,0 +1,175 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : stm32f4xx_hal_msp.c
|
||||
* Date : 03/02/2015 20:27:00
|
||||
* Description : This file provides code for the MSP Initialization
|
||||
* and de-Initialization codes.
|
||||
******************************************************************************
|
||||
*
|
||||
* COPYRIGHT(c) 2015 STMicroelectronics
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* Modifications by Robert Fisk
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include "interrupts.h"
|
||||
#include "board_config.h"
|
||||
|
||||
|
||||
DMA_HandleTypeDef spiTxDmaHandle;
|
||||
DMA_HandleTypeDef spiRxDmaHandle;
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the Global MSP.
|
||||
*/
|
||||
void HAL_MspInit(void)
|
||||
{
|
||||
// HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
|
||||
//
|
||||
// /* System interrupt init*/
|
||||
///* SysTick_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(SysTick_IRQn, INT_PRIORITY_SYSTICK, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint32_t HAL_GetHSECrystalFreqMHz(void)
|
||||
{
|
||||
if ((BOARD_REV_ID_PORT->IDR & BOARD_REV_PIN_MASK) < BOARD_REV_1_0_BETA_3)
|
||||
{
|
||||
return BOARD_REV_1_0_BETA_FREQ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BOARD_REV_1_0_BETA_3_FREQ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
if(hspi->Instance==SPI1)
|
||||
{
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_SPI1_CLK_ENABLE();
|
||||
__HAL_RCC_DMA2_CLK_ENABLE();
|
||||
|
||||
/**SPI1 GPIO Configuration
|
||||
PA4 ------> GPIO manual slave select
|
||||
PA5 ------> SPI1_SCK
|
||||
PA6 ------> SPI1_MISO
|
||||
PA7 ------> SPI1_MOSI
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
SPI1_NSS_DEASSERT;
|
||||
GPIO_InitStruct.Pin = SPI1_NSS_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(SPI1_NSS_PORT, &GPIO_InitStruct);
|
||||
|
||||
//Configure downstream request pin and interrupt
|
||||
GPIO_InitStruct.Pin = DOWNSTREAM_TX_OK_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT | GPIO_MODE_IT_FALLING;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
HAL_GPIO_Init(DOWNSTREAM_TX_OK_PORT, &GPIO_InitStruct);
|
||||
HAL_NVIC_SetPriority(EXTI3_IRQn, INT_PRIORITY_EXT3I, 0);
|
||||
HAL_NVIC_EnableIRQ(EXTI3_IRQn);
|
||||
|
||||
//Prepare Tx DMA stream
|
||||
hspi->hdmatx = &spiTxDmaHandle;
|
||||
spiTxDmaHandle.Instance = DMA2_Stream3;
|
||||
spiTxDmaHandle.Parent = hspi;
|
||||
spiTxDmaHandle.Init.Channel = DMA_CHANNEL_3;
|
||||
spiTxDmaHandle.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
spiTxDmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
spiTxDmaHandle.Init.MemInc = DMA_MINC_ENABLE;
|
||||
spiTxDmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
|
||||
spiTxDmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
|
||||
spiTxDmaHandle.Init.Mode = DMA_NORMAL;
|
||||
spiTxDmaHandle.Init.Priority = DMA_PRIORITY_MEDIUM;
|
||||
spiTxDmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
|
||||
HAL_DMA_Init(&spiTxDmaHandle);
|
||||
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, INT_PRIORITY_SPI_DMA, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
|
||||
|
||||
//Prepare Rx DMA stream
|
||||
hspi->hdmarx = &spiRxDmaHandle;
|
||||
spiRxDmaHandle.Instance = DMA2_Stream2;
|
||||
spiRxDmaHandle.Parent = hspi;
|
||||
spiRxDmaHandle.Init.Channel = DMA_CHANNEL_3;
|
||||
spiRxDmaHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
spiRxDmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
spiRxDmaHandle.Init.MemInc = DMA_MINC_ENABLE;
|
||||
spiRxDmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
|
||||
spiRxDmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
|
||||
spiRxDmaHandle.Init.Mode = DMA_NORMAL;
|
||||
spiRxDmaHandle.Init.Priority = DMA_PRIORITY_MEDIUM;
|
||||
spiRxDmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
|
||||
HAL_DMA_Init(&spiRxDmaHandle);
|
||||
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, INT_PRIORITY_SPI_DMA, 0);
|
||||
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
|
||||
{
|
||||
|
||||
if(hspi->Instance==SPI1)
|
||||
{
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_SPI1_CLK_DISABLE();
|
||||
__HAL_RCC_DMA2_CLK_DISABLE();
|
||||
|
||||
/**SPI1 GPIO Configuration
|
||||
PA4 ------> SPI1_NSS
|
||||
PA5 ------> SPI1_SCK
|
||||
PA6 ------> SPI1_MISO
|
||||
PA7 ------> SPI1_MOSI
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
|
||||
HAL_DMA_DeInit(&spiTxDmaHandle);
|
||||
HAL_DMA_DeInit(&spiRxDmaHandle);
|
||||
|
||||
HAL_NVIC_DisableIRQ(DMA2_Stream3_IRQn);
|
||||
HAL_NVIC_DisableIRQ(DMA2_Stream2_IRQn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
@ -0,0 +1,129 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f4xx_it.c
|
||||
* @date 03/02/2015 20:27:00
|
||||
* @brief Interrupt Service Routines.
|
||||
******************************************************************************
|
||||
*
|
||||
* COPYRIGHT(c) 2015 STMicroelectronics
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* Modifications by Robert Fisk
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "interrupts.h"
|
||||
#include "upstream_spi.h"
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include "board_config.h"
|
||||
#include "build_config.h"
|
||||
#include "led.h"
|
||||
#include "upstream_hid_botdetect.h"
|
||||
#include "upstream_statemachine.h"
|
||||
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
/* External variables --------------------------------------------------------*/
|
||||
|
||||
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
|
||||
extern DMA_HandleTypeDef spiTxDmaHandle;
|
||||
extern DMA_HandleTypeDef spiRxDmaHandle;
|
||||
|
||||
uint8_t BusFaultAllowed = 0;
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cortex-M4 Processor Interruption and Exception Handlers */
|
||||
/******************************************************************************/
|
||||
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
HAL_IncTick();
|
||||
LED_Tick();
|
||||
Upstream_StateMachine_PollDeviceConnected();
|
||||
|
||||
#if (defined (CONFIG_KEYBOARD_ENABLED) && defined (CONFIG_KEYBOARD_BOT_DETECT_ENABLED)) || \
|
||||
(defined (CONFIG_MOUSE_ENABLED) && defined (CONFIG_MOUSE_BOT_DETECT_ENABLED))
|
||||
Upstream_HID_BotDetect_Systick();
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
//All interrupts in this section must be at the same priority.
|
||||
//They interact with each other, and calls are not thread-safe
|
||||
//when different interrupt priorities are used.
|
||||
/////////////////////////
|
||||
void OTG_FS_IRQHandler(void)
|
||||
{
|
||||
HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
|
||||
}
|
||||
|
||||
void DMA2_Stream2_IRQHandler(void)
|
||||
{
|
||||
HAL_DMA_IRQHandler(&spiRxDmaHandle);
|
||||
}
|
||||
|
||||
void DMA2_Stream3_IRQHandler(void)
|
||||
{
|
||||
HAL_DMA_IRQHandler(&spiTxDmaHandle);
|
||||
}
|
||||
|
||||
void EXTI3_IRQHandler(void)
|
||||
{
|
||||
__HAL_GPIO_EXTI_CLEAR_IT(DOWNSTREAM_TX_OK_PIN);
|
||||
Upstream_TxOkInterrupt();
|
||||
}
|
||||
/////////////////////////
|
||||
/////////////////////////
|
||||
|
||||
|
||||
//This weird stuff is required when disabling flash writes.
|
||||
//The deliberate flash lockout will cause a bus fault that we need to process.
|
||||
void EnableOneBusFault(void)
|
||||
{
|
||||
//It should not be enabled already!
|
||||
if (BusFaultAllowed)
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
SCB->SHCSR = SCB_SHCSR_BUSFAULTENA_Msk;
|
||||
BusFaultAllowed = 1;
|
||||
}
|
||||
|
||||
void BusFault_Handler(void)
|
||||
{
|
||||
if (BusFaultAllowed)
|
||||
{
|
||||
BusFaultAllowed = 0;
|
||||
return;
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* led.c
|
||||
*
|
||||
* Created on: 19/08/2015
|
||||
* Author: Robert Fisk
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
#include "led.h"
|
||||
#include "board_config.h"
|
||||
#include "build_config.h"
|
||||
|
||||
uint32_t FaultLedCounter;
|
||||
uint32_t ReadWriteFlashEndTime;
|
||||
|
||||
LedStatusTypeDef FaultLedState;
|
||||
uint16_t FaultLedOnMs;
|
||||
uint16_t FaultLedOffMs;
|
||||
uint8_t FaultLedBlinkCount;
|
||||
|
||||
uint8_t FaultLedBlinkCountState;
|
||||
uint8_t FaultLedOutputState;
|
||||
|
||||
|
||||
void LED_Init(void)
|
||||
{
|
||||
FAULT_LED_ON;
|
||||
ReadWriteFlashEndTime = 0;
|
||||
FaultLedState = LED_STATUS_STARTUP;
|
||||
}
|
||||
|
||||
|
||||
void LED_SetState(LedStatusTypeDef newState)
|
||||
{
|
||||
switch (newState)
|
||||
{
|
||||
case LED_STATUS_OFF:
|
||||
FaultLedCounter = UINT32_MAX;
|
||||
FaultLedBlinkCountState = 0;
|
||||
FaultLedOutputState = 0;
|
||||
FAULT_LED_OFF;
|
||||
break;
|
||||
|
||||
case LED_STATUS_FLASH_UNSUPPORTED:
|
||||
FaultLedOnMs = LED_UNSUPPORTED_BLINK_MS;
|
||||
FaultLedOffMs = LED_UNSUPPORTED_BLINK_MS;
|
||||
FaultLedBlinkCount = 1;
|
||||
break;
|
||||
|
||||
case LED_STATUS_FLASH_BOTDETECT:
|
||||
FaultLedOnMs = LED_BOTDETECT_ON_MS;
|
||||
FaultLedOffMs = LED_BOTDETECT_OFF_MS;
|
||||
FaultLedBlinkCount = 2;
|
||||
break;
|
||||
|
||||
case LED_STATUS_FLASH_READWRITE:
|
||||
#ifdef CONFIG_WRITE_FLASH_TIME_MS
|
||||
if (FaultLedState == LED_STATUS_OFF)
|
||||
{
|
||||
FaultLedOnMs = LED_READWRITE_ON_MS;
|
||||
FaultLedOffMs = LED_READWRITE_OFF_MS;
|
||||
FaultLedBlinkCount = 1;
|
||||
ReadWriteFlashEndTime = HAL_GetTick() + CONFIG_WRITE_FLASH_TIME_MS;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
newState = FaultLedState; //Don't override other active states
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FaultLedOnMs = LED_ERROR_BLINK_MS; //Everything else is LED_STATUS_ERROR
|
||||
FaultLedOffMs = LED_ERROR_BLINK_MS;
|
||||
FaultLedBlinkCount = 1;
|
||||
}
|
||||
|
||||
FaultLedState = newState;
|
||||
}
|
||||
|
||||
|
||||
void LED_Tick(void)
|
||||
{
|
||||
if (FaultLedState == LED_STATUS_OFF) return;
|
||||
|
||||
if (FaultLedState == LED_STATUS_STARTUP)
|
||||
{
|
||||
if (HAL_GetTick() >= STARTUP_FLASH_DELAY_MS)
|
||||
{
|
||||
LED_SetState(LED_STATUS_OFF);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WRITE_FLASH_TIME_MS
|
||||
if (FaultLedState == LED_STATUS_FLASH_READWRITE)
|
||||
{
|
||||
if ((int32_t)(HAL_GetTick() - ReadWriteFlashEndTime) > 0)
|
||||
{
|
||||
LED_SetState(LED_STATUS_OFF);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (FaultLedOutputState)
|
||||
{
|
||||
if (FaultLedCounter++ >= FaultLedOnMs) //Check to turn LED off
|
||||
{
|
||||
FaultLedBlinkCountState++;
|
||||
FaultLedCounter = 0;
|
||||
FaultLedOutputState = 0;
|
||||
FAULT_LED_OFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FaultLedBlinkCountState >= FaultLedBlinkCount) //Checks to turn LED on...
|
||||
{
|
||||
if (FaultLedCounter++ >= FaultLedOffMs) //Last flash may have longer off-time
|
||||
{
|
||||
FaultLedBlinkCountState = 0;
|
||||
FaultLedCounter = 0;
|
||||
FaultLedOutputState = 1;
|
||||
FAULT_LED_ON;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FaultLedCounter++ >= FaultLedOnMs) //Flash sequence uses on-time as intermediate off-time
|
||||
{
|
||||
FaultLedCounter = 0;
|
||||
FaultLedOutputState = 1;
|
||||
FAULT_LED_ON;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,258 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : main.c
|
||||
* Date : 03/02/2015 20:27:01
|
||||
* Description : Main program body
|
||||
******************************************************************************
|
||||
*
|
||||
* COPYRIGHT(c) 2015 STMicroelectronics
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* Modifications by Robert Fisk
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include "usb_device.h"
|
||||
#include "board_config.h"
|
||||
#include "led.h"
|
||||
#include "upstream_statemachine.h"
|
||||
#include "upstream_spi.h"
|
||||
#include "interrupts.h"
|
||||
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static void SystemClock_Config(void);
|
||||
static void GPIO_Init(void);
|
||||
static void DisableFlashWrites(void);
|
||||
static void CheckFirmwareMatchesHardware(void);
|
||||
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
//First things first!
|
||||
DisableFlashWrites();
|
||||
CheckFirmwareMatchesHardware();
|
||||
|
||||
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
|
||||
HAL_Init();
|
||||
|
||||
/* Configure the system clock */
|
||||
SystemClock_Config();
|
||||
|
||||
/* Initialize all configured peripherals */
|
||||
GPIO_Init();
|
||||
LED_Init();
|
||||
Upstream_InitStateMachine();
|
||||
|
||||
HAL_Delay(200); //Delay executing WFI to avoid destroying JTAG access
|
||||
|
||||
while (1)
|
||||
{
|
||||
__WFI(); //sleep time!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DisableFlashWrites(void)
|
||||
{
|
||||
//Disable flash writes until the next reset
|
||||
//This will cause a bus fault interrupt, so allow one now.
|
||||
EnableOneBusFault();
|
||||
FLASH->KEYR = 999;
|
||||
|
||||
//Confirm that flash cannot be unlocked
|
||||
//This unlock attempt will also cause two bus faults.
|
||||
if ((FLASH->CR & FLASH_CR_LOCK) == 0) while(1);
|
||||
EnableOneBusFault();
|
||||
FLASH->KEYR = FLASH_KEY1;
|
||||
EnableOneBusFault();
|
||||
FLASH->KEYR = FLASH_KEY2;
|
||||
if ((FLASH->CR & FLASH_CR_LOCK) == 0) while(1);
|
||||
}
|
||||
|
||||
|
||||
void CheckFirmwareMatchesHardware(void)
|
||||
{
|
||||
//Check we are running on the expected hardware:
|
||||
//STM32F401RC on USG v1.0 beta
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
|
||||
if ((*(uint32_t*)DBGMCU_BASE & DBGMCU_IDCODE_DEV_ID) == DBGMCU_IDCODE_DEV_ID_401xB_xC)
|
||||
{
|
||||
//Read in board revision and ID on port C
|
||||
GPIO_InitStruct.Pin = BOARD_REV_PIN_MASK | BOARD_ID_PIN_MASK;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
|
||||
GPIO_InitStruct.Alternate = 0;
|
||||
HAL_GPIO_Init(BOARD_REV_ID_PORT, &GPIO_InitStruct);
|
||||
|
||||
//Correct board revision?
|
||||
if ((BOARD_REV_ID_PORT->IDR & BOARD_REV_PIN_MASK) <= BOARD_REV_1_0_BETA_3)
|
||||
{
|
||||
//Correct board ID: upstream?
|
||||
if ((BOARD_REV_ID_PORT->IDR & BOARD_ID_PIN_MASK))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//This is not the hardware we expected, so turn on our fault LED(s) and die in a heap.
|
||||
GPIO_InitStruct.Pin = FAULT_LED_PIN | H405_FAULT_LED_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(FAULT_LED_PORT, &GPIO_InitStruct);
|
||||
FAULT_LED_ON;
|
||||
H405_FAULT_LED_ON;
|
||||
while (1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** System Clock Configuration
|
||||
*/
|
||||
void SystemClock_Config(void)
|
||||
{
|
||||
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct;
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct;
|
||||
|
||||
__PWR_CLK_ENABLE();
|
||||
|
||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
|
||||
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = (HAL_GetHSECrystalFreqMHz() / 2); //PLL input frequency = 2MHz
|
||||
RCC_OscInitStruct.PLL.PLLN = 168;
|
||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 7;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) while (1);
|
||||
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK |
|
||||
RCC_CLOCKTYPE_HCLK |
|
||||
RCC_CLOCKTYPE_PCLK1 |
|
||||
RCC_CLOCKTYPE_PCLK2;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) while(1);
|
||||
|
||||
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Configure pins as
|
||||
* Analog
|
||||
* Input
|
||||
* Output
|
||||
* EVENT_OUT
|
||||
* EXTI
|
||||
*/
|
||||
void GPIO_Init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
//__HAL_RCC_GPIOH_CLK_ENABLE(); //HS oscillator on port H
|
||||
|
||||
//Bulk initialise all ports as inputs with pullups active,
|
||||
//excluding JTAG pins which must remain as AF0!
|
||||
GPIO_InitStruct.Pin = (GPIO_PIN_All & ~(PA_JTMS | PA_JTCK | PA_JTDI));
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
|
||||
GPIO_InitStruct.Alternate = 0;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
GPIO_InitStruct.Pin = (GPIO_PIN_All & ~(PB_JTDO | PB_NJTRST));
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_All;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||||
|
||||
//Fault LED is output
|
||||
GPIO_InitStruct.Pin = FAULT_LED_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(FAULT_LED_PORT, &GPIO_InitStruct);
|
||||
FAULT_LED_OFF;
|
||||
|
||||
// //SPI_INT_ACTIVE indicator
|
||||
// GPIO_InitStruct.Pin = INT_ACTIVE_PIN;
|
||||
// //GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
// //GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
// HAL_GPIO_Init(INT_ACTIVE_PORT, &GPIO_InitStruct);
|
||||
// INT_ACTIVE_OFF;
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 4 */
|
||||
|
||||
/* USER CODE END 4 */
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
|
||||
/**
|
||||
* @brief Reports the name of the source file and the source line number
|
||||
* where the assert_param error has occurred.
|
||||
* @param file: pointer to the source file name
|
||||
* @param line: assert_param error line source number
|
||||
* @retval None
|
||||
*/
|
||||
void assert_failed(uint8_t* file, uint32_t line)
|
||||
{
|
||||
/* USER CODE BEGIN 6 */
|
||||
/* User can add his own implementation to report the file name and line number,
|
||||
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
|
||||
/* USER CODE END 6 */
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* upstream_hid.c
|
||||
*
|
||||
* Created on: Jan 16, 2016
|
||||
* Author: Robert Fisk
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "upstream_hid.h"
|
||||
#include "upstream_hid_botdetect.h"
|
||||
#include "upstream_interface_def.h"
|
||||
#include "build_config.h"
|
||||
|
||||
|
||||
#if defined (CONFIG_KEYBOARD_ENABLED) || defined (CONFIG_MOUSE_ENABLED)
|
||||
|
||||
|
||||
UpstreamPacketTypeDef* UpstreamHidPacket = NULL;
|
||||
UpstreamHidGetReportCallback GetReportCallback = NULL;
|
||||
|
||||
#ifdef CONFIG_KEYBOARD_ENABLED
|
||||
KeyboardOutStateTypeDef KeyboardOutDataState = KEYBOARD_OUT_STATE_IDLE;
|
||||
uint8_t KeyboardOutData[HID_KEYBOARD_OUTPUT_DATA_LEN];
|
||||
#endif
|
||||
|
||||
uint8_t GetReportLoopIsRunning = 0;
|
||||
|
||||
|
||||
static void Upstream_HID_ReceiveInterruptReport(void);
|
||||
static void Upstream_HID_ReceiveInterruptReportCallback(UpstreamPacketTypeDef* receivedPacket);
|
||||
static void Upstream_HID_SendControlReport(void);
|
||||
static void Upstream_HID_SendControlReportCallback(UpstreamPacketTypeDef* receivedPacket);
|
||||
|
||||
|
||||
|
||||
void Upstream_HID_DeInit(void)
|
||||
{
|
||||
if (UpstreamHidPacket != NULL)
|
||||
{
|
||||
Upstream_ReleasePacket(UpstreamHidPacket);
|
||||
UpstreamHidPacket = NULL;
|
||||
}
|
||||
GetReportCallback = NULL;
|
||||
GetReportLoopIsRunning = 0;
|
||||
|
||||
#ifdef CONFIG_KEYBOARD_ENABLED
|
||||
KeyboardOutDataState = KEYBOARD_OUT_STATE_IDLE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Called by usbd_hid to request our next interrupt report
|
||||
void Upstream_HID_GetInterruptReport(UpstreamHidGetReportCallback callback)
|
||||
{
|
||||
GetReportCallback = callback;
|
||||
|
||||
if (UpstreamHidPacket != NULL)
|
||||
{
|
||||
Upstream_ReleasePacket(UpstreamHidPacket);
|
||||
UpstreamHidPacket = NULL;
|
||||
}
|
||||
|
||||
//Wakeup interrupts are apparently broken.
|
||||
//So we check for resume when the host sends us something here.
|
||||
Upstream_StateMachine_CheckResume();
|
||||
|
||||
//Start our internal loop?
|
||||
if (!GetReportLoopIsRunning)
|
||||
{
|
||||
GetReportLoopIsRunning = 1;
|
||||
Upstream_HID_ReceiveInterruptReport();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Our internal report request loop
|
||||
static void Upstream_HID_ReceiveInterruptReport(void)
|
||||
{
|
||||
UpstreamPacketTypeDef* freePacket;
|
||||
InterfaceCommandClassTypeDef activeClass;
|
||||
|
||||
activeClass = Upstream_StateMachine_CheckActiveClass();
|
||||
if ((activeClass != COMMAND_CLASS_HID_MOUSE) &&
|
||||
(activeClass != COMMAND_CLASS_HID_KEYBOARD)) //add classes here
|
||||
{
|
||||
UPSTREAM_STATEMACHINE_FREAKOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
freePacket = Upstream_GetFreePacketImmediately();
|
||||
if (freePacket == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
freePacket->Length16 = UPSTREAM_PACKET_HEADER_LEN_16;
|
||||
freePacket->CommandClass = activeClass;
|
||||
freePacket->Command = COMMAND_HID_GET_REPORT;
|
||||
|
||||
if (Upstream_TransmitPacket(freePacket) == HAL_OK)
|
||||
{
|
||||
Upstream_ReceivePacket(Upstream_HID_ReceiveInterruptReportCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
Upstream_ReleasePacket(freePacket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Upstream_HID_ReceiveInterruptReportCallback(UpstreamPacketTypeDef* receivedPacket)
|
||||
{
|
||||
UpstreamHidGetReportCallback tempReportCallback;
|
||||
InterfaceCommandClassTypeDef activeClass;
|
||||
uint32_t i;
|
||||
uint8_t dataLength;
|
||||
|
||||
|
||||
activeClass = Upstream_StateMachine_CheckActiveClass();
|
||||
if ((activeClass != COMMAND_CLASS_HID_MOUSE) &&
|
||||
(activeClass != COMMAND_CLASS_HID_KEYBOARD)) //add classes here
|
||||
{
|
||||
UPSTREAM_STATEMACHINE_FREAKOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
if (receivedPacket == NULL) //Error receiving packet
|
||||
{
|
||||
return; //Just give up...
|
||||
}
|
||||
|
||||
if (receivedPacket->Length16 == UPSTREAM_PACKET_HEADER_LEN_16)
|
||||
{
|
||||
//Zero-length reply indicates no data from downstream device
|
||||
Upstream_ReleasePacket(receivedPacket);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef CONFIG_MOUSE_ENABLED
|
||||
if (activeClass == COMMAND_CLASS_HID_MOUSE)
|
||||
{
|
||||
if (receivedPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_MOUSE_INPUT_DATA_LEN + 1) / 2)))
|
||||
{
|
||||
UPSTREAM_STATEMACHINE_FREAKOUT;
|
||||
return;
|
||||
}
|
||||
dataLength = HID_MOUSE_INPUT_DATA_LEN;
|
||||
if ((receivedPacket->Data[0] & ~((1 << HID_MOUSE_MAX_BUTTONS) - 1)) != 0) //Check number of buttons received
|
||||
{
|
||||
UPSTREAM_STATEMACHINE_FREAKOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
//Mouse wakeup is triggered by button clicks only
|
||||
if (receivedPacket->Data[0] != 0)
|
||||
{
|
||||
if (Upstream_StateMachine_GetSuspendState())
|
||||
{
|
||||
Upstream_StateMachine_Wakeup(); //Send wakeup signal to host
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MOUSE_BOT_DETECT_ENABLED
|
||||
Upstream_HID_BotDetectMouse(receivedPacket->Data);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_KEYBOARD_ENABLED
|
||||
if (activeClass == COMMAND_CLASS_HID_KEYBOARD)
|
||||
{
|
||||
if (receivedPacket->Length16 != (UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_KEYBOARD_INPUT_DATA_LEN + 1) / 2)))
|
||||
{
|
||||
UPSTREAM_STATEMACHINE_FREAKOUT;
|
||||
return;
|
||||
}
|
||||
dataLength = HID_KEYBOARD_INPUT_DATA_LEN;
|
||||
|
||||
if (receivedPacket->Data[1] != 0)
|
||||
{
|
||||
UPSTREAM_STATEMACHINE_FREAKOUT;
|
||||
return;
|
||||
}
|
||||
for (i = 2; i < HID_KEYBOARD_INPUT_DATA_LEN; i++)
|
||||
{
|
||||
if (receivedPacket->Data[i] > HID_KEYBOARD_MAX_KEY)
|
||||
{
|
||||
UPSTREAM_STATEMACHINE_FREAKOUT;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Upstream_StateMachine_GetSuspendState())
|
||||
{
|
||||
Upstream_StateMachine_Wakeup(); //Send wakeup signal to host
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KEYBOARD_BOT_DETECT_ENABLED
|
||||
Upstream_HID_BotDetectKeyboard(receivedPacket->Data);
|
||||
#endif
|
||||
}
|
||||
|
||||
//Other HID classes go here...
|
||||
else
|
||||
#endif
|
||||
|
||||
{
|
||||
UPSTREAM_STATEMACHINE_FREAKOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((GetReportCallback == NULL) ||
|
||||
(UpstreamHidPacket != NULL) ||
|
||||
(Upstream_StateMachine_GetSuspendState()))
|
||||
{
|
||||
Upstream_ReleasePacket(receivedPacket);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Send resulting data to host
|
||||
UpstreamHidPacket = receivedPacket; //Save packet so we can free it when upstream USB transaction is done
|
||||
tempReportCallback = GetReportCallback;
|
||||
GetReportCallback = NULL;
|
||||
tempReportCallback(receivedPacket->Data, dataLength);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetReportLoopIsRunning)
|
||||
{
|
||||
#ifdef CONFIG_KEYBOARD_ENABLED
|
||||
//Check if we need to send OUT data to the keyboard before requesting next Interrupt IN data
|
||||
if (KeyboardOutDataState == KEYBOARD_OUT_STATE_DATA_READY)
|
||||
{
|
||||
Upstream_HID_SendControlReport();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Upstream_HID_ReceiveInterruptReport(); //Otherwise poll downstream again
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef CONFIG_KEYBOARD_ENABLED
|
||||
void Upstream_HID_RequestSendControlReport(UpstreamPacketTypeDef* packetToSend, uint8_t dataLength)
|
||||
{
|
||||
InterfaceCommandClassTypeDef activeClass;
|
||||
uint32_t i;
|
||||
|
||||
activeClass = Upstream_StateMachine_CheckActiveClass();
|
||||
if ((packetToSend == NULL) ||
|
||||
(activeClass != COMMAND_CLASS_HID_KEYBOARD) ||
|
||||
(dataLength != HID_KEYBOARD_OUTPUT_DATA_LEN))
|
||||
{
|
||||
UPSTREAM_STATEMACHINE_FREAKOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
//Save data until after the next interrupt data is received from Downstream
|
||||
KeyboardOutDataState = KEYBOARD_OUT_STATE_DATA_READY;
|
||||
for (i = 0; i < HID_KEYBOARD_OUTPUT_DATA_LEN; i++)
|
||||
{
|
||||
KeyboardOutData[i] = packetToSend->Data[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Upstream_HID_SendControlReport(void)
|
||||
{
|
||||
UpstreamPacketTypeDef* freePacket;
|
||||
uint32_t i;
|
||||
|
||||
KeyboardOutDataState = KEYBOARD_OUT_STATE_BUSY;
|
||||
|
||||
freePacket = Upstream_GetFreePacketImmediately();
|
||||
if (freePacket == NULL) return;
|
||||
|
||||
freePacket->Length16 = UPSTREAM_PACKET_HEADER_LEN_16 + ((HID_KEYBOARD_OUTPUT_DATA_LEN + 1) / 2);
|
||||
freePacket->CommandClass = COMMAND_CLASS_HID_KEYBOARD;
|
||||
freePacket->Command = COMMAND_HID_SET_REPORT;
|
||||
|
||||
for (i = 0; i < HID_KEYBOARD_OUTPUT_DATA_LEN; i++)
|
||||
{
|
||||
freePacket->Data[i] = KeyboardOutData[i];
|
||||
}
|
||||
freePacket->Data[0] &= ((1 << HID_KEYBOARD_MAX_LED) - 1);
|
||||
|
||||
if (Upstream_TransmitPacket(freePacket) == HAL_OK)
|
||||
{
|
||||
Upstream_ReceivePacket(Upstream_HID_SendControlReportCallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
Upstream_ReleasePacket(freePacket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Upstream_HID_SendControlReportCallback(UpstreamPacketTypeDef* receivedPacket)
|
||||
{
|
||||
InterfaceCommandClassTypeDef activeClass;
|
||||
|
||||
activeClass = Upstream_StateMachine_CheckActiveClass();
|
||||
if (activeClass != COMMAND_CLASS_HID_KEYBOARD) //add classes here
|
||||
{
|
||||
UPSTREAM_STATEMACHINE_FREAKOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
if (receivedPacket == NULL)
|
||||
{
|
||||
return; //Just give up...
|
||||
}
|
||||
|
||||
Upstream_ReleasePacket(receivedPacket);
|
||||
KeyboardOutDataState = KEYBOARD_OUT_STATE_IDLE;
|
||||
Upstream_HID_ReceiveInterruptReport();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //#if defined (CONFIG_KEYBOARD_ENABLED) || defined (CONFIG_MOUSE_ENABLED)
|
||||
|
@ -0,0 +1,608 @@
|
||||
/*
|
||||
* upstream_hid_botdetect.c
|
||||
*
|
||||
* Created on: Aug 17, 2017
|
||||
* Author: Robert Fisk
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
#include "upstream_hid_botdetect.h"
|
||||
#include "upstream_hid.h"
|
||||
#include "build_config.h"
|
||||
#include "usbd_hid.h"
|
||||
#include "math.h"
|
||||
|
||||
|
||||
|
||||
//Variables common between keyboard and mouse bot detection:
|
||||
volatile LockoutStateTypeDef LockoutState = LOCKOUT_STATE_INACTIVE;
|
||||
uint32_t TemporaryLockoutTimeMs;
|
||||
uint8_t TemporaryLockoutCount = 0;
|
||||
|
||||
|
||||
//Variables specific to keyboard bot detection:
|
||||
#if defined (CONFIG_KEYBOARD_ENABLED) && defined (CONFIG_KEYBOARD_BOT_DETECT_ENABLED)
|
||||
uint32_t LastKeyDownTime = 0;
|
||||
KeyTimerLogTypeDef KeyTimerLog[KEYBOARD_BOTDETECT_MAX_ACTIVE_KEYS] = {0};
|
||||
uint8_t OldKeyboardInData[HID_KEYBOARD_INPUT_DATA_LEN] = {0};
|
||||
|
||||
uint8_t KeyDelayFastBinDrainDivideCount = 0;
|
||||
uint8_t KeyDelaySlowBinDrainDivideCount = 0;
|
||||
uint8_t KeyDowntimeFastBinDrainDivideCount = 0;
|
||||
uint8_t KeyDowntimeSlowBinDrainDivideCount = 0;
|
||||
uint8_t KeyDelayFastBinArray[KEYBOARD_BOTDETECT_FAST_BIN_COUNT] = {0};
|
||||
uint8_t KeyDelaySlowBinArray[KEYBOARD_BOTDETECT_SLOW_BIN_COUNT] = {0};
|
||||
uint8_t KeyDowntimeFastBinArray[KEYBOARD_BOTDETECT_FAST_BIN_COUNT] = {0};
|
||||
uint8_t KeyDowntimeSlowBinArray[KEYBOARD_BOTDETECT_SLOW_BIN_COUNT] = {0};
|
||||
|
||||
//Debug:
|
||||
// uint8_t KeyDelayFastBinArrayPeak;
|
||||
// uint8_t KeyDelaySlowBinArrayPeak;
|
||||
// uint8_t KeyDowntimeFastBinArrayPeak;
|
||||
// uint8_t KeyDowntimeSlowBinArrayPeak;
|
||||
|
||||
static uint32_t Upstream_HID_BotDetectKeyboard_RolloverCheck(uint8_t* keyboardInData);
|
||||
static void Upstream_HID_BotDetectKeyboard_DoLockout(void);
|
||||
static void Upstream_HID_BotDetectKeyboard_KeyDown(uint8_t keyCode);
|
||||
static void Upstream_HID_BotDetectKeyboard_KeyUp(uint8_t keyCode);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//Variables specific to mouse bot detection:
|
||||
#if defined (CONFIG_MOUSE_ENABLED) && defined (CONFIG_MOUSE_BOT_DETECT_ENABLED)
|
||||
uint32_t LastMouseMoveTime = 0;
|
||||
|
||||
//Jump detection stuff
|
||||
uint32_t FirstMouseMoveTime = 0;
|
||||
uint8_t JumpMouseIsMoving = 0;
|
||||
|
||||
//Constant acceleration detection stuff
|
||||
uint16_t MouseVelocityHistory[MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE] = {0};
|
||||
int32_t PreviousSmoothedAcceleration = 0;
|
||||
int32_t ConstantAccelerationCounter = 0;
|
||||
|
||||
//Jiggle detection stuff
|
||||
uint8_t MouseStopIntervalBinDrainDivideCount = 0;
|
||||
uint8_t MouseStopIntervalBinArray[MOUSE_BOTDETECT_JIGGLE_BIN_COUNT] = {0};
|
||||
|
||||
//Debug:
|
||||
// int8_t ConstantAccelerationCounterMax = 0;
|
||||
// int8_t ConstantAccelerationCounterMin = 0;
|
||||
// uint8_t MouseStopIntervalBinArrayPeak = 0;
|
||||
|
||||
static void Upstream_HID_BotDetectMouse_DoLockout(void);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//Code specific to keyboard bot detection:
|
||||
#if defined (CONFIG_KEYBOARD_ENABLED) && defined (CONFIG_KEYBOARD_BOT_DETECT_ENABLED)
|
||||
|
||||
//Checks if received keyboard data is from a real human.
|
||||
//This is not entirely bulletproof as an attacking device may randomize its keypresses.
|
||||
void Upstream_HID_BotDetectKeyboard(uint8_t* keyboardInData)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t j;
|
||||
uint8_t tempModifier;
|
||||
|
||||
if (Upstream_HID_BotDetectKeyboard_RolloverCheck(keyboardInData)) return;
|
||||
|
||||
//Process modifier keys in first byte
|
||||
tempModifier = keyboardInData[0];
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if ((tempModifier & 1) && !(OldKeyboardInData[0] & 1))
|
||||
{
|
||||
Upstream_HID_BotDetectKeyboard_KeyDown(KEY_MODIFIER_BASE + i);
|
||||
}
|
||||
if (!(tempModifier & 1) && (OldKeyboardInData[0] & 1))
|
||||
{
|
||||
Upstream_HID_BotDetectKeyboard_KeyUp(KEY_MODIFIER_BASE + i);
|
||||
}
|
||||
tempModifier >>= 1;
|
||||
OldKeyboardInData[0] >>= 1;
|
||||
}
|
||||
|
||||
|
||||
//Process key array: search for keydowns
|
||||
for (i = 2; i < HID_KEYBOARD_INPUT_DATA_LEN; i++)
|
||||
{
|
||||
if (keyboardInData[i] >= KEY_A)
|
||||
{
|
||||
for (j = 2; j < HID_KEYBOARD_INPUT_DATA_LEN; j++)
|
||||
{
|
||||
if (keyboardInData[i] == OldKeyboardInData[j]) break;
|
||||
}
|
||||
if (j >= HID_KEYBOARD_INPUT_DATA_LEN)
|
||||
{
|
||||
Upstream_HID_BotDetectKeyboard_KeyDown(keyboardInData[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Process key array: search for keyups
|
||||
for (i = 2; i < HID_KEYBOARD_INPUT_DATA_LEN; i++)
|
||||
{
|
||||
if (OldKeyboardInData[i] >= KEY_A)
|
||||
{
|
||||
for (j = 2; j < HID_KEYBOARD_INPUT_DATA_LEN; j++)
|
||||
{
|
||||
if (OldKeyboardInData[i] == keyboardInData[j]) break;
|
||||
}
|
||||
if (j >= HID_KEYBOARD_INPUT_DATA_LEN)
|
||||
{
|
||||
Upstream_HID_BotDetectKeyboard_KeyUp(OldKeyboardInData[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check for evidence of bot typing
|
||||
for (i = 0; i < KEYBOARD_BOTDETECT_FAST_BIN_COUNT; i++)
|
||||
{
|
||||
if ((KeyDelayFastBinArray[i] > KEYBOARD_BOTDETECT_LOCKOUT_BIN_THRESHOLD) ||
|
||||
(KeyDowntimeFastBinArray[i] > KEYBOARD_BOTDETECT_LOCKOUT_BIN_THRESHOLD))
|
||||
{
|
||||
Upstream_HID_BotDetectKeyboard_DoLockout();
|
||||
break;
|
||||
}
|
||||
//Debug:
|
||||
// if (KeyDelayFastBinArray[i] > KeyDelayFastBinArrayPeak) KeyDelayFastBinArrayPeak = KeyDelayFastBinArray[i];
|
||||
// if (KeyDowntimeFastBinArray[i] > KeyDowntimeFastBinArrayPeak) KeyDowntimeFastBinArrayPeak = KeyDowntimeFastBinArray[i];
|
||||
}
|
||||
for (i = 0; i < KEYBOARD_BOTDETECT_SLOW_BIN_COUNT; i++)
|
||||
{
|
||||
if ((KeyDelaySlowBinArray[i] > KEYBOARD_BOTDETECT_LOCKOUT_BIN_THRESHOLD) ||
|
||||
(KeyDowntimeSlowBinArray[i] > KEYBOARD_BOTDETECT_LOCKOUT_BIN_THRESHOLD))
|
||||
{
|
||||
Upstream_HID_BotDetectKeyboard_DoLockout();
|
||||
break;
|
||||
}
|
||||
//Debug:
|
||||
// if (KeyDelaySlowBinArray[i] > KeyDelaySlowBinArrayPeak) KeyDelaySlowBinArrayPeak = KeyDelaySlowBinArray[i];
|
||||
// if (KeyDowntimeSlowBinArray[i] > KeyDowntimeSlowBinArrayPeak) KeyDowntimeSlowBinArrayPeak = KeyDowntimeSlowBinArray[i];
|
||||
}
|
||||
|
||||
//Copy new data to old array
|
||||
for (i = 0; i < HID_KEYBOARD_INPUT_DATA_LEN; i++)
|
||||
{
|
||||
OldKeyboardInData[i] = keyboardInData[i];
|
||||
}
|
||||
|
||||
//Host receives no data if we are locked
|
||||
if ((LockoutState == LOCKOUT_STATE_TEMPORARY_ACTIVE) ||
|
||||
(LockoutState == LOCKOUT_STATE_PERMANENT_ACTIVE))
|
||||
{
|
||||
for (i = 0; i < HID_KEYBOARD_INPUT_DATA_LEN; i++)
|
||||
{
|
||||
keyboardInData[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Upstream_HID_BotDetectKeyboard_DoLockout(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (LockoutState == LOCKOUT_STATE_PERMANENT_ACTIVE) return;
|
||||
|
||||
//Are we already in warning state? -> activate permanent lockout
|
||||
if ((LockoutState == LOCKOUT_STATE_TEMPORARY_ACTIVE) ||
|
||||
(LockoutState == LOCKOUT_STATE_TEMPORARY_FLASHING))
|
||||
{
|
||||
LockoutState = LOCKOUT_STATE_PERMANENT_ACTIVE;
|
||||
return;
|
||||
}
|
||||
|
||||
//Three (temporary) strikes -> you're out!
|
||||
if (++TemporaryLockoutCount >= 3)
|
||||
{
|
||||
LockoutState = LOCKOUT_STATE_PERMANENT_ACTIVE;
|
||||
LED_SetState(LED_STATUS_FLASH_BOTDETECT);
|
||||
return;
|
||||
}
|
||||
|
||||
//Otherwise, reset counters and give warning
|
||||
for (i = 0; i < KEYBOARD_BOTDETECT_FAST_BIN_COUNT; i++)
|
||||
{
|
||||
KeyDelayFastBinArray[i] = 0;
|
||||
KeyDowntimeFastBinArray[i] = 0;
|
||||
}
|
||||
for (i = 0; i < KEYBOARD_BOTDETECT_SLOW_BIN_COUNT; i++)
|
||||
{
|
||||
KeyDelaySlowBinArray[i] = 0;
|
||||
KeyDowntimeSlowBinArray[i] = 0;
|
||||
}
|
||||
|
||||
TemporaryLockoutTimeMs = 0;
|
||||
LockoutState = LOCKOUT_STATE_TEMPORARY_ACTIVE;
|
||||
LED_SetState(LED_STATUS_FLASH_BOTDETECT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Keyboard reports a rollover code when there are too many keys to scan/report.
|
||||
static uint32_t Upstream_HID_BotDetectKeyboard_RolloverCheck(uint8_t* keyboardInData)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 2; i < HID_KEYBOARD_INPUT_DATA_LEN; i++)
|
||||
{
|
||||
if (keyboardInData[i] == KEY_ROLLOVER) break;
|
||||
}
|
||||
if (i >= HID_KEYBOARD_INPUT_DATA_LEN) return 0;
|
||||
|
||||
//As I am unclear on the exact usage and interpretation of the rollover code,
|
||||
//we are going to play it safe by copying the old keyboard data over the new array.
|
||||
//This ensures the host interprets a rollover event exactly the way we do!
|
||||
|
||||
//Host receives no data if we are locked
|
||||
if ((LockoutState == LOCKOUT_STATE_TEMPORARY_ACTIVE) ||
|
||||
(LockoutState == LOCKOUT_STATE_PERMANENT_ACTIVE))
|
||||
{
|
||||
for (i = 0; i < HID_KEYBOARD_INPUT_DATA_LEN; i++)
|
||||
{
|
||||
keyboardInData[i] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < HID_KEYBOARD_INPUT_DATA_LEN; i++)
|
||||
{
|
||||
keyboardInData[i] = OldKeyboardInData[i];
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Upstream_HID_BotDetectKeyboard_KeyDown(uint8_t keyCode)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t keyDelay;
|
||||
uint32_t now = HAL_GetTick();
|
||||
|
||||
keyDelay = now - LastKeyDownTime;
|
||||
if (keyDelay < (KEYBOARD_BOTDETECT_FAST_BIN_WIDTH_MS * KEYBOARD_BOTDETECT_FAST_BIN_COUNT))
|
||||
{
|
||||
KeyDelayFastBinArray[(keyDelay / KEYBOARD_BOTDETECT_FAST_BIN_WIDTH_MS)]++; //Add key to fast bin
|
||||
|
||||
//Drain fast bins at specified rate
|
||||
KeyDelayFastBinDrainDivideCount++;
|
||||
if (KeyDelayFastBinDrainDivideCount >= KEYBOARD_BOTDETECT_FAST_BIN_DRAIN_DIVIDER)
|
||||
{
|
||||
KeyDelayFastBinDrainDivideCount = 0;
|
||||
for (i = 0; i < KEYBOARD_BOTDETECT_FAST_BIN_COUNT; i++)
|
||||
{
|
||||
if (KeyDelayFastBinArray[i] > 0) KeyDelayFastBinArray[i]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
keyDelay = keyDelay % (KEYBOARD_BOTDETECT_SLOW_BIN_WIDTH_MS * KEYBOARD_BOTDETECT_SLOW_BIN_COUNT); //Wrap slow key time into the slow array
|
||||
KeyDelaySlowBinArray[(keyDelay / KEYBOARD_BOTDETECT_SLOW_BIN_WIDTH_MS)]++; //Add key to slow bin
|
||||
|
||||
//Drain slow bins at specified rate
|
||||
KeyDelaySlowBinDrainDivideCount++;
|
||||
if (KeyDelaySlowBinDrainDivideCount >= KEYBOARD_BOTDETECT_SLOW_BIN_DRAIN_DIVIDER)
|
||||
{
|
||||
KeyDelaySlowBinDrainDivideCount = 0;
|
||||
for (i = 0; i < KEYBOARD_BOTDETECT_SLOW_BIN_COUNT; i++)
|
||||
{
|
||||
if (KeyDelaySlowBinArray[i] > 0) KeyDelaySlowBinArray[i]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
LastKeyDownTime = now;
|
||||
|
||||
for (i = 0; i < KEYBOARD_BOTDETECT_MAX_ACTIVE_KEYS; i++)
|
||||
{
|
||||
if (KeyTimerLog[i].KeyCode == 0) break;
|
||||
}
|
||||
if (i >= KEYBOARD_BOTDETECT_MAX_ACTIVE_KEYS) while (1); //Totally should not happen
|
||||
KeyTimerLog[i].KeyCode = keyCode;
|
||||
KeyTimerLog[i].KeyDownStart = now;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Upstream_HID_BotDetectKeyboard_KeyUp(uint8_t keyCode)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t keyDowntime;
|
||||
|
||||
for (i = 0; i < KEYBOARD_BOTDETECT_MAX_ACTIVE_KEYS; i++)
|
||||
{
|
||||
if (KeyTimerLog[i].KeyCode == keyCode) break;
|
||||
}
|
||||
if (i >= KEYBOARD_BOTDETECT_MAX_ACTIVE_KEYS) while (1); //Totally should not happen
|
||||
|
||||
KeyTimerLog[i].KeyCode = 0; //Clear out the key entry
|
||||
keyDowntime = HAL_GetTick() - KeyTimerLog[i].KeyDownStart;
|
||||
if (keyDowntime < (KEYBOARD_BOTDETECT_FAST_BIN_WIDTH_MS * KEYBOARD_BOTDETECT_FAST_BIN_COUNT))
|
||||
{
|
||||
KeyDowntimeFastBinArray[(keyDowntime / KEYBOARD_BOTDETECT_FAST_BIN_WIDTH_MS)]++; //Add key to fast bin
|
||||
|
||||
//Drain fast bins at specified rate
|
||||
KeyDowntimeFastBinDrainDivideCount++;
|
||||
if (KeyDowntimeFastBinDrainDivideCount >= KEYBOARD_BOTDETECT_FAST_BIN_DRAIN_DIVIDER)
|
||||
{
|
||||
KeyDowntimeFastBinDrainDivideCount = 0;
|
||||
for (i = 0; i < KEYBOARD_BOTDETECT_FAST_BIN_COUNT; i++)
|
||||
{
|
||||
if (KeyDowntimeFastBinArray[i] > 0) KeyDowntimeFastBinArray[i]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
keyDowntime = keyDowntime % (KEYBOARD_BOTDETECT_SLOW_BIN_WIDTH_MS * KEYBOARD_BOTDETECT_SLOW_BIN_COUNT); //Wrap slow key time into the slow array
|
||||
KeyDowntimeSlowBinArray[(keyDowntime / KEYBOARD_BOTDETECT_SLOW_BIN_WIDTH_MS)]++; //Add key to slow bin
|
||||
|
||||
//Drain slow bins at specified rate
|
||||
KeyDowntimeSlowBinDrainDivideCount++;
|
||||
if (KeyDowntimeSlowBinDrainDivideCount >= KEYBOARD_BOTDETECT_SLOW_BIN_DRAIN_DIVIDER)
|
||||
{
|
||||
KeyDowntimeSlowBinDrainDivideCount = 0;
|
||||
for (i = 0; i < KEYBOARD_BOTDETECT_SLOW_BIN_COUNT; i++)
|
||||
{
|
||||
if (KeyDowntimeSlowBinArray[i] > 0) KeyDowntimeSlowBinArray[i]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //if defined (CONFIG_KEYBOARD_ENABLED) && defined (CONFIG_KEYBOARD_BOT_DETECT_ENABLED)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Called by Systick_Handler every 1ms, at high interrupt priority.
|
||||
void Upstream_HID_BotDetect_Systick(void)
|
||||
{
|
||||
#if (defined (CONFIG_KEYBOARD_ENABLED) && defined (CONFIG_KEYBOARD_BOT_DETECT_ENABLED)) || \
|
||||
(defined (CONFIG_MOUSE_ENABLED) && defined (CONFIG_MOUSE_BOT_DETECT_ENABLED))
|
||||
|
||||
//Check if temporary lockout has expired
|
||||
if (LockoutState == LOCKOUT_STATE_TEMPORARY_ACTIVE)
|
||||
{
|
||||
if (TemporaryLockoutTimeMs++ > BOTDETECT_TEMPORARY_LOCKOUT_TIME_MS)
|
||||
{
|
||||
LockoutState = LOCKOUT_STATE_TEMPORARY_FLASHING;
|
||||
}
|
||||
}
|
||||
else if (LockoutState == LOCKOUT_STATE_TEMPORARY_FLASHING)
|
||||
{
|
||||
if (TemporaryLockoutTimeMs++ > BOTDETECT_TEMPORARY_LOCKOUT_FLASH_TIME_MS)
|
||||
{
|
||||
LED_SetState(LED_STATUS_OFF);
|
||||
LockoutState = LOCKOUT_STATE_INACTIVE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Code specific to mouse bot detection:
|
||||
#if defined (CONFIG_MOUSE_ENABLED) && defined (CONFIG_MOUSE_BOT_DETECT_ENABLED)
|
||||
|
||||
void Upstream_HID_BotDetectMouse(uint8_t* mouseInData)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t now = HAL_GetTick();
|
||||
uint32_t moveDelay;
|
||||
uint32_t velocity;
|
||||
int8_t mouseX;
|
||||
int8_t mouseY;
|
||||
|
||||
//Constant acceleration detection stuff
|
||||
uint32_t newSmoothedVelocity;
|
||||
uint32_t oldSmoothedVelocity;
|
||||
int32_t newSmoothedAcceleration;
|
||||
int32_t smoothedAccelerationMatchError;
|
||||
|
||||
|
||||
mouseX = mouseInData[1];
|
||||
mouseY = mouseInData[2];
|
||||
velocity = (sqrtf(((int32_t)mouseX * mouseX) +
|
||||
((int32_t)mouseY * mouseY))) * MOUSE_BOTDETECT_VELOCITY_MULTIPLIER; //Multiply floating-point sqrt result to avoid integer rounding errors
|
||||
moveDelay = now - LastMouseMoveTime;
|
||||
|
||||
|
||||
//Reset constant acceleration detection state after a few seconds of inactivity
|
||||
if (moveDelay > MOUSE_BOTDETECT_VELOCITY_RESET_TIMEOUT_MS)
|
||||
{
|
||||
//Is this the start of a new movement?
|
||||
if (velocity != 0)
|
||||
{
|
||||
for (i = 0; i < MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE; i++)
|
||||
{
|
||||
MouseVelocityHistory[i] = 0;
|
||||
}
|
||||
ConstantAccelerationCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Jiggle detection: did the mouse stop moving?
|
||||
if (moveDelay > ((MOUSE_BOTDETECT_JIGGLE_STOP_PERIODS * HID_FS_BINTERVAL) - (HID_FS_BINTERVAL / 2)))
|
||||
{
|
||||
//Is this the start of a new movement?
|
||||
if (velocity != 0)
|
||||
{
|
||||
//Jiggle detection: add stopped time to jiggle bins
|
||||
moveDelay = moveDelay % (MOUSE_BOTDETECT_JIGGLE_BIN_WIDTH_MS * MOUSE_BOTDETECT_JIGGLE_BIN_COUNT); //Wrap stopped time into the array
|
||||
MouseStopIntervalBinArray[(moveDelay / MOUSE_BOTDETECT_JIGGLE_BIN_WIDTH_MS)]++;
|
||||
if (MouseStopIntervalBinArray[(moveDelay / MOUSE_BOTDETECT_JIGGLE_BIN_WIDTH_MS)] > MOUSE_BOTDETECT_LOCKOUT_JIGGLE_BIN_THRESHOLD)
|
||||
{
|
||||
Upstream_HID_BotDetectMouse_DoLockout();
|
||||
}
|
||||
|
||||
//Debug:
|
||||
// if (MouseStopIntervalBinArray[(moveDelay / MOUSE_BOTDETECT_JIGGLE_BIN_WIDTH_MS)] > MouseStopIntervalBinArrayPeak)
|
||||
// {
|
||||
// MouseStopIntervalBinArrayPeak = MouseStopIntervalBinArray[(moveDelay / MOUSE_BOTDETECT_JIGGLE_BIN_WIDTH_MS)];
|
||||
// }
|
||||
|
||||
//Drain jiggle bins at specified rate
|
||||
MouseStopIntervalBinDrainDivideCount++;
|
||||
if (MouseStopIntervalBinDrainDivideCount >= MOUSE_BOTDETECT_JIGGLE_BIN_DIVIDER)
|
||||
{
|
||||
MouseStopIntervalBinDrainDivideCount = 0;
|
||||
for (i = 0; i < MOUSE_BOTDETECT_JIGGLE_BIN_COUNT; i++)
|
||||
{
|
||||
if (MouseStopIntervalBinArray[i] > 0) MouseStopIntervalBinArray[i]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Jump detection: did the mouse stop moving briefly?
|
||||
if (moveDelay > ((MOUSE_BOTDETECT_JUMP_PERIODS * HID_FS_BINTERVAL) - (HID_FS_BINTERVAL / 2)))
|
||||
{
|
||||
FirstMouseMoveTime = 0;
|
||||
if (JumpMouseIsMoving) //Was a significant movement in progress?
|
||||
{
|
||||
JumpMouseIsMoving = 0;
|
||||
if ((LastMouseMoveTime - FirstMouseMoveTime) < ((MOUSE_BOTDETECT_JUMP_PERIODS * HID_FS_BINTERVAL) - (HID_FS_BINTERVAL / 2)))
|
||||
{
|
||||
Upstream_HID_BotDetectMouse_DoLockout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (velocity != 0)
|
||||
{
|
||||
//Jump detection
|
||||
LastMouseMoveTime = now;
|
||||
if (FirstMouseMoveTime == 0)
|
||||
{
|
||||
FirstMouseMoveTime = now;
|
||||
}
|
||||
if (velocity > (MOUSE_BOTDETECT_JUMP_VELOCITY_THRESHOLD * MOUSE_BOTDETECT_VELOCITY_MULTIPLIER))
|
||||
{
|
||||
JumpMouseIsMoving = 1;
|
||||
}
|
||||
|
||||
//Constant acceleration detection
|
||||
for (i = (MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE - 1); i > 0; i--) //Shuffle down history data
|
||||
{
|
||||
MouseVelocityHistory[i] = MouseVelocityHistory[i - 1];
|
||||
}
|
||||
MouseVelocityHistory[0] = velocity; //Store latest data at head
|
||||
|
||||
if (MouseVelocityHistory[(MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE - 1)] > 0)
|
||||
{
|
||||
velocity = 0; //Calculate new and old average velocities
|
||||
for (i = 0; i < (MOUSE_BOTDETECT_VELOCITY_HISTORY_SIZE / 2); i++)
|