// 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 cores import ( "fmt" "strings" "github.com/arduino/go-properties-orderedmap" ) // Board represents a board loaded from an installed platform type Board struct { BoardID string Properties *properties.Map `json:"-"` PlatformRelease *PlatformRelease `json:"-"` } // HasUsbID returns true if the board match the usb vid and pid parameters func (b *Board) HasUsbID(reqVid, reqPid string) bool { vids := b.Properties.SubTree("vid") pids := b.Properties.SubTree("pid") for id, vid := range vids.AsMap() { if pid, ok := pids.GetOk(id); ok { if strings.EqualFold(vid, reqVid) && strings.EqualFold(pid, reqPid) { return true } } } return false } // Name returns the board name as defined in boards.txt properties func (b *Board) Name() string { return b.Properties.Get("name") } // FQBN return the Fully-Qualified-Board-Name for the default configuration of this board func (b *Board) FQBN() string { platform := b.PlatformRelease.Platform return platform.Package.Name + ":" + platform.Architecture + ":" + b.BoardID } // IsHidden returns true if the board is marked as hidden in the platform func (b *Board) IsHidden() bool { return b.Properties.GetBoolean("hide") } func (b *Board) String() string { return b.FQBN() } // GetConfigOptions returns an OrderedMap of configuration options for this board. // The returned map will have key and value as option id and option name, respectively. func (b *Board) GetConfigOptions() *properties.Map { res := properties.NewMap() menu := b.Properties.SubTree("menu") for _, option := range menu.FirstLevelKeys() { res.Set(option, b.PlatformRelease.Menus.Get(option)) } return res } // GetConfigOptionValues returns an OrderedMap of possible values for a specific configuratio options // for this board. The returned map will have key and value as option value and option value name, // respectively. func (b *Board) GetConfigOptionValues(option string) *properties.Map { res := properties.NewMap() menu := b.Properties.SubTree("menu").SubTree(option) for _, value := range menu.FirstLevelKeys() { if label, ok := menu.GetOk(value); ok { res.Set(value, label) } } return res } // GetBuildProperties returns the build properties and the build // platform for the Board with the configuration passed as parameter. func (b *Board) GetBuildProperties(userConfigs *properties.Map) (*properties.Map, error) { // Clone user configs because they are destroyed during iteration userConfigs = userConfigs.Clone() // Start with board's base properties buildProperties := b.Properties.Clone() // Add all sub-configurations one by one (a config is: option=value) menu := b.Properties.SubTree("menu") for _, option := range menu.FirstLevelKeys() { optionMenu := menu.SubTree(option) userValue, haveUserValue := userConfigs.GetOk(option) if haveUserValue { userConfigs.Remove(option) if !optionMenu.ContainsKey(userValue) { return nil, fmt.Errorf("invalid value '%s' for option '%s'", userValue, option) } } else { // apply default userValue = optionMenu.FirstLevelKeys()[0] } optionsConf := optionMenu.SubTree(userValue) buildProperties.Merge(optionsConf) } // Check for residual invalid options... for _, invalidOption := range userConfigs.Keys() { if invalidOption == "" { return nil, fmt.Errorf("invalid empty option found") } return nil, fmt.Errorf("invalid option '%s'", invalidOption) } return buildProperties, nil } // GeneratePropertiesForConfiguration returns the board properties for a particular // configuration. The parameter is the latest part of the FQBN, for example if // the full FQBN is "arduino:avr:mega:cpu=atmega2560" the config part must be // "cpu=atmega2560". // FIXME: deprecated, use GetBuildProperties instead func (b *Board) GeneratePropertiesForConfiguration(config string) (*properties.Map, error) { fqbn, err := ParseFQBN(b.String() + ":" + config) if err != nil { return nil, fmt.Errorf("parsing fqbn: %s", err) } return b.GetBuildProperties(fqbn.Configs) }