From 96942ac5b5864eb2efba2df2ecfa9670a0dfdf46 Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 00:20:08 +0100 Subject: [PATCH 01/16] config/families: add avr family Signed-off-by: perigoso --- config/families/avr.toml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 config/families/avr.toml diff --git a/config/families/avr.toml b/config/families/avr.toml new file mode 100644 index 00000000..3036265d --- /dev/null +++ b/config/families/avr.toml @@ -0,0 +1,18 @@ +toolchain = 'avr' +has-linker = false +c_flags = [ + '-Os', + '-fpack-struct', + '-fshort-enums', + '-ffunction-sections', + '-fdata-sections', +] +ld_flags = [ + '-fdata-sections', + '-ffunction-sections', + '-Wl,--gc-sections', +] +source = [ +] + +[dependencies] From 15a08e6b856100e5e94e12d0bfb3d93345a148f4 Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 00:33:31 +0100 Subject: [PATCH 02/16] targets: add atmega32u4 generic target Signed-off-by: perigoso --- config/targets/atmega32u4-generic.toml | 10 ++++++++++ src/targets/atmega32u4-generic/config/sample.h | 10 ++++++++++ src/targets/atmega32u4-generic/main.c | 15 +++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 config/targets/atmega32u4-generic.toml create mode 100644 src/targets/atmega32u4-generic/config/sample.h create mode 100644 src/targets/atmega32u4-generic/main.c diff --git a/config/targets/atmega32u4-generic.toml b/config/targets/atmega32u4-generic.toml new file mode 100644 index 00000000..77bd8acd --- /dev/null +++ b/config/targets/atmega32u4-generic.toml @@ -0,0 +1,10 @@ +family = 'avr' +has-config = true +c_flags = [ + '-mmcu=atmega32u4', +] +ld_flags = [ + '-mmcu=atmega32u4', +] + +[dependencies] diff --git a/src/targets/atmega32u4-generic/config/sample.h b/src/targets/atmega32u4-generic/config/sample.h new file mode 100644 index 00000000..2a0bb726 --- /dev/null +++ b/src/targets/atmega32u4-generic/config/sample.h @@ -0,0 +1,10 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +/* clang-format off */ + +/* Clock Config */ + +#define F_CPU 16000000UL diff --git a/src/targets/atmega32u4-generic/main.c b/src/targets/atmega32u4-generic/main.c new file mode 100644 index 00000000..9546bd54 --- /dev/null +++ b/src/targets/atmega32u4-generic/main.c @@ -0,0 +1,15 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#include + +#include "util/data.h" +#include "util/types.h" + +void main() +{ + for (;;) { + } +} From c9466c60b58ad04912817732aa229f86d36ef541 Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 00:37:18 +0100 Subject: [PATCH 03/16] workflows: setub build for atmega32u4-generic target Signed-off-by: perigoso --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3008a965..4f82f2be 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,9 +28,10 @@ jobs: - 'stm32f1-generic -c bluepill' - 'efm32gg12b-generic -c sltb009a' - 'sams70-generic -c big-sammy' + - 'atmega32u4-generic -c sample' steps: - name: Update the system and install dependencies - run: pacman -Syu --noconfirm --noprogressbar --needed python-pip ninja gcc arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib pkgconf readline git + run: pacman -Syu --noconfirm --noprogressbar --needed python-pip ninja gcc arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib avr-gcc avr-binutils avr-libc pkgconf readline git - name: Install ninja_syntax run: pip install ninja_syntax From 5b81cc4334373d839c55e884db0616a72f104e70 Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 11:34:16 +0100 Subject: [PATCH 04/16] targets/atmega32u4-generic: rename sample config to octupus, a mouse pcb by gilmore Signed-off-by: perigoso --- .github/workflows/build.yml | 2 +- .../atmega32u4-generic/config/octopus.h | 46 +++++++++++++++++++ .../atmega32u4-generic/config/sample.h | 10 ---- 3 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 src/targets/atmega32u4-generic/config/octopus.h delete mode 100644 src/targets/atmega32u4-generic/config/sample.h diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f82f2be..99409f0b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,7 +28,7 @@ jobs: - 'stm32f1-generic -c bluepill' - 'efm32gg12b-generic -c sltb009a' - 'sams70-generic -c big-sammy' - - 'atmega32u4-generic -c sample' + - 'atmega32u4-generic -c octopus' steps: - name: Update the system and install dependencies run: pacman -Syu --noconfirm --noprogressbar --needed python-pip ninja gcc arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib avr-gcc avr-binutils avr-libc pkgconf readline git diff --git a/src/targets/atmega32u4-generic/config/octopus.h b/src/targets/atmega32u4-generic/config/octopus.h new file mode 100644 index 00000000..63258c47 --- /dev/null +++ b/src/targets/atmega32u4-generic/config/octopus.h @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +/* clang-format off */ + +/* Clock Config */ + +#define F_CPU 16000000UL + +/* Sensor Config */ + +#define SENSOR_ENABLED +#define SENSOR_DRIVER PIXART_PMW + +#define SENSOR_FIRMWARE_BLOB pmw3360_blob + +//#define SENSOR_MOTION_IO { .port = , .pin = } + +#define SENSOR_INTERFACE SPI_INTERFACE_1 + +#define SENSOR_INTERFACE_SPEED 10000000 + +/* o -> active low, 1 -> active high */ +#define SENSOR_INTERFACE_CS_POL 0 +#define SENSOR_INTERFACE_CS_IO { .port = GPIO_PORT_B, .pin = 6 } + +#define SENSOR_INTERFACE_SCK_IO { .port = GPIO_PORT_B, .pin = 1 } +#define SENSOR_INTERFACE_MISO_IO { .port = GPIO_PORT_B, .pin = 3 } +#define SENSOR_INTERFACE_MOSI_IO { .port = GPIO_PORT_B, .pin = 2 } + +/* IO config */ +#define MB1_IO { .port = GPIO_PORT_F, .pin = 5 } +#define MB1_N_IO { .port = GPIO_PORT_F, .pin = 1 } +#define MB2_IO { .port = GPIO_PORT_F, .pin = 6 } +#define MB2_N_IO { .port = GPIO_PORT_F, .pin = 7 } +#define MB3_IO { .port = GPIO_PORT_D, .pin = 4 } +#define MB3_N_IO { .port = GPIO_PORT_D, .pin = 5 } +#define MB4_IO { .port = GPIO_PORT_D, .pin = 6 } +#define MB4_N_IO { .port = GPIO_PORT_D, .pin = 7 } +#define MB5_IO { .port = GPIO_PORT_B, .pin = 4 } +#define MB5_N_IO { .port = GPIO_PORT_B, .pin = 5 } + +#define WHEEL_A_IO { .port = GPIO_PORT_D, .pin = 2 } +#define WHEEL_B_IO { .port = GPIO_PORT_D, .pin = 3 } diff --git a/src/targets/atmega32u4-generic/config/sample.h b/src/targets/atmega32u4-generic/config/sample.h deleted file mode 100644 index 2a0bb726..00000000 --- a/src/targets/atmega32u4-generic/config/sample.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * SPDX-License-Identifier: MIT - * SPDX-FileCopyrightText: 2021 Rafael Silva - */ - -/* clang-format off */ - -/* Clock Config */ - -#define F_CPU 16000000UL From 2db37db9f350c6a60dbd004a6bcc38c395c49569 Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 13:01:58 +0100 Subject: [PATCH 05/16] external: add lufa submodule, avr usb Signed-off-by: perigoso --- .gitmodules | 3 +++ external/lufa | 1 + 2 files changed, 4 insertions(+) create mode 160000 external/lufa diff --git a/.gitmodules b/.gitmodules index d1f98869..ef1b11e3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "external/cmsis-dfp-sams70"] path = external/cmsis-dfp-sams70 url = https://github.com/cmsis-packs/cmsis-dfp-sams70 +[submodule "external/lufa"] + path = external/lufa + url = https://github.com/abcminiuser/lufa diff --git a/external/lufa b/external/lufa new file mode 160000 index 00000000..8a785549 --- /dev/null +++ b/external/lufa @@ -0,0 +1 @@ +Subproject commit 8a785549cf41ec8ba7dac6480e81d0de2c243c98 From 978535081740bbb7c70a97177b1b7d003481a8a9 Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 15:10:59 +0100 Subject: [PATCH 06/16] build_system/dependencies: add lufa dependency Signed-off-by: perigoso --- build_system/dependencies.py | 20 +++++++++++++++++++ config/families/avr.toml | 1 + .../atmega32u4-generic/config/octopus.h | 4 +++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/build_system/dependencies.py b/build_system/dependencies.py index e23cf248..44442c4b 100644 --- a/build_system/dependencies.py +++ b/build_system/dependencies.py @@ -146,6 +146,26 @@ def __init__(self, location: BuildLocation, target: str) -> None: } +@dataclasses.dataclass(init=False) +class LufaDependency(Dependency, name='lufa'): + def __init__(self, location: BuildLocation) -> None: + super().__init__(location) + + src_path = self.base_path / 'LUFA/Drivers/USB' + + for path in src_path.rglob('*.c'): + self.source.add(path) + + self._include = [ + 'LUFA/Common' + 'LUFA/Driver/USB' + ] + self._external_include = [ + 'LUFA/Common' + 'LUFA/Driver/USB' + ] + + @dataclasses.dataclass(init=False) class CMSIS5Dependency(Dependency, name='cmsis-5'): components: List[str] diff --git a/config/families/avr.toml b/config/families/avr.toml index 3036265d..5fa078a2 100644 --- a/config/families/avr.toml +++ b/config/families/avr.toml @@ -16,3 +16,4 @@ source = [ ] [dependencies] +lufa = {} diff --git a/src/targets/atmega32u4-generic/config/octopus.h b/src/targets/atmega32u4-generic/config/octopus.h index 63258c47..389e91a0 100644 --- a/src/targets/atmega32u4-generic/config/octopus.h +++ b/src/targets/atmega32u4-generic/config/octopus.h @@ -7,7 +7,9 @@ /* Clock Config */ -#define F_CPU 16000000UL +#define ARCH AVR8 +#define F_CPU 16000000UL +#define F_USB F_CPU /* Sensor Config */ From 6b1bfba512394e16e388ec761ec2dac0b1894e66 Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 16:09:04 +0100 Subject: [PATCH 07/16] external/lufa: checkout latest release Signed-off-by: perigoso --- external/lufa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/lufa b/external/lufa index 8a785549..fa2cc3e1 160000 --- a/external/lufa +++ b/external/lufa @@ -1 +1 @@ -Subproject commit 8a785549cf41ec8ba7dac6480e81d0de2c243c98 +Subproject commit fa2cc3e1c3abab7c971506bd86ca4e28ecc7d288 From 6e7d01a7c58eccd0f5ab72f186681a35519e2d2e Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Tue, 25 Jan 2022 10:46:43 +0000 Subject: [PATCH 08/16] targets/octopus: rename to octomouse --- src/targets/atmega32u4-generic/config/{octopus.h => octomouse.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/targets/atmega32u4-generic/config/{octopus.h => octomouse.h} (100%) diff --git a/src/targets/atmega32u4-generic/config/octopus.h b/src/targets/atmega32u4-generic/config/octomouse.h similarity index 100% rename from src/targets/atmega32u4-generic/config/octopus.h rename to src/targets/atmega32u4-generic/config/octomouse.h From 6ff36d0117380c35e7eea08b45091d5e348a1b63 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Tue, 25 Jan 2022 10:47:49 +0000 Subject: [PATCH 09/16] workflow: rename avr target to octomouse --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 99409f0b..3e7e422a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,7 +28,7 @@ jobs: - 'stm32f1-generic -c bluepill' - 'efm32gg12b-generic -c sltb009a' - 'sams70-generic -c big-sammy' - - 'atmega32u4-generic -c octopus' + - 'atmega32u4-generic -c octomouse' steps: - name: Update the system and install dependencies run: pacman -Syu --noconfirm --noprogressbar --needed python-pip ninja gcc arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib avr-gcc avr-binutils avr-libc pkgconf readline git From ed6045e42927815cb8bc4b3d9b59b6423bedea7e Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Tue, 10 May 2022 03:50:36 +0100 Subject: [PATCH 10/16] tools: add caterina bootloader tool Signed-off-by: Rafael Silva --- tools/caterina-load.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100755 tools/caterina-load.sh diff --git a/tools/caterina-load.sh b/tools/caterina-load.sh new file mode 100755 index 00000000..5e3e35d0 --- /dev/null +++ b/tools/caterina-load.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# wait for port to spawn +while :; do + sleep 0.5 + [ -c "${UPLOAD_PORT}" ] && break +done + +# reset to bootloader (magic baudrate) +stty -F "${UPLOAD_PORT}" 1200 + +# wait for port to respawn +while :; do + sleep 0.5 + [ -c "${UPLOAD_PORT}" ] && break +done + +# upload +avrdude -v -patmega32u4 -cavr109 -P${UPLOAD_PORT} -b57600 -D -Uflash:w:${HEX_FILE} From e82ab562d509b4759e10a3ad2395dd674ef415e8 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Tue, 10 May 2022 03:57:47 +0100 Subject: [PATCH 11/16] fixup! build_system/dependencies: add lufa dependency --- build_system/dependencies.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/build_system/dependencies.py b/build_system/dependencies.py index 44442c4b..bb8769c3 100644 --- a/build_system/dependencies.py +++ b/build_system/dependencies.py @@ -152,18 +152,20 @@ def __init__(self, location: BuildLocation) -> None: super().__init__(location) src_path = self.base_path / 'LUFA/Drivers/USB' + common_path = self.base_path / 'LUFA/Common' for path in src_path.rglob('*.c'): self.source.add(path) - self._include = [ - 'LUFA/Common' - 'LUFA/Driver/USB' - ] - self._external_include = [ - 'LUFA/Common' - 'LUFA/Driver/USB' - ] + self.include = { + src_path, + common_path, + self.location.code, + } + self.external_include = { + src_path, + common_path, + } @dataclasses.dataclass(init=False) From 35caf4be35fe00d93d562065e88f698394c5b915 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Tue, 10 May 2022 03:59:02 +0100 Subject: [PATCH 12/16] build_system/ninja: add local target directory to includes Signed-off-by: Rafael Silva --- build_system/ninja.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_system/ninja.py b/build_system/ninja.py index 0057570b..f9c64345 100644 --- a/build_system/ninja.py +++ b/build_system/ninja.py @@ -120,6 +120,8 @@ def write_variables( self.writer.variable('c_flags', details.c_flags) self.writer.variable('c_include_flags', [ f'-I{self.path(self._location.code)}' + ] + [ + f'-I{self.path(self._location.code / "targets" / self._target.name)}' ] + [ f'-include {self.path(path)}' for path in details.include_files ] + [ From b4848cffc017bc35ac3863d9e1d5decf7dc113ae Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Tue, 10 May 2022 04:00:40 +0100 Subject: [PATCH 13/16] platform/avr: add reset to bootloader and reset functions Signed-off-by: Rafael Silva --- src/platform/avr/boot.c | 24 ++++++++++++++++++++++++ src/platform/avr/boot.h | 8 ++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/platform/avr/boot.c create mode 100644 src/platform/avr/boot.h diff --git a/src/platform/avr/boot.c b/src/platform/avr/boot.c new file mode 100644 index 00000000..0c1589e6 --- /dev/null +++ b/src/platform/avr/boot.c @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2022 Rafael Silva + */ + +#include + +// Assuming the Caterina bootloader that comes with the 32u4 +uint16_t bootKey = 0x7777; +volatile uint16_t *const bootKeyPtr = (volatile uint16_t *) 0x0800; + +void reset() +{ + wdt_enable(WDTO_15MS); + for (;;) { + } +} + +void bootloader() +{ + *bootKeyPtr = bootKey; + + reset(); +} diff --git a/src/platform/avr/boot.h b/src/platform/avr/boot.h new file mode 100644 index 00000000..28b9442f --- /dev/null +++ b/src/platform/avr/boot.h @@ -0,0 +1,8 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2022 Rafael Silva + */ + +void reset() __attribute__((noreturn)); +void bootloader() __attribute__((noreturn)); +; From f708a84d7581ca8b67711b9a2fd7cfdaa16c5163 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Tue, 10 May 2022 04:02:24 +0100 Subject: [PATCH 14/16] target/atmega32u4-generic: configure lufa usb stack Signed-off-by: Rafael Silva --- config/families/avr.toml | 3 + config/targets/atmega32u4-generic.toml | 1 + src/platform/avr/usb.c | 102 +++++ src/platform/avr/usb.h | 12 + src/platform/avr/usb_descriptors.c | 399 ++++++++++++++++++++ src/targets/atmega32u4-generic/LUFAConfig.h | 68 ++++ src/targets/atmega32u4-generic/main.c | 26 +- 7 files changed, 610 insertions(+), 1 deletion(-) create mode 100644 src/platform/avr/usb.c create mode 100644 src/platform/avr/usb.h create mode 100644 src/platform/avr/usb_descriptors.c create mode 100644 src/targets/atmega32u4-generic/LUFAConfig.h diff --git a/config/families/avr.toml b/config/families/avr.toml index 5fa078a2..17a5132f 100644 --- a/config/families/avr.toml +++ b/config/families/avr.toml @@ -13,6 +13,9 @@ ld_flags = [ '-Wl,--gc-sections', ] source = [ + 'boot.c', + 'usb.c', + 'usb_descriptors.c', ] [dependencies] diff --git a/config/targets/atmega32u4-generic.toml b/config/targets/atmega32u4-generic.toml index 77bd8acd..68d031dc 100644 --- a/config/targets/atmega32u4-generic.toml +++ b/config/targets/atmega32u4-generic.toml @@ -2,6 +2,7 @@ family = 'avr' has-config = true c_flags = [ '-mmcu=atmega32u4', + '-DUSE_LUFA_CONFIG_HEADER', ] ld_flags = [ '-mmcu=atmega32u4', diff --git a/src/platform/avr/usb.c b/src/platform/avr/usb.c new file mode 100644 index 00000000..c471a962 --- /dev/null +++ b/src/platform/avr/usb.c @@ -0,0 +1,102 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2022 Rafael Silva + */ + +#include + +#include "protocol/reports.h" +#include "usb.h" +#include "util/types.h" + +#include + +static struct protocol_config_t protocol_config; + +void usb_attach_protocol_config(struct protocol_config_t config) +{ + protocol_config = config; +} + +void usb_init() +{ + /* Init USB stack */ + USB_Init(); +} + +void usb_task() +{ + USB_USBTask(); +} + +/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and + * starts the library USB task to begin the enumeration and USB management process. + */ +void EVENT_USB_Device_Connect(void) +{ +} + +/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via + * the status LEDs and stops the USB management task. + */ +void EVENT_USB_Device_Disconnect(void) +{ +} + +/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to + * the device from the USB host before passing along unhandled control requests to the library for processing + * internally. + */ +void EVENT_USB_Device_ControlRequest(void) +{ + struct oi_report_t oi_report; + uint8_t *ReportData; + uint8_t ReportSize; + + /* Handle HID Class specific requests */ + switch (USB_ControlRequest.bRequest) { + case HID_REQ_GetReport: + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { + Endpoint_ClearSETUP(); + + // /* Determine if it is the mouse or the keyboard data that is being requested */ + // if (USB_ControlRequest.wIndex == 0) { // openinput + // } else if (USB_ControlRequest.wIndex == 1) { // mouse + // } else if (USB_ControlRequest.wIndex == 2) { // keyboard + // } + + // /* Write the report data to the control endpoint */ + // Endpoint_Write_Control_Stream_LE(ReportData, ReportSize); + Endpoint_ClearOUT(); + } + + break; + case HID_REQ_SetReport: + if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { + Endpoint_ClearSETUP(); + + /* Wait until the report has been sent by the host */ + while (!(Endpoint_IsOUTReceived())) { + if (USB_DeviceState == DEVICE_STATE_Unattached) + return; + } + + if (USB_ControlRequest.wIndex == 0) { + // for (size_t i = 0; i < USB_ControlRequest.wLength; i++) + // { + // ((uint8_t *)(&oi_report))[i] = Endpoint_Read_8(); + // } + // protocol_dispatch(protocol_config, (uint8_t *)(&oi_report), USB_ControlRequest.wLength); + + } else if (USB_ControlRequest.wIndex == 2) { + /* Read in the LED report from the host */ + uint8_t LEDStatus = Endpoint_Read_8(); + } + + Endpoint_ClearOUT(); + Endpoint_ClearStatusStage(); + } + + break; + } +} diff --git a/src/platform/avr/usb.h b/src/platform/avr/usb.h new file mode 100644 index 00000000..b8c7ff17 --- /dev/null +++ b/src/platform/avr/usb.h @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2022 Rafael Silva + */ + +#pragma once + +#include "protocol/protocol.h" + +void usb_init(); +void usb_task(); +void usb_attach_protocol_config(struct protocol_config_t config); diff --git a/src/platform/avr/usb_descriptors.c b/src/platform/avr/usb_descriptors.c new file mode 100644 index 00000000..f417820d --- /dev/null +++ b/src/platform/avr/usb_descriptors.c @@ -0,0 +1,399 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2022 Rafael Silva + */ + +#include + +#include + +#include "util/data.h" +#include "util/types.h" + +/* Device descriptor */ +const u8 PROGMEM desc_device[] = { + /* clang-format off */ + 0x12, /* LENGTH (18) */ + 0x01, /* DESCRIPTOR TYPE (Device) */ + 0x10, 0x01, /* USB SPEC VERSION (0x0110) */ + 0x00, /* DEVICE CLASS */ + 0x00, /* DEVICE SUBCLASS */ + 0x00, /* DEVICE PROTOCOL */ + 0x40, /* MAX EP0 PACKET SIZE (32) */ + 0x50, 0x1D, /* VENDOR ID (0x1D50) */ + 0x6A, 0x61, /* PRODUCT ID (0x616A) */ + 0x00, 0x01, /* DEVICE RELEASE */ + 0x01, /* MANUFACTURER STRING INDEX */ + 0x02, /* PRODUCT STRING INDEX */ + 0x00, /* SERIAL STRING INDEX (None) */ + 0x01, /* NO CONFIGURATIONS */ + /* clang-format on */ +}; + +const u8 PROGMEM oi_rdesc[] = { + /* clang-format off */ + /* short report */ + 0x06, 0x00, 0xff, /* USAGE_PAGE (Vendor Page) */ + 0x09, 0x00, /* USAGE (Vendor Usage 0) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, 0x20, /* REPORT_ID (0x20) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x15, 0x00, /* LOGICAL MINIMUM (0) */ + 0x26, 0xff, 0x00, /* LOGICAL MAXIMUM (255) */ + 0x09, 0x00, /* USAGE (Vendor Usage 0) */ + 0x81, 0x00, /* INPUT (Data,Arr,Abs) */ + 0x09, 0x00, /* USAGE (Vendor Usage 0) */ + 0x91, 0x00, /* OUTPUT (Data,Arr,Abs) */ + 0xc0, /* END_COLLECTION */ + /* long report */ + 0x06, 0x00, 0xff, /* USAGE_PAGE (Vendor Page) */ + 0x09, 0x00, /* USAGE (Vendor Usage 0) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x85, 0x21, /* REPORT_ID (0x21) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x20, /* REPORT_COUNT (32) */ + 0x15, 0x00, /* LOGICAL MINIMUM (0) */ + 0x26, 0xff, 0x00, /* LOGICAL MAXIMUM (255) */ + 0x09, 0x00, /* USAGE (Vendor Usage 0) */ + 0x81, 0x00, /* INPUT (Data,Arr,Abs) */ + 0x09, 0x00, /* USAGE (Vendor Usage 0) */ + 0x91, 0x00, /* OUTPUT (Data,Arr,Abs) */ + 0xc0, /* END_COLLECTION */ + /* clang-format on */ +}; + +/* HID Mouse report descriptor */ +const u8 PROGMEM desc_hid_mouse_report[] = { + /* clang-format off */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x02, /* USAGE (Mouse) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x09, 0x01, /* USAGE (Pointer) */ + 0xa1, 0x00, /* COLLECTION (Physical) */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x09, 0x38, /* USAGE (WHEEL) */ + 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ + 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ + 0x05, 0x09, /* USAGE_PAGE (Button) */ + 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ + 0x29, 0x03, /* USAGE_MAXIMUM (Button 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x81, 0x01, /* INPUT (Cnst,Var,Abs) */ + 0xc0, /* END_COLLECTION */ + 0xc0, /* END_COLLECTION */ + /* clang-format on */ +}; + +/* HID keyboard report descriptor */ +const u8 PROGMEM desc_hid_keyboard_report[] = { + /* clang-format off */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + /* Report ID if any */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + /* 8 bits Modifier Keys (Shfit, Control, Alt) */ + 0x05, 0x07, /* USAGE_PAGE (keyboard) */ + 0x19, 0xE0, /* USAGE_MINIMUM (224) */ + 0x29, 0xE7, /* USAGE_MAXIMUM (231) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + /* 8 bit reserved */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x01, /* INPUT (Const) */ + /* 6-byte Keycodes */ + 0x05, 0x07, /* USAGE_PAGE (keyboard) */ + 0x19, 0x00, /* USAGE_MINIMUM (0) */ + 0x29, 0xFF, /* USAGE_MAXIMUM (255) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xFF, /* LOGICAL_MAXIMUM (255) */ + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x00, /* INPUT (Data,Arr,Abs) */ + /* 5-bit LED Indicator Kana | Compose | ScrollLock | CapsLock | NumLock */ + 0x05, 0x08, /* USAGE_PAGE (led) */ + 0x19, 0x00, /* USAGE_MINIMUM (0) */ + 0x29, 0x01, /* USAGE_MAXIMUM (1) */ + 0x95, 0x05, /* REPORT_COUNT (5) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + /* led padding */ + 0x95, 0x01, /* REPORT_COUNT (5) */ + 0x75, 0x03, /* REPORT_SIZE (1) */ + 0x91, 0x01, /* INPUT (Const) */ + 0xc0, /* END_COLLECTION */ + /* clang-format on */ +}; + +const u8 PROGMEM oi_hid_desc[] = { + /* HID */ + 0x09, /* LENGTH */ + 0x21, /* DESCRIPTOR TYPE (hid) */ + 0x11, + 0x01, /* HID VERSION (0x0111) */ + 0x00, /* COUNTRY CODE (None) */ + 0x01, /* NO DESCRIPTORS (1) */ + 0x22, /* DESCRIPTOR TYPE (Report) */ + sizeof(oi_rdesc), + 0x00, /* DESCRIPTOR LENGTH () */ +}; + +const u8 PROGMEM mouse_hid_desc[] = { + /* HID */ + 0x09, /* LENGTH */ + 0x21, /* DESCRIPTOR TYPE (hid) */ + 0x11, + 0x01, /* HID VERSION (0x0111) */ + 0x00, /* COUNTRY CODE (None) */ + 0x01, /* NO DESCRIPTORS (1) */ + 0x22, /* DESCRIPTOR TYPE (Report) */ + sizeof(desc_hid_mouse_report), + 0x00, /* DESCRIPTOR LENGTH () */ +}; + +const u8 PROGMEM keyboard_hid_desc[] = { + /* HID */ + 0x09, /* LENGTH */ + 0x21, /* DESCRIPTOR TYPE (hid) */ + 0x11, + 0x01, /* HID VERSION (0x0111) */ + 0x00, /* COUNTRY CODE (None) */ + 0x01, /* NO DESCRIPTORS (1) */ + 0x22, /* DESCRIPTOR TYPE (Report) */ + sizeof(desc_hid_keyboard_report), + 0x00, /* DESCRIPTOR LENGTH () */ +}; + +/* Configuration Descriptor */ +const u8 PROGMEM desc_configuration[] = { + /* clang-format off */ + /* configuration */ + 0x09, /* LENGTH */ + 0x02, /* DESCRIPTOR TYPE (Configuration) */ + 0x62, 0x00, /* TOTAL LENGTH (98) */ + 0x03, /* NUM INTERFACES (3) */ + 0x01, /* CONFIG NUMBER (1) */ + 0x00, /* STRING INDEX (null) */ + 0xA0, /* ATTRIBUTES (Bus powered, Remote wakeup) */ + 0x32, /* MAX POWER (100mA) */ + + /* Interface 0 - openinput protocol */ + 0x09, /* LENGTH */ + 0x04, /* DESCRIPTOR TYPE (Interface) */ + 0x00, /* INTERFACE NO (0) */ + 0x00, /* ALTERNATE SETTING (none) */ + 0x02, /* NUM ENDPOINTS (2) */ + 0x03, /* INTERFACE CLASS (HID) */ + 0x00, /* INTERFACE SUBCLASS (None) */ + 0x00, /* INTERFACE PROTOCOL (None) */ + 0x00, /* INTERFACE STRING (Null) */ + /* HID */ + 0x09, /* LENGTH */ + 0x21, /* DESCRIPTOR TYPE (hid) */ + 0x11, 0x01, /* HID VERSION (0x0111) */ + 0x00, /* COUNTRY CODE (None) */ + 0x01, /* NO DESCRIPTORS (1) */ + 0x22, /* DESCRIPTOR TYPE (Report) */ + sizeof(oi_rdesc), + 0x00, /* DESCRIPTOR LENGTH () */ + /* Endpoint in */ + 0x07, /* LENGTH */ + 0x05, /* DESCRIPTOR TYPE (Endpoint) */ + 0x81, /* ENDPOINT ADDRESS (Endpoint 1, IN) */ + 0x03, /* ATTRIBUTES (Interrupt) */ + 0x40, 0x00, /* MAX PACKET SIZE (64) */ + 0x0A, /* POLLING INTERVAL (100Hz) */ + /* Endpoint out */ + 0x07, /* LENGTH */ + 0x05, /* DESCRIPTOR TYPE (Endpoint) */ + 0x01, /* ENDPOINT ADDRESS (Endpoint 1, OUT) */ + 0x03, /* ATTRIBUTES (Interrupt) */ + 0x40, 0x00, /* MAX PACKET SIZE (64) */ + 0x0A, /* POLLING INTERVAL (100Hz) */ + + + /* Interface 1 - HID Mouse */ + 0x09, /* LENGTH */ + 0x04, /* DESCRIPTOR TYPE (Interface) */ + 0x01, /* INTERFACE NO (1) */ + 0x00, /* ALTERNATE SETTING (none) */ + 0x01, /* NUM ENDPOINTS (1) */ + 0x03, /* INTERFACE CLASS (HID) */ + 0x00, /* INTERFACE SUBCLASS (None) */ + 0x00, /* INTERFACE PROTOCOL (None) */ + 0x00, /* INTERFACE STRING (Null) */ + /* HID */ + 0x09, /* LENGTH */ + 0x21, /* DESCRIPTOR TYPE (hid) */ + 0x11, 0x01, /* HID VERSION (0x0111) */ + 0x00, /* COUNTRY CODE (None) */ + 0x01, /* NO DESCRIPTORS (1) */ + 0x22, /* DESCRIPTOR TYPE (Report) */ + sizeof(desc_hid_mouse_report), + 0x00, /* DESCRIPTOR LENGTH () */ + /* Endpoint in */ + 0x07, /* LENGTH */ + 0x05, /* DESCRIPTOR TYPE (Endpoint) */ + 0x82, /* ENDPOINT ADDRESS (Endpoint 2, IN) */ + 0x03, /* ATTRIBUTES (Interrupt) */ + 0x40, 0x00, /* MAX PACKET SIZE (64) */ + 0x01, /* POLLING INTERVAL (1000Hz) */ + + + /* Interface 2 - HID Keyboard */ + 0x09, /* LENGTH */ + 0x04, /* DESCRIPTOR TYPE (Interface) */ + 0x02, /* INTERFACE NO (2) */ + 0x00, /* ALTERNATE SETTING (none) */ + 0x02, /* NUM ENDPOINTS (2) */ + 0x03, /* INTERFACE CLASS (HID) */ + 0x00, /* INTERFACE SUBCLASS (None) */ + 0x00, /* INTERFACE PROTOCOL (None) */ + 0x00, /* INTERFACE STRING (Null) */ + /* HID */ + 0x09, /* LENGTH */ + 0x21, /* DESCRIPTOR TYPE (hid) */ + 0x11, 0x01, /* HID VERSION (0x0111) */ + 0x00, /* COUNTRY CODE (None) */ + 0x01, /* NO DESCRIPTORS (1) */ + 0x22, /* DESCRIPTOR TYPE (Report) */ + sizeof(desc_hid_keyboard_report), + 0x00, /* DESCRIPTOR LENGTH () */ + /* Endpoint in */ + 0x07, /* LENGTH */ + 0x05, /* DESCRIPTOR TYPE (Endpoint) */ + 0x83, /* ENDPOINT ADDRESS (Endpoint 3, IN) */ + 0x03, /* ATTRIBUTES (Interrupt) */ + 0x40, 0x00, /* MAX PACKET SIZE (64) */ + 0x0A, /* POLLING INTERVAL (100Hz) */ + /* Endpoint out */ + 0x07, /* LENGTH */ + 0x05, /* DESCRIPTOR TYPE (Endpoint) */ + 0x03, /* ENDPOINT ADDRESS (Endpoint 3, OUT) */ + 0x03, /* ATTRIBUTES (Interrupt) */ + 0x40, 0x00, /* MAX PACKET SIZE (64) */ + 0x0A, /* POLLING INTERVAL (100Hz) */ + /* clang-format on */ +}; + +/* String Descriptors */ +const USB_Descriptor_String_t PROGMEM lang_str = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG); +const USB_Descriptor_String_t PROGMEM manu_str = USB_STRING_DESCRIPTOR(L"Openinput"); +const USB_Descriptor_String_t PROGMEM prod_str = USB_STRING_DESCRIPTOR(L"Openinput Device"); + +/** + * This function is called by the library when in device mode, and must be overridden (see LUFA library "USB Descriptors" + * documentation) by the application code so that the address and size of a requested descriptor can be given + * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function + * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the + * USB host. + */ +u16 CALLBACK_USB_GetDescriptor(const u16 w_value, const u16 w_index, const void **const descriptor_address) +{ + const u8 descriptor_type = (w_value >> 8); + const u8 descriptor_number = (w_value & 0xFF); + + const void *addr = NULL; + u16 size = 0; + + switch (descriptor_type) { + case DTYPE_Device: + addr = desc_device; + size = sizeof(desc_device); + break; + + case DTYPE_Configuration: + addr = desc_configuration; + size = sizeof(desc_configuration); + break; + + case DTYPE_String: + switch (descriptor_number) { + case 0: + addr = &lang_str; + size = pgm_read_byte(&lang_str.Header.Size); + break; + case 1: + addr = &manu_str; + size = pgm_read_byte(&manu_str.Header.Size); + break; + case 2: + addr = &prod_str; + size = pgm_read_byte(&prod_str.Header.Size); + break; + } + + break; + + case HID_DTYPE_HID: + switch (w_index) { + case 0: + addr = oi_hid_desc; + size = sizeof(oi_hid_desc); + break; + case 1: + addr = mouse_hid_desc; + size = sizeof(mouse_hid_desc); + break; + case 2: + addr = keyboard_hid_desc; + size = sizeof(keyboard_hid_desc); + break; + } + break; + + case HID_DTYPE_Report: + switch (w_index) { + case 0: + addr = oi_rdesc; + size = sizeof(oi_rdesc); + break; + case 1: + addr = desc_hid_mouse_report; + size = sizeof(desc_hid_mouse_report); + break; + case 2: + addr = desc_hid_keyboard_report; + size = sizeof(desc_hid_keyboard_report); + break; + } + break; + } + + *descriptor_address = addr; + return size; +} + +/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration + * of the USB device after enumeration, and configures the keyboard and mouse device endpoints. + */ +void EVENT_USB_Device_ConfigurationChanged(void) +{ + /* Setup Openinput Report Endpoints */ + Endpoint_ConfigureEndpoint(0x81, EP_TYPE_INTERRUPT, 0x40, 1); // IN + Endpoint_ConfigureEndpoint(0x01, EP_TYPE_INTERRUPT, 0x40, 1); // OUT + + /* Setup Mouse HID Report Endpoint */ + Endpoint_ConfigureEndpoint(0x82, EP_TYPE_INTERRUPT, 0x40, 1); // IN + + /* Setup Keyboard HID Report Endpoints */ + Endpoint_ConfigureEndpoint(0x83, EP_TYPE_INTERRUPT, 0x40, 1); // IN + Endpoint_ConfigureEndpoint(0x03, EP_TYPE_INTERRUPT, 0x40, 1); // OUT +} diff --git a/src/targets/atmega32u4-generic/LUFAConfig.h b/src/targets/atmega32u4-generic/LUFAConfig.h new file mode 100644 index 00000000..b7c4cf91 --- /dev/null +++ b/src/targets/atmega32u4-generic/LUFAConfig.h @@ -0,0 +1,68 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2022 Rafael Silva + */ + +/** + * LUFA Library Configuration Header File + * + * This header file is used to configure LUFA's compile time options, + * as an alternative to the compile time constants supplied through + * a makefile. + * + * For information on what each token does, refer to the LUFA + * manual section "Summary of Compile Tokens". + */ + +#ifndef _LUFA_CONFIG_H_ +#define _LUFA_CONFIG_H_ + +#if (ARCH == ARCH_AVR8) + +/* Non-USB Related Configuration Tokens: */ +// #define DISABLE_TERMINAL_CODES + +/* USB Class Driver Related Tokens: */ +// #define HID_HOST_BOOT_PROTOCOL_ONLY +// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here} +// #define HID_USAGE_STACK_DEPTH {Insert Value Here} +// #define HID_MAX_COLLECTIONS {Insert Value Here} +// #define HID_MAX_REPORTITEMS {Insert Value Here} +// #define HID_MAX_REPORT_IDS {Insert Value Here} +// #define NO_CLASS_DRIVER_AUTOFLUSH + +/* General USB Driver Related Tokens: */ +// #define ORDERED_EP_CONFIG +#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL) +#define USB_DEVICE_ONLY +// #define USB_HOST_ONLY +// #define USB_STREAM_TIMEOUT_MS {Insert Value Here} +// #define NO_LIMITED_CONTROLLER_CONNECT +// #define NO_SOF_EVENTS + +/* USB Device Mode Driver Related Tokens: */ +// #define USE_RAM_DESCRIPTORS +#define USE_FLASH_DESCRIPTORS +// #define USE_EEPROM_DESCRIPTORS +// #define NO_INTERNAL_SERIAL +// #define FIXED_CONTROL_ENDPOINT_SIZE 32 +// #define DEVICE_STATE_AS_GPIOR 0 +#define FIXED_NUM_CONFIGURATIONS 1 +// #define CONTROL_ONLY_DEVICE +// #define INTERRUPT_CONTROL_ENDPOINT +// #define NO_DEVICE_REMOTE_WAKEUP +// #define NO_DEVICE_SELF_POWER + +/* USB Host Mode Driver Related Tokens: */ +// #define HOST_STATE_AS_GPIOR {Insert Value Here} +// #define USB_HOST_TIMEOUT_MS {Insert Value Here} +// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here} +// #define NO_AUTO_VBUS_MANAGEMENT +// #define INVERTED_VBUS_ENABLE_LINE + +#else + +#error Unsupported architecture for this LUFA configuration file. + +#endif +#endif diff --git a/src/targets/atmega32u4-generic/main.c b/src/targets/atmega32u4-generic/main.c index 9546bd54..3a77da33 100644 --- a/src/targets/atmega32u4-generic/main.c +++ b/src/targets/atmega32u4-generic/main.c @@ -1,15 +1,39 @@ /* * SPDX-License-Identifier: MIT - * SPDX-FileCopyrightText: 2021 Rafael Silva + * SPDX-FileCopyrightText: 2022 Rafael Silva */ +#include #include +#include +#include #include "util/data.h" #include "util/types.h" +#include "platform/avr/boot.h" +#include "platform/avr/usb.h" + void main() { + /* Disable watch dog */ + MCUSR &= ~(1 << WDRF); + wdt_disable(); + + /* Disable clock division */ + clock_prescale_set(clock_div_1); + + /* Initialize USB Subsystem */ + usb_init(); + + /* Enable global interrupts */ + sei(); + + u8 led_state = 0; + for (;;) { + usb_task(); } + + bootloader(); } From 13e841a67c74b3bb155787220fb63e2fd398934c Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Sun, 15 May 2022 02:47:37 +0100 Subject: [PATCH 15/16] target/atmega32u4-generic: configure usb descriptors and endpoints Signed-off-by: Rafael Silva --- src/platform/avr/usb.c | 111 ++++++++++++++++++++++++++--- src/platform/avr/usb_descriptors.c | 48 ++++--------- 2 files changed, 116 insertions(+), 43 deletions(-) diff --git a/src/platform/avr/usb.c b/src/platform/avr/usb.c index c471a962..33d7ca4c 100644 --- a/src/platform/avr/usb.c +++ b/src/platform/avr/usb.c @@ -7,6 +7,7 @@ #include "protocol/reports.h" #include "usb.h" +#include "util/hid_descriptors.h" #include "util/types.h" #include @@ -27,6 +28,66 @@ void usb_init() void usb_task() { USB_USBTask(); + + /* openinput IN */ + Endpoint_SelectEndpoint(0x81); + + /* Check if Endpoint Ready for Read/Write */ + if (Endpoint_IsReadWriteAllowed()) { + /* Write Report Data */ + // Endpoint_Write_Stream_LE(&report_data, sizeof(report_data), NULL); + + /* Finalize the stream transfer to send the last packet */ + // Endpoint_ClearIN(); + } + + /* openinput OUT */ + Endpoint_SelectEndpoint(0x02); + + /* Check if Endpoint Ready for Read/Write */ + if (Endpoint_IsReadWriteAllowed()) { + /* Write Report Data */ + // Keyboard_ProcessLEDReport(Endpoint_Read_8()); + + /* Handshake the OUT Endpoint - clear endpoint and ready for next report */ + Endpoint_ClearOUT(); + } + + /* mouse IN */ + Endpoint_SelectEndpoint(0x83); + + /* Check if Endpoint Ready for Read/Write */ + if (Endpoint_IsReadWriteAllowed()) { + /* Write Report Data */ + // Endpoint_Write_Stream_LE(&report_data, sizeof(report_data), NULL); + + /* Finalize the stream transfer to send the last packet */ + // Endpoint_ClearIN(); + } + + /* keyboard IN */ + Endpoint_SelectEndpoint(0x84); + + /* Check if Endpoint Ready for Read/Write */ + if (Endpoint_IsReadWriteAllowed()) { + /* Write Report Data */ + // Endpoint_Write_Stream_LE(&report_data, sizeof(report_data), NULL); + + /* Finalize the stream transfer to send the last packet */ + // Endpoint_ClearIN(); + } + + /* keyboard OUT */ + Endpoint_SelectEndpoint(0x05); + + /* Check if Endpoint Ready for Read/Write */ + if (Endpoint_IsReadWriteAllowed()) { + /* Write Report Data */ + // Keyboard_ProcessLEDReport(Endpoint_Read_8()); + + /* Handshake the OUT Endpoint - clear endpoint and ready for next report */ + Endpoint_ClearOUT(); + } } /** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and @@ -43,6 +104,10 @@ void EVENT_USB_Device_Disconnect(void) { } +struct oi_report_t oi_rep; +struct mouse_report mouse_rep; +struct keyboard_report keyb_rep; + /** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to * the device from the USB host before passing along unhandled control requests to the library for processing * internally. @@ -61,8 +126,14 @@ void EVENT_USB_Device_ControlRequest(void) // /* Determine if it is the mouse or the keyboard data that is being requested */ // if (USB_ControlRequest.wIndex == 0) { // openinput + // ReportData = (uint8_t *) &oi_rep; + // ReportSize = sizeof(struct oi_report_t); // } else if (USB_ControlRequest.wIndex == 1) { // mouse + // ReportData = (uint8_t *) &mouse_rep; + // ReportSize = sizeof(struct mouse_report); // } else if (USB_ControlRequest.wIndex == 2) { // keyboard + // ReportData = (uint8_t *) &keyb_rep; + // ReportSize = sizeof(struct keyboard_report); // } // /* Write the report data to the control endpoint */ @@ -81,17 +152,20 @@ void EVENT_USB_Device_ControlRequest(void) return; } - if (USB_ControlRequest.wIndex == 0) { - // for (size_t i = 0; i < USB_ControlRequest.wLength; i++) - // { - // ((uint8_t *)(&oi_report))[i] = Endpoint_Read_8(); - // } - // protocol_dispatch(protocol_config, (uint8_t *)(&oi_report), USB_ControlRequest.wLength); + // if (USB_ControlRequest.wIndex == 0) { + // // for (size_t i = 0; i < USB_ControlRequest.wLength; i++) + // // { + // // ((uint8_t *)(&oi_report))[i] = Endpoint_Read_8(); + // // } + // // protocol_dispatch(protocol_config, (uint8_t *)(&oi_report), USB_ControlRequest.wLength); - } else if (USB_ControlRequest.wIndex == 2) { - /* Read in the LED report from the host */ - uint8_t LEDStatus = Endpoint_Read_8(); - } + // } else if (USB_ControlRequest.wIndex == 2) { + // /* Read in the LED report from the host */ + // uint8_t LEDStatus = Endpoint_Read_8(); + // } + + /* Read in the LED report from the host */ + uint8_t LEDStatus = Endpoint_Read_8(); Endpoint_ClearOUT(); Endpoint_ClearStatusStage(); @@ -100,3 +174,20 @@ void EVENT_USB_Device_ControlRequest(void) break; } } + +/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration + * of the USB device after enumeration, and configures the keyboard and mouse device endpoints. + */ +void EVENT_USB_Device_ConfigurationChanged(void) +{ + /* Setup Openinput Report Endpoints */ + Endpoint_ConfigureEndpoint(0x81, EP_TYPE_INTERRUPT, 0x40, 1); // IN + Endpoint_ConfigureEndpoint(0x02, EP_TYPE_INTERRUPT, 0x40, 1); // OUT + + /* Setup Mouse HID Report Endpoint */ + Endpoint_ConfigureEndpoint(0x83, EP_TYPE_INTERRUPT, 0x40, 1); // IN + + /* Setup Keyboard HID Report Endpoints */ + Endpoint_ConfigureEndpoint(0x84, EP_TYPE_INTERRUPT, 0x40, 1); // IN + Endpoint_ConfigureEndpoint(0x05, EP_TYPE_INTERRUPT, 0x40, 1); // OUT +} diff --git a/src/platform/avr/usb_descriptors.c b/src/platform/avr/usb_descriptors.c index f417820d..c9c9c228 100644 --- a/src/platform/avr/usb_descriptors.c +++ b/src/platform/avr/usb_descriptors.c @@ -11,7 +11,7 @@ #include "util/types.h" /* Device descriptor */ -const u8 PROGMEM desc_device[] = { +const u8 __attribute__((__progmem__)) desc_device[] = { /* clang-format off */ 0x12, /* LENGTH (18) */ 0x01, /* DESCRIPTOR TYPE (Device) */ @@ -30,7 +30,7 @@ const u8 PROGMEM desc_device[] = { /* clang-format on */ }; -const u8 PROGMEM oi_rdesc[] = { +const u8 __attribute__((__progmem__)) oi_rdesc[] = { /* clang-format off */ /* short report */ 0x06, 0x00, 0xff, /* USAGE_PAGE (Vendor Page) */ @@ -64,7 +64,7 @@ const u8 PROGMEM oi_rdesc[] = { }; /* HID Mouse report descriptor */ -const u8 PROGMEM desc_hid_mouse_report[] = { +const u8 __attribute__((__progmem__)) desc_hid_mouse_report[] = { /* clang-format off */ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ 0x09, 0x02, /* USAGE (Mouse) */ @@ -98,7 +98,7 @@ const u8 PROGMEM desc_hid_mouse_report[] = { }; /* HID keyboard report descriptor */ -const u8 PROGMEM desc_hid_keyboard_report[] = { +const u8 __attribute__((__progmem__)) desc_hid_keyboard_report[] = { /* clang-format off */ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ 0x09, 0x06, /* USAGE (keyboard) */ @@ -142,7 +142,7 @@ const u8 PROGMEM desc_hid_keyboard_report[] = { /* clang-format on */ }; -const u8 PROGMEM oi_hid_desc[] = { +const u8 __attribute__((__progmem__)) oi_hid_desc[] = { /* HID */ 0x09, /* LENGTH */ 0x21, /* DESCRIPTOR TYPE (hid) */ @@ -155,7 +155,7 @@ const u8 PROGMEM oi_hid_desc[] = { 0x00, /* DESCRIPTOR LENGTH () */ }; -const u8 PROGMEM mouse_hid_desc[] = { +const u8 __attribute__((__progmem__)) mouse_hid_desc[] = { /* HID */ 0x09, /* LENGTH */ 0x21, /* DESCRIPTOR TYPE (hid) */ @@ -168,7 +168,7 @@ const u8 PROGMEM mouse_hid_desc[] = { 0x00, /* DESCRIPTOR LENGTH () */ }; -const u8 PROGMEM keyboard_hid_desc[] = { +const u8 __attribute__((__progmem__)) keyboard_hid_desc[] = { /* HID */ 0x09, /* LENGTH */ 0x21, /* DESCRIPTOR TYPE (hid) */ @@ -182,7 +182,7 @@ const u8 PROGMEM keyboard_hid_desc[] = { }; /* Configuration Descriptor */ -const u8 PROGMEM desc_configuration[] = { +const u8 __attribute__((__progmem__)) desc_configuration[] = { /* clang-format off */ /* configuration */ 0x09, /* LENGTH */ @@ -223,12 +223,11 @@ const u8 PROGMEM desc_configuration[] = { /* Endpoint out */ 0x07, /* LENGTH */ 0x05, /* DESCRIPTOR TYPE (Endpoint) */ - 0x01, /* ENDPOINT ADDRESS (Endpoint 1, OUT) */ + 0x02, /* ENDPOINT ADDRESS (Endpoint 2, OUT) */ 0x03, /* ATTRIBUTES (Interrupt) */ 0x40, 0x00, /* MAX PACKET SIZE (64) */ 0x0A, /* POLLING INTERVAL (100Hz) */ - /* Interface 1 - HID Mouse */ 0x09, /* LENGTH */ 0x04, /* DESCRIPTOR TYPE (Interface) */ @@ -251,7 +250,7 @@ const u8 PROGMEM desc_configuration[] = { /* Endpoint in */ 0x07, /* LENGTH */ 0x05, /* DESCRIPTOR TYPE (Endpoint) */ - 0x82, /* ENDPOINT ADDRESS (Endpoint 2, IN) */ + 0x83, /* ENDPOINT ADDRESS (Endpoint 3, IN) */ 0x03, /* ATTRIBUTES (Interrupt) */ 0x40, 0x00, /* MAX PACKET SIZE (64) */ 0x01, /* POLLING INTERVAL (1000Hz) */ @@ -279,14 +278,14 @@ const u8 PROGMEM desc_configuration[] = { /* Endpoint in */ 0x07, /* LENGTH */ 0x05, /* DESCRIPTOR TYPE (Endpoint) */ - 0x83, /* ENDPOINT ADDRESS (Endpoint 3, IN) */ + 0x84, /* ENDPOINT ADDRESS (Endpoint 4, IN) */ 0x03, /* ATTRIBUTES (Interrupt) */ 0x40, 0x00, /* MAX PACKET SIZE (64) */ 0x0A, /* POLLING INTERVAL (100Hz) */ /* Endpoint out */ 0x07, /* LENGTH */ 0x05, /* DESCRIPTOR TYPE (Endpoint) */ - 0x03, /* ENDPOINT ADDRESS (Endpoint 3, OUT) */ + 0x05, /* ENDPOINT ADDRESS (Endpoint 5, OUT) */ 0x03, /* ATTRIBUTES (Interrupt) */ 0x40, 0x00, /* MAX PACKET SIZE (64) */ 0x0A, /* POLLING INTERVAL (100Hz) */ @@ -294,9 +293,9 @@ const u8 PROGMEM desc_configuration[] = { }; /* String Descriptors */ -const USB_Descriptor_String_t PROGMEM lang_str = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG); -const USB_Descriptor_String_t PROGMEM manu_str = USB_STRING_DESCRIPTOR(L"Openinput"); -const USB_Descriptor_String_t PROGMEM prod_str = USB_STRING_DESCRIPTOR(L"Openinput Device"); +const USB_Descriptor_String_t __attribute__((__progmem__)) PROGMEM lang_str = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG); +const USB_Descriptor_String_t __attribute__((__progmem__)) PROGMEM manu_str = USB_STRING_DESCRIPTOR(L"Openinput"); +const USB_Descriptor_String_t __attribute__((__progmem__)) PROGMEM prod_str = USB_STRING_DESCRIPTOR(L"Openinput Device"); /** * This function is called by the library when in device mode, and must be overridden (see LUFA library "USB Descriptors" @@ -380,20 +379,3 @@ u16 CALLBACK_USB_GetDescriptor(const u16 w_value, const u16 w_index, const void *descriptor_address = addr; return size; } - -/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration - * of the USB device after enumeration, and configures the keyboard and mouse device endpoints. - */ -void EVENT_USB_Device_ConfigurationChanged(void) -{ - /* Setup Openinput Report Endpoints */ - Endpoint_ConfigureEndpoint(0x81, EP_TYPE_INTERRUPT, 0x40, 1); // IN - Endpoint_ConfigureEndpoint(0x01, EP_TYPE_INTERRUPT, 0x40, 1); // OUT - - /* Setup Mouse HID Report Endpoint */ - Endpoint_ConfigureEndpoint(0x82, EP_TYPE_INTERRUPT, 0x40, 1); // IN - - /* Setup Keyboard HID Report Endpoints */ - Endpoint_ConfigureEndpoint(0x83, EP_TYPE_INTERRUPT, 0x40, 1); // IN - Endpoint_ConfigureEndpoint(0x03, EP_TYPE_INTERRUPT, 0x40, 1); // OUT -} From 6d3bfb08b4e312bdfca0e90967ff6957c7895d03 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Sat, 21 May 2022 13:37:35 +0100 Subject: [PATCH 16/16] platform/avr: implement lufa hid driver and hid hal Signed-off-by: Rafael Silva --- config/families/avr.toml | 1 + src/platform/avr/hal/hid.c | 21 ++ src/platform/avr/hal/hid.h | 11 + src/platform/avr/usb.c | 292 ++++++++++++++------------ src/platform/avr/usb.h | 1 + src/targets/atmega32u4-generic/main.c | 21 ++ 6 files changed, 209 insertions(+), 138 deletions(-) create mode 100644 src/platform/avr/hal/hid.c create mode 100644 src/platform/avr/hal/hid.h diff --git a/config/families/avr.toml b/config/families/avr.toml index 17a5132f..f59a8ba1 100644 --- a/config/families/avr.toml +++ b/config/families/avr.toml @@ -16,6 +16,7 @@ source = [ 'boot.c', 'usb.c', 'usb_descriptors.c', + 'hal/hid.c', ] [dependencies] diff --git a/src/platform/avr/hal/hid.c b/src/platform/avr/hal/hid.c new file mode 100644 index 00000000..cc23df2d --- /dev/null +++ b/src/platform/avr/hal/hid.c @@ -0,0 +1,21 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#include "platform/avr/hal/hid.h" +#include "platform/avr/usb.h" + +int hid_hal_send(struct hid_hal_t interface, u8 *buffer, size_t buffer_size) +{ + usb_write_descriptor(0, buffer, buffer_size); +} + +struct hid_hal_t hid_hal_init(void) +{ + struct hid_hal_t hal = { + .send = hid_hal_send, + .drv_data = NULL, + }; + return hal; +} diff --git a/src/platform/avr/hal/hid.h b/src/platform/avr/hal/hid.h new file mode 100644 index 00000000..5c1d4cc5 --- /dev/null +++ b/src/platform/avr/hal/hid.h @@ -0,0 +1,11 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#pragma once + +#include "hal/hid.h" +#include "util/types.h" + +struct hid_hal_t hid_hal_init(void); diff --git a/src/platform/avr/usb.c b/src/platform/avr/usb.c index 33d7ca4c..79fb7d26 100644 --- a/src/platform/avr/usb.c +++ b/src/platform/avr/usb.c @@ -12,12 +12,73 @@ #include +/** Buffer to hold the previously generated HID report, for comparison purposes inside the HID class driver. */ +static u8 openinput_hid_report_buff[sizeof(struct oi_report_t)]; +static u8 mouse_hid_report_buff[sizeof(struct mouse_report)]; +static u8 keyboard_hid_report_buff[sizeof(struct keyboard_report)]; + +static u8 new_oi_report; +static struct oi_report_t oi_report; +static u8 oi_report_size; + +static u8 new_mouse_report; +static struct mouse_report mouse_report; +static u8 mouse_report_size; + +static u8 new_keyboard_report; +static struct keyboard_report keyboard_report; +static u8 keyboard_report_size; + static struct protocol_config_t protocol_config; -void usb_attach_protocol_config(struct protocol_config_t config) -{ - protocol_config = config; -} +/** LUFA HID Class driver interface configuration and state information. This structure is + * passed to all HID Class driver functions, so that multiple instances of the same class + * within a device can be differentiated from one another. + */ +USB_ClassInfo_HID_Device_t openinput_hid_interface = { + .Config = + { + .InterfaceNumber = 0, + .ReportINEndpoint = + { + .Address = 0x81, + .Size = 64, + .Banks = 1, + }, + .PrevReportINBuffer = openinput_hid_report_buff, + .PrevReportINBufferSize = sizeof(openinput_hid_report_buff), + }, +}; + +USB_ClassInfo_HID_Device_t mouse_hid_interface = { + .Config = + { + .InterfaceNumber = 1, + .ReportINEndpoint = + { + .Address = 0x83, + .Size = 64, + .Banks = 1, + }, + .PrevReportINBuffer = mouse_hid_report_buff, + .PrevReportINBufferSize = sizeof(mouse_hid_report_buff), + }, +}; + +USB_ClassInfo_HID_Device_t keyboard_hid_interface = { + .Config = + { + .InterfaceNumber = 2, + .ReportINEndpoint = + { + .Address = 0x84, + .Size = 64, + .Banks = 1, + }, + .PrevReportINBuffer = keyboard_hid_report_buff, + .PrevReportINBufferSize = sizeof(keyboard_hid_report_buff), + }, +}; void usb_init() { @@ -29,64 +90,30 @@ void usb_task() { USB_USBTask(); - /* openinput IN */ - Endpoint_SelectEndpoint(0x81); - - /* Check if Endpoint Ready for Read/Write */ - if (Endpoint_IsReadWriteAllowed()) { - /* Write Report Data */ - // Endpoint_Write_Stream_LE(&report_data, sizeof(report_data), NULL); - - /* Finalize the stream transfer to send the last packet */ - // Endpoint_ClearIN(); - } - - /* openinput OUT */ - Endpoint_SelectEndpoint(0x02); - - /* Check if Endpoint Ready for Read/Write */ - if (Endpoint_IsReadWriteAllowed()) { - /* Write Report Data */ - // Keyboard_ProcessLEDReport(Endpoint_Read_8()); - - /* Handshake the OUT Endpoint - clear endpoint and ready for next report */ - Endpoint_ClearOUT(); - } - - /* mouse IN */ - Endpoint_SelectEndpoint(0x83); - - /* Check if Endpoint Ready for Read/Write */ - if (Endpoint_IsReadWriteAllowed()) { - /* Write Report Data */ - // Endpoint_Write_Stream_LE(&report_data, sizeof(report_data), NULL); - - /* Finalize the stream transfer to send the last packet */ - // Endpoint_ClearIN(); - } - - /* keyboard IN */ - Endpoint_SelectEndpoint(0x84); - - /* Check if Endpoint Ready for Read/Write */ - if (Endpoint_IsReadWriteAllowed()) { - /* Write Report Data */ - // Endpoint_Write_Stream_LE(&report_data, sizeof(report_data), NULL); - - /* Finalize the stream transfer to send the last packet */ - // Endpoint_ClearIN(); - } - - /* keyboard OUT */ - Endpoint_SelectEndpoint(0x05); + HID_Device_USBTask(&openinput_hid_interface); + HID_Device_USBTask(&mouse_hid_interface); + HID_Device_USBTask(&keyboard_hid_interface); +} - /* Check if Endpoint Ready for Read/Write */ - if (Endpoint_IsReadWriteAllowed()) { - /* Write Report Data */ - // Keyboard_ProcessLEDReport(Endpoint_Read_8()); +void usb_attach_protocol_config(struct protocol_config_t config) +{ + protocol_config = config; +} - /* Handshake the OUT Endpoint - clear endpoint and ready for next report */ - Endpoint_ClearOUT(); +void usb_write_descriptor(u8 interface, u8 *report_data, u16 report_size) +{ + if (interface == openinput_hid_interface.Config.InterfaceNumber) { + memcpy(&oi_report, report_data, report_size); + oi_report_size = report_size; + new_oi_report = 1; + } else if (interface == mouse_hid_interface.Config.InterfaceNumber) { + memcpy(&mouse_report, report_data, report_size); + mouse_report_size = report_size; + new_mouse_report = 1; + } else if (interface == keyboard_hid_interface.Config.InterfaceNumber) { + memcpy(&keyboard_report, report_data, report_size); + keyboard_report_size = report_size; + new_keyboard_report = 1; } } @@ -104,90 +131,79 @@ void EVENT_USB_Device_Disconnect(void) { } -struct oi_report_t oi_rep; -struct mouse_report mouse_rep; -struct keyboard_report keyb_rep; +/** Event handler for the library USB Configuration Changed event. */ +void EVENT_USB_Device_ConfigurationChanged(void) +{ + HID_Device_ConfigureEndpoints(&openinput_hid_interface); + HID_Device_ConfigureEndpoints(&mouse_hid_interface); + HID_Device_ConfigureEndpoints(&keyboard_hid_interface); +} -/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to - * the device from the USB host before passing along unhandled control requests to the library for processing - * internally. +/** HID class driver callback function for the creation of HID reports to the host. + * + * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced + * \param[in,out] ReportID Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID + * \param[in] ReportType Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature + * \param[out] ReportData Pointer to a buffer where the created report should be stored + * \param[out] ReportSize Number of bytes written in the report (or zero if no report is to be sent) + * + * \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent */ -void EVENT_USB_Device_ControlRequest(void) +bool CALLBACK_HID_Device_CreateHIDReport( + USB_ClassInfo_HID_Device_t *const HIDInterfaceInfo, + uint8_t *const ReportID, + const uint8_t ReportType, + void *ReportData, + uint16_t *const ReportSize) { - struct oi_report_t oi_report; - uint8_t *ReportData; - uint8_t ReportSize; - - /* Handle HID Class specific requests */ - switch (USB_ControlRequest.bRequest) { - case HID_REQ_GetReport: - if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) { - Endpoint_ClearSETUP(); - - // /* Determine if it is the mouse or the keyboard data that is being requested */ - // if (USB_ControlRequest.wIndex == 0) { // openinput - // ReportData = (uint8_t *) &oi_rep; - // ReportSize = sizeof(struct oi_report_t); - // } else if (USB_ControlRequest.wIndex == 1) { // mouse - // ReportData = (uint8_t *) &mouse_rep; - // ReportSize = sizeof(struct mouse_report); - // } else if (USB_ControlRequest.wIndex == 2) { // keyboard - // ReportData = (uint8_t *) &keyb_rep; - // ReportSize = sizeof(struct keyboard_report); - // } - - // /* Write the report data to the control endpoint */ - // Endpoint_Write_Control_Stream_LE(ReportData, ReportSize); - Endpoint_ClearOUT(); - } - - break; - case HID_REQ_SetReport: - if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { - Endpoint_ClearSETUP(); - - /* Wait until the report has been sent by the host */ - while (!(Endpoint_IsOUTReceived())) { - if (USB_DeviceState == DEVICE_STATE_Unattached) - return; - } - - // if (USB_ControlRequest.wIndex == 0) { - // // for (size_t i = 0; i < USB_ControlRequest.wLength; i++) - // // { - // // ((uint8_t *)(&oi_report))[i] = Endpoint_Read_8(); - // // } - // // protocol_dispatch(protocol_config, (uint8_t *)(&oi_report), USB_ControlRequest.wLength); - - // } else if (USB_ControlRequest.wIndex == 2) { - // /* Read in the LED report from the host */ - // uint8_t LEDStatus = Endpoint_Read_8(); - // } - - /* Read in the LED report from the host */ - uint8_t LEDStatus = Endpoint_Read_8(); - - Endpoint_ClearOUT(); - Endpoint_ClearStatusStage(); - } - - break; + /* Determine which interface must have its report generated */ + if (HIDInterfaceInfo == &openinput_hid_interface) { + if (new_oi_report == 1) { + memcpy(ReportData, &oi_report, oi_report_size); + *ReportSize = oi_report_size; + new_oi_report = 0; + return true; + } else { + return false; + } + } else if (HIDInterfaceInfo == &mouse_hid_interface) { + if (new_mouse_report == 1) { + memcpy(ReportData, &mouse_report, mouse_report_size); + *ReportSize = mouse_report_size; + new_mouse_report = 0; + return true; + } else { + return false; + } + } else if (HIDInterfaceInfo == &keyboard_hid_interface) { + if (new_keyboard_report == 1) { + memcpy(ReportData, &keyboard_report, keyboard_report_size); + *ReportSize = keyboard_report_size; + new_keyboard_report = 0; + return true; + } else { + return false; + } } } -/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration - * of the USB device after enumeration, and configures the keyboard and mouse device endpoints. +/** HID class driver callback function for the processing of HID reports from the host. + * + * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced + * \param[in] ReportID Report ID of the received report from the host + * \param[in] ReportType The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature + * \param[in] ReportData Pointer to a buffer where the received report has been stored + * \param[in] ReportSize Size in bytes of the received HID report */ -void EVENT_USB_Device_ConfigurationChanged(void) +void CALLBACK_HID_Device_ProcessHIDReport( + USB_ClassInfo_HID_Device_t *const HIDInterfaceInfo, + const uint8_t ReportID, + const uint8_t ReportType, + const void *ReportData, + const uint16_t ReportSize) { - /* Setup Openinput Report Endpoints */ - Endpoint_ConfigureEndpoint(0x81, EP_TYPE_INTERRUPT, 0x40, 1); // IN - Endpoint_ConfigureEndpoint(0x02, EP_TYPE_INTERRUPT, 0x40, 1); // OUT - - /* Setup Mouse HID Report Endpoint */ - Endpoint_ConfigureEndpoint(0x83, EP_TYPE_INTERRUPT, 0x40, 1); // IN - - /* Setup Keyboard HID Report Endpoints */ - Endpoint_ConfigureEndpoint(0x84, EP_TYPE_INTERRUPT, 0x40, 1); // IN - Endpoint_ConfigureEndpoint(0x05, EP_TYPE_INTERRUPT, 0x40, 1); // OUT + if (HIDInterfaceInfo == &openinput_hid_interface) { + } else if (HIDInterfaceInfo == &keyboard_hid_interface) { + protocol_dispatch(protocol_config, (u8 *) ReportData, ReportSize); + } } diff --git a/src/platform/avr/usb.h b/src/platform/avr/usb.h index b8c7ff17..7c598400 100644 --- a/src/platform/avr/usb.h +++ b/src/platform/avr/usb.h @@ -10,3 +10,4 @@ void usb_init(); void usb_task(); void usb_attach_protocol_config(struct protocol_config_t config); +void usb_write_descriptor(u8 interface, u8 *report_data, u16 report_size); diff --git a/src/targets/atmega32u4-generic/main.c b/src/targets/atmega32u4-generic/main.c index 3a77da33..d1fb397a 100644 --- a/src/targets/atmega32u4-generic/main.c +++ b/src/targets/atmega32u4-generic/main.c @@ -8,10 +8,13 @@ #include #include +#include + #include "util/data.h" #include "util/types.h" #include "platform/avr/boot.h" +#include "platform/avr/hal/hid.h" #include "platform/avr/usb.h" void main() @@ -23,6 +26,24 @@ void main() /* Disable clock division */ clock_prescale_set(clock_div_1); + struct hid_hal_t hid_hal; + u8 info_functions[] = { + OI_FUNCTION_VERSION, + OI_FUNCTION_FW_INFO, + OI_FUNCTION_SUPPORTED_FUNCTION_PAGES, + OI_FUNCTION_SUPPORTED_FUNCTIONS, + }; + + /* create protocol config */ + struct protocol_config_t protocol_config; + memset(&protocol_config, 0, sizeof(protocol_config)); + protocol_config.device_name = "openinput Device"; + protocol_config.hid_hal = hid_hal_init(); + protocol_config.functions[INFO] = info_functions; + protocol_config.functions_size[INFO] = sizeof(info_functions); + + usb_attach_protocol_config(protocol_config); + /* Initialize USB Subsystem */ usb_init();