Unverified Commit 6d57ce69 authored by Alessio Perugini's avatar Alessio Perugini Committed by GitHub

Porting `legacy` tests to new integration-test infra (part 4...) (#2315)

* ported SketchThatIncludesArduinoH from legacy into integration test

* ported SketchWithStaticAsserts from legacy into integration test

* ported SketchWithEnumClass from legacy into integration test

* ported SketchWithExternC from legacy into integration test

* ported testBuilderSketchWithMultilinePrototypes from legacy into integration test

* ported SketchWithExternCMultiline from legacy into integration test

* ported SketchWithMultilineTemplate from legacy into integration test

* ported SketchWithFakeFunctionPointer from legacy into integration test

* fix wrong templating

* ported SketchWithMinMaxDefinitions from legacy into integration test

* ported SketchWithFastledsLibrary from legacy into integration test

* ported sketch with merged sketch and bootloader from legacy into integration test

* temporary disable legacy test, before porting them to the new infra

* update .gitignore

* ported CheckBuildOptionsFile from legacy into integration test

* ported SketchClassFunction from legacy into integration test

* ported SketchThatChecksIfSPIHasTransactionsAndIncludesMissingEthernet from legacy into integration test

* remove legacy builder test folder

* remove unsued fields from context
parent 9c073c14
......@@ -14,6 +14,7 @@ venv
/dist
/.pytest-tmp-dir
/node_modules/
__debug_bin*
# gRPC client example folder
/client_example/client_example
......
#include <Arduino.h>
#line 1 {{QuoteCppString .sketchMainFile}}
class test {
void asdf() {}
};
#line 4 {{QuoteCppString .sketchMainFile}}
void setup();
#line 7 {{QuoteCppString .sketchMainFile}}
void loop();
#line 8 {{QuoteCppString .sketchMainFile}}
void asdf();
#line 4 {{QuoteCppString .sketchMainFile}}
void setup() {
asdf();
}
void loop() {}
void asdf() {}
#line 1 {{QuoteCppString .sketchMainFile}}
// Arduino.h should not be automatically included by the Arduino
// preprocessor before the explicit include line in this sketch.
#if defined(HIGH)
#error Arduino.h seems to be automatically included
#endif
# include <Arduino.h>
#line 10 {{QuoteCppString .sketchMainFile}}
void setup();
#line 13 {{QuoteCppString .sketchMainFile}}
void loop();
#line 10 {{QuoteCppString .sketchMainFile}}
void setup() {
}
void loop() {
}
#include <Arduino.h>
#line 1 {{QuoteCppString .sketchMainFile}}
#line 1 {{QuoteCppString .sketchMainFile}}
void test();
#line 11 {{QuoteCppString .sketchMainFile}}
void test2();
#line 14 {{QuoteCppString .sketchMainFile}}
void setup();
#line 17 {{QuoteCppString .sketchMainFile}}
void loop();
#line 1 {{QuoteCppString .sketchMainFile}}
void test() {
test2();
}
enum class MyEnum
{
AValue = 0,
AnotherValue = 1
};
void test2() {
}
void setup() {
}
void loop() {
}
#include <Arduino.h>
#line 1 {{QuoteCppString .sketchMainFile}}
#line 1 {{QuoteCppString .sketchMainFile}}
void setup();
#line 6 {{QuoteCppString .sketchMainFile}}
void loop();
#line 11 {{QuoteCppString .sketchMainFile}}
extern "C" void test();
#line 1 {{QuoteCppString .sketchMainFile}}
void setup() {
// put your setup code here, to run once:
test();
}
void loop() {
// put your main code here, to run repeatedly:
}
extern "C" void test() {}
#include <Arduino.h>
#line 1 {{QuoteCppString .sketchMainFile}}
#line 1 {{QuoteCppString .sketchMainFile}}
void setup();
#line 5 {{QuoteCppString .sketchMainFile}}
void loop();
#line 15 {{QuoteCppString .sketchMainFile}}
extern "C" void test2();
#line 20 {{QuoteCppString .sketchMainFile}}
extern "C" void test4();
#line 26 {{QuoteCppString .sketchMainFile}}
extern "C" void test6();
#line 30 {{QuoteCppString .sketchMainFile}}
void test7();
#line 32 {{QuoteCppString .sketchMainFile}}
extern "C" void test10();
#line 1 {{QuoteCppString .sketchMainFile}}
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
test2();
test4();
test6();
test7();
test10();
}
extern "C" {
void test2() {}
}
extern "C"
{
void test4() {}
}
extern "C"
{
void test6() {}
}
// this function should not have C linkage
void test7() {}
extern "C" void test10() {
};
#include <Arduino.h>
#line 1 {{QuoteCppString .sketchMainFile}}
template< uint16_t nBuffSize >
class Foo{
public:
template< uint16_t N >
Foo &operator +=( const Foo<N> &ref ){
//...
return *this;
}
};
Foo<64> a;
Foo<32> b;
#line 15 {{QuoteCppString .sketchMainFile}}
void setup();
#line 19 {{QuoteCppString .sketchMainFile}}
void loop();
#line 15 {{QuoteCppString .sketchMainFile}}
void setup(){
a += b;
}
void loop(){}
#include <Arduino.h>
#line 1 {{QuoteCppString .sketchMainFile}}
#include "FastLED.h"
#define DATA_PIN 7
#define CLK_PIN 6
#define LED_TYPE APA102
#define COLOR_ORDER GRB
#define NUM_LEDS 79
CRGB leds[NUM_LEDS];
#define BRIGHTNESS 96
#define FRAMES_PER_SECOND 120
#line 12 {{QuoteCppString .sketchMainFile}}
void setup();
#line 17 {{QuoteCppString .sketchMainFile}}
void loop();
#line 25 {{QuoteCppString .sketchMainFile}}
void sinelon();
#line 12 {{QuoteCppString .sketchMainFile}}
void setup() {
FastLED.addLeds<LED_TYPE, DATA_PIN, CLK_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
}
void loop() {
}
typedef void (*SimplePatternList[])();
//SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm };
SimplePatternList gPatterns = {sinelon};
void sinelon()
{
}
#include <Arduino.h>
#line 1 {{QuoteCppString .sketchMainFile}}
// See: https://github.com/arduino/arduino-builder/issues/68
// The following avoid duplicate definitions of min and max
#undef min
#undef max
#include <memory>
#line 9 {{QuoteCppString .sketchMainFile}}
void setup();
#line 13 {{QuoteCppString .sketchMainFile}}
void loop();
#line 15 {{QuoteCppString .sketchMainFile}}
void test();
#line 9 {{QuoteCppString .sketchMainFile}}
void setup() {
test();
}
void loop() {}
void test() {}
#include <Arduino.h>
#line 1 {{QuoteCppString .sketchMainFile}}
#line 1 {{QuoteCppString .sketchMainFile}}
void setup();
#line 12 {{QuoteCppString .sketchMainFile}}
void myctagstestfunc(int a, int b, int c, int d);
#line 17 {{QuoteCppString .sketchMainFile}}
void loop();
#line 18 {{QuoteCppString .sketchMainFile}}
void test();
#line 21 {{QuoteCppString .sketchMainFile}}
void test3();
#line 25 {{QuoteCppString .sketchMainFile}}
void test5(int a, int b, int c);
#line 33 {{QuoteCppString .sketchMainFile}}
void test7();
#line 36 {{QuoteCppString .sketchMainFile}}
void test8();
#line 44 {{QuoteCppString .sketchMainFile}}
void test9(int a, int b);
#line 50 {{QuoteCppString .sketchMainFile}}
void test10(int a, int b, int c );
#line 1 {{QuoteCppString .sketchMainFile}}
void setup() {
myctagstestfunc(1,2,3,4);
test();
test3();
test5(1,2,3);
test7();
test8();
test9(42, 42);
test10(0,0,0);
}
void myctagstestfunc(int a,
int b,
int c,
int d) { }
void loop() {}
void
test() {}
void
// comment
test3() {}
void
test5(int a,
int b,
int c)
{
}
void /* comment */
test7() {}
void
/*
multi
line
comment
*/
test8() {}
void
/* comment */
test9(int a,
int b) {}
void test10(int a, // this
int b, // doesn't
int c // work
) {}
#include <Arduino.h>
#line 0 {{QuoteCppString .sketchMainFile}}
template< typename T > T func(T t);
#line 6 {{QuoteCppString .sketchMainFile}}
void setup();
#line 10 {{QuoteCppString .sketchMainFile}}
void loop();
#line 0 {{QuoteCppString .sketchMainFile}}
#line 1 {{QuoteCppString .sketchMainFile}}
template< typename T >
T func(T t){
return t * t;
}
void setup() {
func( 12.34f );
}
void loop() {}
#include <Arduino.h>
#line 1 {{QuoteCppString .sketchMainFile}}
// https://github.com/arduino/arduino-builder/issues/68
const int a = 10;
const int b = 20;
static_assert(a < b, "bar");
#line 8 {{QuoteCppString .sketchMainFile}}
void setup();
#line 12 {{QuoteCppString .sketchMainFile}}
void loop();
#line 15 {{QuoteCppString .sketchMainFile}}
void test();
#line 8 {{QuoteCppString .sketchMainFile}}
void setup() {
test();
}
void loop() {
}
void test() {
}
......@@ -27,8 +27,6 @@ import (
var tr = i18n.Tr
const DEFAULT_DEBUG_LEVEL = 5
type Builder struct{}
func (s *Builder) Run(ctx *types.Context) error {
......
// This file is part of arduino-cli.
//
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.
package test
import (
"fmt"
"os"
"path/filepath"
"testing"
bldr "github.com/arduino/arduino-cli/arduino/builder"
"github.com/arduino/arduino-cli/arduino/builder/detector"
"github.com/arduino/arduino-cli/arduino/builder/logger"
"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/arduino/sketch"
"github.com/arduino/arduino-cli/legacy/builder/types"
"github.com/arduino/go-paths-helper"
"github.com/stretchr/testify/require"
)
func cleanUpBuilderTestContext(t *testing.T, ctx *types.Context) {
if ctx.Builder.GetBuildPath() != nil {
require.NoError(t, ctx.Builder.GetBuildPath().RemoveAll())
}
}
func prepareBuilderTestContext(t *testing.T, ctx *types.Context, sketchPath *paths.Path, fqbnString string) *types.Context {
DownloadCoresAndToolsAndLibraries(t)
if ctx == nil {
ctx = &types.Context{}
}
if ctx.HardwareDirs.Len() == 0 {
ctx.HardwareDirs = paths.NewPathList(filepath.Join("..", "hardware"), "downloaded_hardware")
ctx.BuiltInToolsDirs = paths.NewPathList("downloaded_tools")
ctx.BuiltInLibrariesDirs = paths.New("downloaded_libraries")
ctx.OtherLibrariesDirs = paths.NewPathList("libraries")
}
buildPath, err := paths.MkTempDir("", "test_build_path")
require.NoError(t, err)
require.NotNil(t, buildPath)
// Create a Package Manager from the given context
// This should happen only on legacy arduino-builder.
// Hopefully this piece will be removed once the legacy package will be cleanedup.
pmb := packagemanager.NewBuilder(nil, nil, nil, nil, "arduino-builder")
for _, err := range pmb.LoadHardwareFromDirectories(ctx.HardwareDirs) {
// NoError(t, err)
fmt.Println(err)
}
if ctx.BuiltInToolsDirs != nil {
pmb.LoadToolsFromBundleDirectories(ctx.BuiltInToolsDirs)
}
pm := pmb.Build()
pme, _ /* never release... */ := pm.NewExplorer()
ctx.PackageManager = pme
var sk *sketch.Sketch
if sketchPath != nil {
s, err := sketch.New(sketchPath)
require.NoError(t, err)
sk = s
}
// This is an hack to avoid panic when the `NewBuilder` assert a condition on sketch path.
// Since the test will be migrated soon in an E2E manner we temporary set the sketch to be empty.
// so this assertion inside the Builder:
// buildPath().Canonical().EqualsTo(sk.FullPath.Canonical())`
// Doesn't fail
if sk == nil {
sk = &sketch.Sketch{
MainFile: &paths.Path{},
FullPath: paths.New(os.TempDir()),
OtherSketchFiles: []*paths.Path{},
AdditionalFiles: []*paths.Path{},
RootFolderFiles: []*paths.Path{},
Project: &sketch.Project{},
}
}
builderLogger := logger.New(nil, nil, false, "")
ctx.BuilderLogger = builderLogger
ctx.Builder, err = bldr.NewBuilder(
sk, nil, buildPath, false, nil, 0, nil,
ctx.HardwareDirs, ctx.BuiltInToolsDirs, ctx.OtherLibrariesDirs,
ctx.BuiltInLibrariesDirs, parseFQBN(t, "a:b:c"), false, nil, false,
nil, nil, builderLogger, nil,
)
require.NoError(t, err)
var actualPlatform, targetPlatform *cores.PlatformRelease
if fqbnString != "" {
fqbn := parseFQBN(t, fqbnString)
_, targetPlatfrm, _, boardBuildProperties, buildPlatform, err := pme.ResolveFQBN(fqbn)
require.NoError(t, err)
targetPlatform = targetPlatfrm
actualPlatform = buildPlatform
_, err = pme.FindToolsRequiredForBuild(targetPlatform, buildPlatform)
require.NoError(t, err)
ctx.Builder, err = bldr.NewBuilder(
sk, boardBuildProperties, buildPath, false, nil, 0, nil,
ctx.HardwareDirs, ctx.BuiltInToolsDirs, ctx.OtherLibrariesDirs,
ctx.BuiltInLibrariesDirs, fqbn, false, nil, false, targetPlatform,
actualPlatform, builderLogger, nil)
require.NoError(t, err)
ctx.PackageManager = pme
}
lm, libsResolver, _, err := detector.LibrariesLoader(
false, nil,
ctx.BuiltInLibrariesDirs, nil, ctx.OtherLibrariesDirs,
actualPlatform, targetPlatform,
)
require.NoError(t, err)
ctx.SketchLibrariesDetector = detector.NewSketchLibrariesDetector(
lm, libsResolver,
false,
false,
builderLogger,
)
return ctx
}
# VID 0x6666 is a prototype product Vendor ID
# http://www.linux-usb.org/usb.ids
menu.speed=Speed
menu.core=Core
menu.info=Info
# ATmega32u4 @ 16 MHz
atmega32u4.name=ATmega32u4
atmega32u4.menu.speed.16mhz=16 MHz
atmega32u4.menu.speed.16mhz.build.f_cpu=16000000L
atmega32u4.menu.speed.16mhz.bootloader.file=caterina_16mhz.hex
atmega32u4.menu.speed.8mhz=8 MHz
atmega32u4.menu.speed.8mhz.build.f_cpu=8000000L
atmega32u4.menu.speed.8mhz.bootloader.file=caterina_8mhz.hex
atmega32u4.vid.0=0x1D50
atmega32u4.pid.0=0x60B0
atmega32u4.vid.1=0x6666
atmega32u4.pid.1=0x60B0
atmega32u4.vid.2=0x2341
atmega32u4.pid.2=0x0036
atmega32u4.vid.3=0x2341
atmega32u4.pid.3=0x8036
atmega32u4.vid.4=0x2A03
atmega32u4.pid.4=0x0036
atmega32u4.vid.5=0x2A03
atmega32u4.pid.5=0x8036
atmega32u4.bootloader.tool=avrdude
atmega32u4.bootloader.low_fuses=0xff
atmega32u4.bootloader.high_fuses=0xd8
atmega32u4.bootloader.extended_fuses=0xcb
#atmega32u4.bootloader.file=caterina_16mhz.hex
atmega32u4.bootloader.unlock_bits=0x3F
atmega32u4.bootloader.lock_bits=0x2F
atmega32u4.upload.tool=avrdude
atmega32u4.upload.protocol=avr109
atmega32u4.upload.maximum_size=28672
atmega32u4.upload.maximum_data_size=2560
atmega32u4.upload.speed=57600
atmega32u4.upload.disable_flushing=true
atmega32u4.upload.use_1200bps_touch=true
atmega32u4.upload.wait_for_upload_port=true
atmega32u4.build.mcu=atmega32u4
#atmega32u4.build.f_cpu=16000000L
atmega32u4.build.vid=0x6666
atmega32u4.build.pid=0x60B0
atmega32u4.build.usb_product="USB IO Board"
atmega32u4.build.usb_manufacturer="ATmega32u4"
atmega32u4.build.board=AVR_LEONARDO
atmega32u4.build.core=arduino:arduino
atmega32u4.build.variant=leonardo
atmega32u4.build.extra_flags={build.usb_flags} -DMOUSE_ABS_ENABLED
# ATtiny841 @ internal 8 MHz
attiny841.name=ATtiny841 (8 MHz)
# use Standard Arduino Core
attiny841.menu.core.arduino=Standard Arduino
attiny841.menu.core.arduino.build.core=arduino:arduino
attiny841.menu.core.arduino.build.variant=tiny14
# use Spence Konde Core: https://github.com/SpenceKonde/arduino-tiny-841/
attiny841.menu.core.spencekonde=ATtiny841 (by Spence Konde)
#attiny841.menu.core.spencekonde.build.core=arduino-tiny-841:tiny
attiny841.menu.core.spencekonde.build.core=tiny841
attiny841.menu.core.spencekonde.build.variant=tiny14
# info menu item
attiny841.menu.info.info=Press Reset, when Uploading is shown.
attiny841.vid.0=0x16D0
attiny841.pid.0=0x0753
attiny841.bootloader.tool=avrdude
attiny841.bootloader.low_fuses=0xE2
attiny841.bootloader.high_fuses=0xDD
attiny841.bootloader.extended_fuses=0xFE
attiny841.bootloader.unlock_bits=0xFF
attiny841.bootloader.lock_bits=0xFF
attiny841.bootloader.file=micronucleus-t841.hex
attiny841.upload.tool=micronucleus
attiny841.upload.protocol=usb
attiny841.upload.wait_for_upload_port=false
attiny841.upload.use_1200bps_touch=false
attiny841.upload.disable_flushing=false
attiny841.upload.maximum_size=6500
attiny841.build.mcu=attiny841
attiny841.build.f_cpu=8000000L
attiny841.build.board=AVR_ATTINY841
#attiny841.build.core=arduino:arduino
#attiny841.build.variant=tiny14
# ATtiny85 @ internal 16.5 MHz
attiny85.name=ATtiny85 (16.5 MHz)
# use Standard Arduino Core
attiny85.menu.core.arduino=Standard Arduino
attiny85.menu.core.arduino.build.board=AVR_ATTINY85
attiny85.menu.core.arduino.build.core=arduino:arduino
attiny85.menu.core.arduino.build.variant=tiny8
# use Spence Konde Core: https://github.com/SpenceKonde/ATTinyCore
attiny85.menu.core.spencekonde=ATtiny85 (by Spence Konde)
attiny85.menu.core.spencekonde.build.board=AVR_ATTINY85
#attiny85.menu.core.spencekonde.build.core=ATTinyCore:tiny
attiny85.menu.core.spencekonde.build.core=tiny85
attiny85.menu.core.spencekonde.build.variant=tiny8
# use Digistump Core: https://github.com/digistump/DigistumpArduino
attiny85.menu.core.digistump=Digistump/Digispark
attiny85.menu.core.digistump.build.board=AVR_DIGISPARK
attiny85.menu.core.digistump.build.core=digistump:tiny
attiny85.menu.core.digistump.build.variant=digispark
# info menu item
attiny85.menu.info.info=Press Reset, when Uploading is shown.
attiny85.vid.0=0x16D0
attiny85.pid.0=0x0753
attiny85.bootloader.tool=avrdude
attiny85.bootloader.low_fuses=0xE1
attiny85.bootloader.high_fuses=0xDD
attiny85.bootloader.extended_fuses=0xFE
attiny85.bootloader.unlock_bits=0xFF
attiny85.bootloader.lock_bits=0xFF
attiny85.bootloader.file=micronucleus-t85.hex
attiny85.upload.tool=micronucleus
attiny85.upload.protocol=usb
attiny85.upload.wait_for_upload_port=false
attiny85.upload.use_1200bps_touch=false
attiny85.upload.disable_flushing=false
attiny85.upload.maximum_size=6300
attiny85.build.mcu=attiny85
attiny85.build.f_cpu=16500000L
attiny85.build.board=AVR_ATTINY85
#attiny85.build.core=arduino:arduino
#attiny85.build.variant=tiny8
# Watterott AVR Core and platform.
# ------------------------------
#
# For more info:
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification
name=Watterott AVR Boards
version=1.0.0
# AVR compile variables
# ---------------------
compiler.warning_flags=-w
compiler.warning_flags.none=-w
compiler.warning_flags.default=
compiler.warning_flags.more=-Wall
compiler.warning_flags.all=-Wall -Wextra
# Default "compiler.path" is correct, change only if you want to overidde the initial value
#compiler.path={runtime.ide.path}/hardware/tools/avr/bin/
compiler.path={runtime.tools.avr-gcc.path}/bin/
compiler.c.cmd=avr-gcc
compiler.c.flags=-c -g -Os {compiler.warning_flags} -ffunction-sections -fdata-sections -MMD
# -w flag added to avoid printing a wrong warning http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59396
# This is fixed in gcc 4.8.3 and will be removed as soon as we update the toolchain
compiler.c.elf.flags=-Os {compiler.warning_flags} -Wl,--gc-sections
compiler.c.elf.cmd=avr-gcc
compiler.S.flags=-c -g -x assembler-with-cpp
compiler.cpp.cmd=avr-g++
compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD
compiler.ar.cmd=avr-ar
compiler.ar.flags=rcs
compiler.objcopy.cmd=avr-objcopy
compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0
compiler.elf2hex.flags=-O ihex -R .eeprom
compiler.elf2hex.cmd=avr-objcopy
compiler.ldflags=
compiler.size.cmd=avr-size
# This can be overriden in boards.txt
build.extra_flags=
# These can be overridden in platform.local.txt
compiler.c.extra_flags=
compiler.c.elf.extra_flags=
compiler.S.extra_flags=
compiler.cpp.extra_flags=
compiler.ar.extra_flags=
compiler.objcopy.eep.extra_flags=
compiler.elf2hex.extra_flags=
# AVR compile patterns
# --------------------
## Compile c files
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Compile c++ files
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Compile S files
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Create archives
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/{archive_file}" "{object_file}"
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm
## Create output files (.eep and .hex)
recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep"
recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
## Save hex
recipe.output.tmp_file={build.project_name}.hex
recipe.output.save_file={build.project_name}.{build.variant}.hex
## Compute size
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).*
recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).*
recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).*
## Preprocessor
preproc.includes.flags=-w -x c++ -M -MG -MP
recipe.preproc.includes="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.includes.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}"
preproc.macros.flags=-w -x c++ -E -CC
recipe.preproc.macros="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.macros.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}"
# AVR Uploader/Programmers tools
# ------------------------------
## AVRdude
#tools.avrdude.path={runtime.ide.path}/hardware/tools/avr/
tools.avrdude.path={runtime.tools.avrdude.path}
tools.avrdude.cmd.path={path}/bin/avrdude
#tools.avrdude.config.path={path}/etc/avrdude.conf
tools.avrdude.config.path={runtime.platform.path}/tools/avrdude.conf
tools.avrdude.upload.params.verbose=-v
tools.avrdude.upload.params.quiet=-q -q
tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D "-Uflash:w:{build.path}/{build.project_name}.hex:i"
tools.avrdude.program.params.verbose=-v
tools.avrdude.program.params.quiet=-q -q
tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} -p{build.mcu} -c{protocol} -P{serial.port} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i"
tools.avrdude.erase.params.verbose=-v
tools.avrdude.erase.params.quiet=-q -q
tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} -P{serial.port} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m
tools.avrdude.bootloader.params.verbose=-v
tools.avrdude.bootloader.params.quiet=-q -q
tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} -P{serial.port} {program.extra_params} "-Uflash:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m
## Micronucleus
tools.micronucleus.path={runtime.tools.micronucleus.path}
tools.micronucleus.cmd=micronucleus
tools.micronucleus.cmd.windows=micronucleus.exe
tools.micronucleus.upload.params.verbose=
tools.micronucleus.upload.params.quiet=
tools.micronucleus.upload.pattern="{path}/{cmd}" --run --timeout 60 "{build.path}/{build.project_name}.hex"
tools.micronucleus.program.params.verbose=
tools.micronucleus.program.params.quiet=
tools.micronucleus.program.pattern="{path}/{cmd}" --run --timeout 60 "{build.path}/{build.project_name}.hex"
tools.micronucleus.erase.params.verbose=
tools.micronucleus.erase.params.quiet=
tools.micronucleus.erase.pattern=
#tools.micronucleus.erase.pattern="{path}/{cmd}" --erase-only --timeout 60
tools.micronucleus.bootloader.params.verbose=
tools.micronucleus.bootloader.params.quiet=
tools.micronucleus.bootloader.pattern="{path}/{cmd}" --run --timeout 60 "{runtime.platform.path}/bootloaders/{bootloader.file}"
# USB Default Flags
# Default blank usb manufacturer will be filled it at compile time
# - from numeric vendor ID, set to Unknown otherwise
build.usb_manufacturer="Unknown"
build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}'
// This file is part of arduino-cli.
//
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
// Copyright 2015 Matthijs Kooijman
//
// This software is released under the GNU General Public License version 3,
// which covers the main part of arduino-cli.
// The terms of this license can be found at:
// https://www.gnu.org/licenses/gpl-3.0.en.html
//
// You can be released from the requirements of the above licenses by purchasing
// a commercial license. Buying such a license is mandatory if you want to
// modify or otherwise use the software for commercial activities involving the
// Arduino software without disclosing the source code of your own applications.
// To purchase a commercial license, send an email to license@arduino.cc.
package test
import (
"testing"
"github.com/arduino/arduino-cli/arduino/cores"
paths "github.com/arduino/go-paths-helper"
"github.com/stretchr/testify/require"
)
func SetupBuildPath(t *testing.T) *paths.Path {
buildPath, err := paths.MkTempDir("", "test_build_path")
require.NoError(t, err)
return buildPath
}
func parseFQBN(t *testing.T, fqbnIn string) *cores.FQBN {
fqbn, err := cores.ParseFQBN(fqbnIn)
require.NoError(t, err)
return fqbn
}
This diff is collapsed.
#warning IRRemote included!
\ No newline at end of file
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@arduino.cc>
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
* Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
* SPI Master library for arduino.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/
#include "SPI.h"
SPIClass SPI;
uint8_t SPIClass::initialized = 0;
uint8_t SPIClass::interruptMode = 0;
uint8_t SPIClass::interruptMask = 0;
uint8_t SPIClass::interruptSave = 0;
#ifdef SPI_TRANSACTION_MISMATCH_LED
uint8_t SPIClass::inTransactionFlag = 0;
#endif
void SPIClass::begin()
{
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
if (!initialized) {
// Set SS to high so a connected chip will be "deselected" by default
uint8_t port = digitalPinToPort(SS);
uint8_t bit = digitalPinToBitMask(SS);
volatile uint8_t *reg = portModeRegister(port);
// if the SS pin is not already configured as an output
// then set it high (to enable the internal pull-up resistor)
if(!(*reg & bit)){
digitalWrite(SS, HIGH);
}
// When the SS pin is set as OUTPUT, it can be used as
// a general purpose output port (it doesn't influence
// SPI operations).
pinMode(SS, OUTPUT);
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
// automatically switches to Slave, so the data direction of
// the SS pin MUST be kept as OUTPUT.
SPCR |= _BV(MSTR);
SPCR |= _BV(SPE);
// Set direction register for SCK and MOSI pin.
// MISO pin automatically overrides to INPUT.
// By doing this AFTER enabling SPI, we avoid accidentally
// clocking in a single bit since the lines go directly
// from "input" to SPI control.
// http://code.google.com/p/arduino/issues/detail?id=888
pinMode(SCK, OUTPUT);
pinMode(MOSI, OUTPUT);
}
initialized++; // reference count
SREG = sreg;
}
void SPIClass::end() {
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
// Decrease the reference counter
if (initialized)
initialized--;
// If there are no more references disable SPI
if (!initialized) {
SPCR &= ~_BV(SPE);
interruptMode = 0;
#ifdef SPI_TRANSACTION_MISMATCH_LED
inTransactionFlag = 0;
#endif
}
SREG = sreg;
}
// mapping of interrupt numbers to bits within SPI_AVR_EIMSK
#if defined(__AVR_ATmega32U4__)
#define SPI_INT0_MASK (1<<INT0)
#define SPI_INT1_MASK (1<<INT1)
#define SPI_INT2_MASK (1<<INT2)
#define SPI_INT3_MASK (1<<INT3)
#define SPI_INT4_MASK (1<<INT6)
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
#define SPI_INT0_MASK (1<<INT0)
#define SPI_INT1_MASK (1<<INT1)
#define SPI_INT2_MASK (1<<INT2)
#define SPI_INT3_MASK (1<<INT3)
#define SPI_INT4_MASK (1<<INT4)
#define SPI_INT5_MASK (1<<INT5)
#define SPI_INT6_MASK (1<<INT6)
#define SPI_INT7_MASK (1<<INT7)
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
#define SPI_INT0_MASK (1<<INT4)
#define SPI_INT1_MASK (1<<INT5)
#define SPI_INT2_MASK (1<<INT0)
#define SPI_INT3_MASK (1<<INT1)
#define SPI_INT4_MASK (1<<INT2)
#define SPI_INT5_MASK (1<<INT3)
#define SPI_INT6_MASK (1<<INT6)
#define SPI_INT7_MASK (1<<INT7)
#else
#ifdef INT0
#define SPI_INT0_MASK (1<<INT0)
#endif
#ifdef INT1
#define SPI_INT1_MASK (1<<INT1)
#endif
#ifdef INT2
#define SPI_INT2_MASK (1<<INT2)
#endif
#endif
void SPIClass::usingInterrupt(uint8_t interruptNumber)
{
uint8_t mask = 0;
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
switch (interruptNumber) {
#ifdef SPI_INT0_MASK
case 0: mask = SPI_INT0_MASK; break;
#endif
#ifdef SPI_INT1_MASK
case 1: mask = SPI_INT1_MASK; break;
#endif
#ifdef SPI_INT2_MASK
case 2: mask = SPI_INT2_MASK; break;
#endif
#ifdef SPI_INT3_MASK
case 3: mask = SPI_INT3_MASK; break;
#endif
#ifdef SPI_INT4_MASK
case 4: mask = SPI_INT4_MASK; break;
#endif
#ifdef SPI_INT5_MASK
case 5: mask = SPI_INT5_MASK; break;
#endif
#ifdef SPI_INT6_MASK
case 6: mask = SPI_INT6_MASK; break;
#endif
#ifdef SPI_INT7_MASK
case 7: mask = SPI_INT7_MASK; break;
#endif
default:
interruptMode = 2;
break;
}
interruptMask |= mask;
if (!interruptMode)
interruptMode = 1;
SREG = sreg;
}
void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
{
// Once in mode 2 we can't go back to 0 without a proper reference count
if (interruptMode == 2)
return;
uint8_t mask = 0;
uint8_t sreg = SREG;
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
switch (interruptNumber) {
#ifdef SPI_INT0_MASK
case 0: mask = SPI_INT0_MASK; break;
#endif
#ifdef SPI_INT1_MASK
case 1: mask = SPI_INT1_MASK; break;
#endif
#ifdef SPI_INT2_MASK
case 2: mask = SPI_INT2_MASK; break;
#endif
#ifdef SPI_INT3_MASK
case 3: mask = SPI_INT3_MASK; break;
#endif
#ifdef SPI_INT4_MASK
case 4: mask = SPI_INT4_MASK; break;
#endif
#ifdef SPI_INT5_MASK
case 5: mask = SPI_INT5_MASK; break;
#endif
#ifdef SPI_INT6_MASK
case 6: mask = SPI_INT6_MASK; break;
#endif
#ifdef SPI_INT7_MASK
case 7: mask = SPI_INT7_MASK; break;
#endif
default:
break;
// this case can't be reached
}
interruptMask &= ~mask;
if (!interruptMask)
interruptMode = 0;
SREG = sreg;
}
This diff is collapsed.
#######################################
# Syntax Coloring Map SPI
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
SPI KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
end KEYWORD2
transfer KEYWORD2
setBitOrder KEYWORD2
setDataMode KEYWORD2
setClockDivider KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
SPI_CLOCK_DIV4 LITERAL1
SPI_CLOCK_DIV16 LITERAL1
SPI_CLOCK_DIV64 LITERAL1
SPI_CLOCK_DIV128 LITERAL1
SPI_CLOCK_DIV2 LITERAL1
SPI_CLOCK_DIV8 LITERAL1
SPI_CLOCK_DIV32 LITERAL1
SPI_CLOCK_DIV64 LITERAL1
SPI_MODE0 LITERAL1
SPI_MODE1 LITERAL1
SPI_MODE2 LITERAL1
SPI_MODE3 LITERAL1
\ No newline at end of file
name=SPI
version=1.0
author=Arduino
maintainer=Arduino <info@arduino.cc>
sentence=Enables the communication with devices that use the Serial Peripheral Interface (SPI) Bus. For all Arduino boards, BUT Arduino DUE.
paragraph=
url=http://arduino.cc/en/Reference/SPI
architectures=avr
types=Arduino
category=Other
#######################################
# Syntax Coloring Map For USBHost
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
MouseController KEYWORD1
USBHost KEYWORD1
KeyboardController KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
Task KEYWORD2
mouseMoved KEYWORD2
mouseDragged KEYWORD2
mousePressed KEYWORD2
mouseReleased KEYWORD2
getXChange KEYWORD2
getYChange KEYWORD2
getButton KEYWORD2
keyPressed KEYWORD2
keyReleased KEYWORD2
getModifiers KEYWORD2
getKey KEYWORD2
getOemKey KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
name=USBHost
version=1.0
author=Arduino
maintainer=Arduino <info@arduino.cc>
sentence=Allows the communication with USB peripherals like mice, keyboards, and thumbdrives. For Arduino Due and Zero.
paragraph=The USBHost library allows the board to appear as a USB host, enabling it to communicate with peripherals like USB mice and keyboards. USBHost does not support devices that are connected through USB hubs. This includes some keyboards that have an internal hub.
url=http://arduino.cc/en/Reference/USBHost
architectures=samd
category=Other
/*
Copyright (c) 2012 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <KeyboardController.h>
extern "C" {
void __keyboardControllerEmptyCallback() { }
}
void keyPressed() __attribute__ ((weak, alias("__keyboardControllerEmptyCallback")));
void keyReleased() __attribute__ ((weak, alias("__keyboardControllerEmptyCallback")));
void KeyboardController::OnKeyDown(uint8_t _mod, uint8_t _oemKey) {
modifiers = _mod;
keyOem = _oemKey;
key = OemToAscii(_mod, _oemKey);
keyPressed();
}
void KeyboardController::OnKeyUp(uint8_t _mod, uint8_t _oemKey) {
modifiers = _mod;
keyOem = _oemKey;
key = OemToAscii(_mod, _oemKey);
keyReleased();
}
/*
Copyright (c) 2012 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef KEYBOARD_CONTROLLER_H
#define KEYBOARD_CONTROLLER_H
#include <hidboot.h>
enum KeyboardModifiers {
LeftCtrl = 1,
LeftShift = 2,
Alt = 4,
LeftCmd = 8,
RightCtrl = 16,
RightShift = 32,
AltGr = 64,
RightCmd = 128
};
class KeyboardController : public KeyboardReportParser {
public:
KeyboardController(USBHost &usb) : hostKeyboard(&usb), key(0), keyOem(0), modifiers(0) {
hostKeyboard.SetReportParser(0, this);
};
uint8_t getKey() { return key; };
uint8_t getModifiers() { return modifiers; };
uint8_t getOemKey() { return keyOem; };
protected:
virtual void OnKeyDown(uint8_t mod, uint8_t key);
virtual void OnKeyUp(uint8_t mod, uint8_t key);
private:
HIDBoot<HID_PROTOCOL_KEYBOARD> hostKeyboard;
uint8_t key, keyOem, modifiers;
};
#endif
/*
Copyright (c) 2012 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MouseController.h>
extern "C" {
void __mouseControllerEmptyCallback() { }
}
void mouseClicked() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mouseDragged() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mouseMoved() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mousePressed() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mouseReleased() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
int MouseController::getXChange() {
int r = dx;
dx = 0;
return r;
}
int MouseController::getYChange() {
int r = dy;
dy = 0;
return r;
}
void MouseController::OnMouseMove(MOUSEINFO *mi) {
dx += mi->dX;
dy += mi->dY;
if (buttons != 0)
mouseDragged();
else
mouseMoved();
}
void MouseController::OnLeftButtonUp(MOUSEINFO *mi) {
buttons &= ~LEFT_BUTTON;
mouseReleased();
mouseClicked();
}
void MouseController::OnLeftButtonDown(MOUSEINFO *mi) {
buttons |= LEFT_BUTTON;
mousePressed();
}
void MouseController::OnMiddleButtonUp(MOUSEINFO *mi) {
buttons &= ~MIDDLE_BUTTON;
mouseReleased();
mouseClicked();
}
void MouseController::OnMiddleButtonDown(MOUSEINFO *mi) {
buttons |= MIDDLE_BUTTON;
mousePressed();
}
void MouseController::OnRightButtonUp(MOUSEINFO *mi) {
buttons &= ~RIGHT_BUTTON;
mouseReleased();
mouseClicked();
}
void MouseController::OnRightButtonDown(MOUSEINFO *mi) {
buttons |= RIGHT_BUTTON;
mousePressed();
}
/*
Copyright (c) 2012 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MOUSE_CONTROLLER_H
#define MOUSE_CONTROLLER_H
#include <hidboot.h>
enum MouseButton {
LEFT_BUTTON = 0x01,
MIDDLE_BUTTON = 0x02,
RIGHT_BUTTON = 0x04
};
class MouseController : public MouseReportParser
{
public:
MouseController(USBHost &usb) : hostMouse(&usb), dx(0), dy(0), buttons(0) {
hostMouse.SetReportParser(0, this);
};
bool getButton(MouseButton button) { return (buttons & button) == button; };
int getXChange();
int getYChange();
// int getWheelChange(); // Not implemented
protected:
virtual void OnMouseMove(MOUSEINFO *mi);
virtual void OnLeftButtonUp(MOUSEINFO *mi);
virtual void OnLeftButtonDown(MOUSEINFO *mi);
virtual void OnMiddleButtonUp(MOUSEINFO *mi);
virtual void OnMiddleButtonDown(MOUSEINFO *mi);
virtual void OnRightButtonUp(MOUSEINFO *mi);
virtual void OnRightButtonDown(MOUSEINFO *mi);
private:
HIDBoot<HID_PROTOCOL_MOUSE> hostMouse;
int dx, dy;
int buttons;
};
#endif
This diff is collapsed.
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
/* USB functions */
#ifndef USB_H_INCLUDED
#define USB_H_INCLUDED
#define _usb_h_
#include <stdint.h>
#define ARDUINO 101
//#include "Arduino.h"
#include "macros.h"
// None of these should ever be included by a driver, or a user's sketch.
#include "variant.h"
#define USB_HOST_SERIAL SERIAL_PORT_MONITOR
#include "Print.h"
#include "printhex.h"
#include "message.h"
#include "hexdump.h"
#include "sink_parser.h"
#include "address.h"
#include "usb_ch9.h"
//#include "usbhost.h"
#include "UsbCore.h"
#include "parsetools.h"
#include "confdescparser.h"
#endif /* USB_H_INCLUDED */
This diff is collapsed.
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#if !defined(_usb_h_) || defined(ADDRESS_H_INCLUDED)
#error "Never include address.h directly; include Usb.h instead"
#else
#define ADDRESS_H_INCLUDED
#include <stddef.h>
#include <stdint.h>
/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */
/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */
#define USB_NAK_MAX_POWER 15 //NAK binary order maximum value
#define USB_NAK_DEFAULT 14 //default 32K-1 NAKs before giving up
#define USB_NAK_NOWAIT 1 //Single NAK stops transfer
#define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout
struct EpInfo {
uint32_t epAddr; // Endpoint address
uint32_t maxPktSize; // Maximum packet size
union {
uint8_t epAttribs;
struct {
uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
};
};
};
// 7 6 5 4 3 2 1 0
// ---------------------------------
// | | H | P | P | P | A | A | A |
// ---------------------------------
//
// H - if 1 the address is a hub address
// P - parent hub address
// A - device address / port number in case of hub
//
struct UsbDeviceAddress {
union {
struct {
uint32_t bmAddress : 3; // device address/port number
uint32_t bmParent : 3; // parent hub address
uint32_t bmHub : 1; // hub flag
uint32_t bmReserved : 25; // reserved, must be zerro
};
uint32_t devAddress;
};
};
#define bmUSB_DEV_ADDR_ADDRESS 0x07
#define bmUSB_DEV_ADDR_PARENT 0x38
#define bmUSB_DEV_ADDR_HUB 0x40
struct UsbDeviceDefinition {
EpInfo *epinfo; // endpoint info pointer
UsbDeviceAddress address;
uint32_t epcount; // number of endpoints
uint32_t lowspeed; // indicates if a device is the low speed one
// uint8_t devclass; // device class
};
class AddressPool {
public:
virtual UsbDeviceDefinition* GetUsbDevicePtr(uint32_t addr) = 0;
virtual uint32_t AllocAddress(uint32_t parent, uint32_t is_hub = 0, uint32_t port = 0) = 0;
virtual void FreeAddress(uint32_t addr) = 0;
};
typedef void (*UsbDeviceHandleFunc)(UsbDeviceDefinition *pdev);
#define ADDR_ERROR_INVALID_INDEX 0xFF
#define ADDR_ERROR_INVALID_ADDRESS 0xFF
template <const uint32_t MAX_DEVICES_ALLOWED>
class AddressPoolImpl : public AddressPool {
EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device
uint32_t hubCounter; // hub counter is kept
// in order to avoid hub address duplication
UsbDeviceDefinition thePool[MAX_DEVICES_ALLOWED];
// Initializes address pool entry
void InitEntry(uint32_t index) {
thePool[index].address.devAddress = 0;
thePool[index].epcount = 1;
thePool[index].lowspeed = 0;
thePool[index].epinfo = &dev0ep;
};
// Returns thePool index for a given address
uint32_t FindAddressIndex(uint32_t address = 0) {
for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) {
if(thePool[i].address.devAddress == address)
return i;
}
return 0;
};
// Returns thePool child index for a given parent
uint32_t FindChildIndex(UsbDeviceAddress addr, uint32_t start = 1) {
for (uint32_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) {
if(thePool[i].address.bmParent == addr.bmAddress)
return i;
}
return 0;
};
// Frees address entry specified by index parameter
void FreeAddressByIndex(uint32_t index) {
// Zero field is reserved and should not be affected
if(index == 0)
return;
UsbDeviceAddress uda = thePool[index].address;
// If a hub was switched off all port addresses should be freed
if(uda.bmHub == 1) {
for (uint32_t i = 1; (i = FindChildIndex(uda, i));)
FreeAddressByIndex(i);
// If the hub had the last allocated address, hubCounter should be decremented
if(hubCounter == uda.bmAddress)
hubCounter--;
}
InitEntry(index);
}
// Initializes the whole address pool at once
void InitAllAddresses() {
for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
InitEntry(i);
hubCounter = 0;
};
public:
AddressPoolImpl() : hubCounter(0) {
// Zero address is reserved
InitEntry(0);
thePool[0].address.devAddress = 0;
thePool[0].epinfo = &dev0ep;
dev0ep.epAddr = 0;
dev0ep.maxPktSize = 8;
dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0
dev0ep.bmNakPower = USB_NAK_MAX_POWER;
InitAllAddresses();
};
// Returns a pointer to a specified address entry
virtual UsbDeviceDefinition* GetUsbDevicePtr(uint32_t addr) {
if(!addr)
return thePool;
uint32_t index = FindAddressIndex(addr);
return (!index) ? NULL : thePool + index;
};
// Performs an operation specified by pfunc for each addressed device
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
if(!pfunc)
return;
for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
if(thePool[i].address.devAddress)
pfunc(thePool + i);
};
// Allocates new address
virtual uint32_t AllocAddress(uint32_t parent, uint32_t is_hub = 0, uint32_t port = 0) {
/* if (parent != 0 && port == 0)
USB_HOST_SERIAL.println("PRT:0"); */
UsbDeviceAddress _parent;
_parent.devAddress = parent;
if(_parent.bmReserved || port > 7)
//if(parent > 127 || port > 7)
return 0;
if(is_hub && hubCounter == 7)
return 0;
// finds first empty address entry starting from one
uint32_t index = FindAddressIndex(0);
if(!index) // if empty entry is not found
return 0;
if(_parent.devAddress == 0) {
if(is_hub) {
thePool[index].address.devAddress = 0x41;
hubCounter++;
} else
thePool[index].address.devAddress = 1;
return thePool[index].address.devAddress;
}
UsbDeviceAddress addr;
addr.devAddress = 0; // Ensure all bits are zero
addr.bmParent = _parent.bmAddress;
if(is_hub) {
addr.bmHub = 1;
addr.bmAddress = ++hubCounter;
} else {
addr.bmHub = 0;
addr.bmAddress = port;
}
thePool[index].address = addr;
/*
USB_HOST_SERIAL.print("Addr:");
USB_HOST_SERIAL.print(addr.bmHub, HEX);
USB_HOST_SERIAL.print(".");
USB_HOST_SERIAL.print(addr.bmParent, HEX);
USB_HOST_SERIAL.print(".");
USB_HOST_SERIAL.println(addr.bmAddress, HEX);
*/
return thePool[index].address.devAddress;
};
// Empties pool entry
virtual void FreeAddress(uint32_t addr) {
// if the root hub is disconnected all the addresses should be initialized
if(addr == 0x41) {
InitAllAddresses();
return;
}
uint32_t index = FindAddressIndex(addr);
FreeAddressByIndex(index);
};
// Returns number of hubs attached
// It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs.
//uint32_t GetNumHubs()
//{
// return hubCounter;
//};
//uint32_t GetNumDevices()
//{
// uint32_t counter = 0;
// for (uint32_t i=1; i<MAX_DEVICES_ALLOWED; i++)
// if (thePool[i].address != 0);
// counter++;
// return counter;
//};
};
#endif /* ADDRESS_H_INCLUDED */
This diff is collapsed.
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
/* Google ADK interface support header */
#ifndef ADK_H_INCLUDED
#define ADK_H_INCLUDED
#include <stdint.h>
#include "Usb.h"
#include "hid.h"
#include "Arduino.h"
// #define ADK_VID 0x18D1
// #define ADK_PID 0x2D00
// #define ADB_PID 0x2D01
// JCB
#define ADK_VID 0x04E8
#define ADK_PID 0x685C
#define ADB_PID 0x685D
#define XOOM //enables repeating getProto() and getConf() attempts
//necessary for slow devices such as Motorola XOOM
//defined by default, can be commented out to save memory
/* requests */
#define ADK_GETPROTO 51 //check USB accessory protocol version 0x33
#define ADK_SENDSTR 52 //send identifying string 0x34
#define ADK_ACCSTART 53 //start device in accessory mode 0x35
#define bmREQ_ADK_GET USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
#define bmREQ_ADK_SEND USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
#define ACCESSORY_STRING_MANUFACTURER 0
#define ACCESSORY_STRING_MODEL 1
#define ACCESSORY_STRING_DESCRIPTION 2
#define ACCESSORY_STRING_VERSION 3
#define ACCESSORY_STRING_URI 4
#define ACCESSORY_STRING_SERIAL 5
#define ADK_MAX_ENDPOINTS 3 //endpoint 0, bulk_IN, bulk_OUT
class ADK;
class ADK : public USBDeviceConfig, public UsbConfigXtracter {
private:
/* ID strings */
const char* manufacturer;
const char* model;
const char* description;
const char* version;
const char* uri;
const char* serial;
/* ADK proprietary requests */
uint32_t getProto(uint8_t* adkproto);
uint32_t sendStr(uint32_t index, const char* str);
uint32_t switchAcc(void);
protected:
static const uint32_t epDataInIndex; // DataIn endpoint index
static const uint32_t epDataOutIndex; // DataOUT endpoint index
/* Mandatory members */
USBHost *pUsb;
uint32_t bAddress; // Device USB address
uint32_t bConfNum; // configuration number
uint32_t bNumEP; // total number of EP in the configuration
uint32_t ready;
/* Endpoint data structure */
EpInfo epInfo[ADK_MAX_ENDPOINTS];
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
public:
ADK(USBHost *pUsb, const char* manufacturer,
const char* model,
const char* description,
const char* version,
const char* uri,
const char* serial);
// Methods for receiving and sending data
uint32_t RcvData(uint8_t *nbytesptr, uint8_t *dataptr);
uint32_t SndData(uint32_t nbytes, uint8_t *dataptr);
// USBDeviceConfig implementation
virtual uint32_t ConfigureDevice(uint32_t parent, uint32_t port, uint32_t lowspeed);
virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed);
virtual uint32_t Release();
virtual uint32_t Poll() {
return 0;
};
virtual uint32_t GetAddress() {
return bAddress;
};
virtual uint32_t isReady() {
return ready;
};
virtual uint32_t VIDPIDOK(uint32_t vid, uint32_t pid) {
return (vid == ADK_VID && (pid == ADK_PID || pid == ADB_PID));
};
//UsbConfigXtracter implementation
virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
}; //class ADK : public USBDeviceConfig ...
/* get ADK protocol version */
/* returns 2 bytes in *adkproto */
inline uint32_t ADK::getProto(uint8_t* adkproto) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL));
}
/* send ADK string */
inline uint32_t ADK::sendStr(uint32_t index, const char* str) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*)str, NULL));
}
/* switch to accessory mode */
inline uint32_t ADK::switchAcc(void) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL));
}
#endif /* ADK_H_INCLUDED */
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__)
#error "Never include confdescparser.h directly; include Usb.h instead"
#else
#define __CONFDESCPARSER_H__
#include <stdint.h>
//#define TRACE_USBHOST(x) x
#define TRACE_USBHOST(x)
class UsbConfigXtracter {
public:
//virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;
//virtual void InterfaceXtract(uint32_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0;
virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) = 0;
};
#define CP_MASK_COMPARE_CLASS 1
#define CP_MASK_COMPARE_SUBCLASS 2
#define CP_MASK_COMPARE_PROTOCOL 4
#define CP_MASK_COMPARE_ALL 7
// Configuration Descriptor Parser Class Template
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
class ConfigDescParser : public USBReadParser {
UsbConfigXtracter *theXtractor;
MultiValueBuffer theBuffer;
MultiByteValueParser valParser;
ByteSkipper theSkipper;
uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/];
uint32_t stateParseDescr; // ParseDescriptor state
uint32_t dscrLen; // Descriptor length
uint32_t dscrType; // Descriptor type
bool isGoodInterface; // Apropriate interface flag
uint32_t confValue; // Configuration value
uint32_t protoValue; // Protocol value
uint32_t ifaceNumber; // Interface number
uint32_t ifaceAltSet; // Interface alternate settings
bool UseOr;
bool ParseDescriptor(uint8_t **pp, uint32_t *pcntdn);
void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
public:
void SetOR(void) {
UseOr = true;
}
ConfigDescParser(UsbConfigXtracter *xtractor);
virtual void Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset);
};
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :
theXtractor(xtractor),
stateParseDescr(0),
dscrLen(0),
dscrType(0),
UseOr(false) {
theBuffer.pValue = varBuffer;
valParser.Initialize(&theBuffer);
theSkipper.Initialize(&theBuffer);
};
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset) {
uint32_t cntdn = len;
uint8_t *p = (uint8_t*)pbuf;
while (cntdn)
if(!ParseDescriptor(&p, &cntdn))
return;
}
/* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and
compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint32_t *pcntdn) {
USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);
switch(stateParseDescr) {
case 0:
theBuffer.valueSize = 2;
valParser.Initialize(&theBuffer);
stateParseDescr = 1;
case 1:
if(!valParser.Parse(pp, pcntdn))
return false;
dscrLen = *((uint8_t*)theBuffer.pValue);
dscrType = *((uint8_t*)theBuffer.pValue + 1);
stateParseDescr = 2;
case 2:
// This is a sort of hack. Assuming that two bytes are all ready in the buffer
// the pointer is positioned two bytes ahead in order for the rest of descriptor
// to be read right after the size and the type fields.
// This should be used carefully. varBuffer should be used directly to handle data
// in the buffer.
theBuffer.pValue = varBuffer + 2;
stateParseDescr = 3;
case 3:
switch(dscrType) {
case USB_DESCRIPTOR_INTERFACE:
isGoodInterface = false;
case USB_DESCRIPTOR_CONFIGURATION:
theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2;
break;
case USB_DESCRIPTOR_ENDPOINT:
theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2;
break;
case HID_DESCRIPTOR_HID:
theBuffer.valueSize = dscrLen - 2;
break;
}
valParser.Initialize(&theBuffer);
stateParseDescr = 4;
case 4:
switch(dscrType) {
case USB_DESCRIPTOR_CONFIGURATION:
if(!valParser.Parse(pp, pcntdn))
return false;
confValue = ucd->bConfigurationValue;
break;
case USB_DESCRIPTOR_INTERFACE:
if(!valParser.Parse(pp, pcntdn))
return false;
if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)
break;
if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID)
break;
if(UseOr) {
if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol)))
break;
} else {
if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)
break;
}
isGoodInterface = true;
ifaceNumber = uid->bInterfaceNumber;
ifaceAltSet = uid->bAlternateSetting;
protoValue = uid->bInterfaceProtocol;
break;
case USB_DESCRIPTOR_ENDPOINT:
if(!valParser.Parse(pp, pcntdn))
return false;
if(isGoodInterface)
if(theXtractor)
theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
break;
//case HID_DESCRIPTOR_HID:
// if (!valParser.Parse(pp, pcntdn))
// return false;
// PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
// break;
default:
if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2))
return false;
}
theBuffer.pValue = varBuffer;
stateParseDescr = 0;
}
return true;
}
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {
Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
Notify(PSTR("bDescLength:\t\t"), 0x80);
PrintHex<uint8_t > (pDesc->bLength, 0x80);
Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
//Notify(PSTR("\r\nbDescrType:\t\t"));
//PrintHex<uint8_t>(pDesc->bDescrType);
//
//Notify(PSTR("\r\nwDescriptorLength:\t"));
//PrintHex<uint16_t>(pDesc->wDescriptorLength);
for (uint32_t i = 0; i < pDesc->bNumDescriptors; i++) {
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);
Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);
}
Notify(PSTR("\r\n"), 0x80);
}
#endif // __CONFDESCPARSER_H__
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment