Firmware Provisioning: add servo/lib

This module allows users to get correct servo-related variables for
flashing, specifically, dut-controls to be run before and after flashing
and the programmer argument.

BUG=None
TEST=unit

Change-Id: I105d22f03a324c3a64105464228b412f978df255
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/3321296
Tested-by: Sergey Frolov <sfrolov@google.com>
Auto-Submit: Sergey Frolov <sfrolov@google.com>
Reviewed-by: Otabek Kasimov <otabek@google.com>
Reviewed-by: Jaques Clapauch <jaquesc@google.com>
Commit-Queue: Sergey Frolov <sfrolov@google.com>
diff --git a/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/firmwareservice/servo/lib/servo_config.go b/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/firmwareservice/servo/lib/servo_config.go
new file mode 100644
index 0000000..45003c5
--- /dev/null
+++ b/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/firmwareservice/servo/lib/servo_config.go
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// package servo_lib provides servo-related variables, such as dut-controls
+// to be run before and after flashing, and a programmer argument.
+package servo_lib
+
+import "fmt"
+
+type ServoConfig struct {
+	dut_on     [][]string
+	dut_off    [][]string
+	programmer string
+}
+
+type UnsupportedServoError struct {
+	servoType ServoType
+	board     string
+}
+
+func (m *UnsupportedServoError) Error() string {
+	return fmt.Sprintf("board %v does not support servo %v", m.board, m.servoType.string)
+}
+
+func GetServoConfig(board, servoSerial string, servoType ServoType) (*ServoConfig, error) {
+	dut_on := [][]string{{"cpu_fw_spi:on"}}
+	dut_off := [][]string{{"cpu_fw_spi:off"}}
+	programmer := ""
+	if servoType.IsV2() {
+		programmer = fmt.Sprintf("ft2232_spi:type=google-servo-v2,serial=%v", servoSerial)
+	} else if servoType.IsMicro() || servoType.IsC2D2() {
+		programmer = fmt.Sprintf("raiden_debug_spi:serial=%v", servoSerial)
+	} else if servoType.IsCCD() {
+		dut_on = nil
+		dut_off = nil
+		programmer = fmt.Sprintf("raiden_debug_spi:target=AP,serial=%v", servoSerial)
+	} else {
+		return nil, &UnsupportedServoError{servoType, board}
+	}
+	return &ServoConfig{dut_on, dut_off, programmer}, nil
+}
diff --git a/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/firmwareservice/servo/lib/servo_type.go b/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/firmwareservice/servo/lib/servo_type.go
new file mode 100644
index 0000000..70f1871
--- /dev/null
+++ b/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/firmwareservice/servo/lib/servo_type.go
@@ -0,0 +1,40 @@
+// Copyright 2021 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package servo_lib
+
+import "strings"
+
+type ServoType struct {
+	string
+}
+
+func NewServoType(servo_type string) ServoType {
+	return ServoType{servo_type}
+}
+
+func (s *ServoType) IsV2() bool {
+	return strings.Contains(s.string, "servo_v2")
+}
+func (s *ServoType) IsV4() bool {
+	return strings.Contains(s.string, "servo_v4")
+}
+func (s *ServoType) IsC2D2() bool {
+	return strings.Contains(s.string, "c2d2")
+}
+func (s *ServoType) IsCCD() bool {
+	return strings.Contains(s.string, "ccd")
+}
+func (s *ServoType) IsMicro() bool {
+	return strings.Contains(s.string, "servo_micro")
+}
+
+func (s *ServoType) GetSerialNumberOption() string {
+	if s.IsV4() && s.IsCCD() {
+		return "ccd_serialname"
+	}
+	if s.IsV4() && s.IsMicro() {
+		return "servo_micro_serialname"
+	}
+	return "serialname"
+}
diff --git a/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/firmwareservice/servo/lib/servo_type_test.go b/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/firmwareservice/servo/lib/servo_type_test.go
new file mode 100644
index 0000000..c53e29d
--- /dev/null
+++ b/src/chromiumos/test/provision/cmd/provisionserver/bootstrap/services/firmwareservice/servo/lib/servo_type_test.go
@@ -0,0 +1,100 @@
+// Copyright 2021 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package servo_lib_test
+
+import (
+	servo_lib "chromiumos/test/provision/cmd/provisionserver/bootstrap/services/firmwareservice/servo/lib"
+	"testing"
+)
+
+func TestServoType(t *testing.T) {
+	SERVO_C2D2 := "c2d2"
+	SERVO_CCD_CR50 := "ccd_cr50"
+	SERVO_CCD_TI50 := "ccd_ti50"
+	SERVO_CCD_GSC := "ccd_gsc"
+	SERVO_MICRO := "servo_micro"
+	SERVO_V2 := "servo_v2"
+	SERVO_V4_C2D2 := "servo_v4_with_c2d2"
+	SERVO_V4_CCD := "servo_v4_with_ccd"
+	SERVO_V4_CCD_CR50 := "servo_v4_with_ccd_cr50"
+	SERVO_V4_CCD_TI50 := "servo_v4_with_ccd_ti50"
+	SERVO_V4_CCD_GSC := "servo_v4_with_ccd_gsc"
+	SERVO_V4_MICRO := "servo_v4_with_servo_micro"
+	SERVO_V4P1_C2D2 := "servo_v4p1_with_c2d2"
+	SERVO_V4P1_CCD := "servo_v4p1_with_ccd"
+	SERVO_V4P1_CCD_CR50 := "servo_v4p1_with_ccd_cr50"
+	SERVO_V4P1_CCD_TI50 := "servo_v4p1_with_ccd_ti50"
+	SERVO_V4P1_CCD_GSC := "servo_v4p1_with_ccd_gsc"
+	SERVO_V4P1_MICRO := "servo_v4p1_with_servo_micro"
+
+	VALID_SERVOS := []string{
+		SERVO_C2D2,
+		SERVO_CCD_CR50,
+		SERVO_CCD_TI50,
+		SERVO_CCD_GSC,
+		SERVO_MICRO,
+		SERVO_V2,
+		SERVO_V4_C2D2,
+		SERVO_V4_CCD,
+		SERVO_V4_CCD_CR50,
+		SERVO_V4_CCD_TI50,
+		SERVO_V4_CCD_GSC,
+		SERVO_V4_MICRO,
+		SERVO_V4P1_C2D2,
+		SERVO_V4P1_CCD,
+		SERVO_V4P1_CCD_CR50,
+		SERVO_V4P1_CCD_TI50,
+		SERVO_V4P1_CCD_GSC,
+		SERVO_V4P1_MICRO,
+	}
+	CCD_SERVOS := []string{
+		SERVO_CCD_CR50,
+		SERVO_CCD_TI50,
+		SERVO_CCD_GSC,
+		SERVO_V4_CCD,
+		SERVO_V4_CCD_CR50,
+		SERVO_V4_CCD_TI50,
+		SERVO_V4_CCD_GSC,
+		SERVO_V4P1_CCD,
+		SERVO_V4P1_CCD_CR50,
+		SERVO_V4P1_CCD_TI50,
+		SERVO_V4P1_CCD_GSC,
+	}
+	MICRO_SERVOS := []string{SERVO_MICRO, SERVO_V4_MICRO, SERVO_V4P1_MICRO}
+	V2_SERVOS := []string{SERVO_V2}
+	V4_SERVOS := []string{SERVO_V4_C2D2, SERVO_V4_CCD, SERVO_V4_CCD_CR50,
+		SERVO_V4_CCD_TI50, SERVO_V4_CCD_GSC, SERVO_V4_MICRO,
+		SERVO_V4P1_C2D2, SERVO_V4P1_CCD, SERVO_V4P1_CCD_CR50, SERVO_V4P1_CCD_TI50,
+		SERVO_V4P1_CCD_GSC, SERVO_V4P1_MICRO}
+	C2D2_SERVOS := []string{SERVO_C2D2, SERVO_V4_C2D2, SERVO_V4P1_C2D2}
+
+	listContains := func(list []string, str string) bool {
+		for i := 0; i < len(list); i++ {
+			if list[i] == str {
+				return true
+			}
+		}
+		return false
+	}
+
+	for i := 0; i < len(VALID_SERVOS); i++ {
+		servoStr := VALID_SERVOS[i]
+		servo := servo_lib.NewServoType(servoStr)
+		if servo.IsV2() != listContains(V2_SERVOS, servoStr) {
+			t.Errorf("servo %v: expected IsV2() to return %v", servoStr, !servo.IsV2())
+		}
+		if servo.IsV4() != listContains(V4_SERVOS, servoStr) {
+			t.Errorf("servo %v: expected IsV4() to return %v", servoStr, !servo.IsV4())
+		}
+		if servo.IsCCD() != listContains(CCD_SERVOS, servoStr) {
+			t.Errorf("servo %v: expected IsCCD() to return %v", servoStr, !servo.IsCCD())
+		}
+		if servo.IsC2D2() != listContains(C2D2_SERVOS, servoStr) {
+			t.Errorf("servo %v: expected IsC2D2() to return %v", servoStr, !servo.IsC2D2())
+		}
+		if servo.IsMicro() != listContains(MICRO_SERVOS, servoStr) {
+			t.Errorf("servo %v: expected IsMicro() to return %v", servoStr, !servo.IsMicro())
+		}
+	}
+}