summaryrefslogtreecommitdiff
path: root/util/pinmap/readers/csv/csv.go
blob: 8e1691268ddbf395e8fac81f4ea4760dac310aa0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// 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 csv

import (
	"bufio"
	"encoding/csv"
	"fmt"
	"os"

	"pinmap/pm"
)

// CSVReader reads the EC pin references from a comma separated
// values file.
type CSVReader struct {
}

// Name returns the name of this reader.
func (r *CSVReader) Name() string {
	return "csv"
}

// Read reads the CSV file (provided as the argument) and extracts
// the pin reference data. The first line is expected to be column
// titles that are used to identify the columns.
func (r *CSVReader) Read(chipName, arg string) (*pm.Pins, error) {
	f, err := os.Open(arg)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	rdr := csv.NewReader(bufio.NewReader(f))
	data, err := rdr.ReadAll()
	if err != nil {
		return nil, err
	}
	if len(data) < 2 {
		return nil, fmt.Errorf("no data in file")
	}
	// Put the CSV headers into a map.
	cmap := make(map[string]int)
	for c, s := range data[0] {
		cmap[s] = c
	}
	// Find the matching columns that are needed.
	signal, ok := cmap["Signal Name"]
	if !ok {
		return nil, fmt.Errorf("missing 'Signal Name' column")
	}
	// Find chip column
	chip, ok := cmap[chipName]
	if !ok {
		return nil, fmt.Errorf("missing '%s' chip column", chipName)
	}
	ptype, ok := cmap["Type"]
	if !ok {
		return nil, fmt.Errorf("missing 'Type' column")
	}
	enum, ok := cmap["Enum"]
	if !ok {
		return nil, fmt.Errorf("missing 'Enum' column")
	}
	var pins pm.Pins
	// Read the rest of the rows.
	for i, row := range data[1:] {
		p := new(pm.Pin)
		switch row[ptype] {
		default:
			fmt.Printf("%s:%d: Unknown signal type (%s) - ignored", arg, i+1, row[ptype])
			continue
		case "OTHER":
			// Skipped
			continue
		case "ADC":
			p.PinType = pm.ADC
			pins.Adc = append(pins.Adc, p)
		case "PWM":
			p.PinType = pm.PWM
			pins.Pwm = append(pins.Pwm, p)
		case "PWM_INVERT":
			p.PinType = pm.PWM_INVERT
			pins.Pwm = append(pins.Pwm, p)
		case "I2C_DATA":
			// Only the clock pin is used for the config
			continue
		case "I2C_CLOCK":
			p.PinType = pm.I2C
			pins.I2c = append(pins.I2c, p)
		case "INPUT":
			p.PinType = pm.Input
			pins.Gpio = append(pins.Gpio, p)
		case "INPUT_L":
			p.PinType = pm.InputL
			pins.Gpio = append(pins.Gpio, p)
		case "INPUT_PU":
			p.PinType = pm.InputPU
			pins.Gpio = append(pins.Gpio, p)
		case "INPUT_PU_L":
			p.PinType = pm.InputPUL
			pins.Gpio = append(pins.Gpio, p)
		case "INPUT_PD":
			p.PinType = pm.InputPD
			pins.Gpio = append(pins.Gpio, p)
		case "OUTPUT":
			p.PinType = pm.Output
			pins.Gpio = append(pins.Gpio, p)
		case "OUTPUT_L":
			p.PinType = pm.OutputL
			pins.Gpio = append(pins.Gpio, p)
		case "OUTPUT_ODL":
			p.PinType = pm.OutputODL
			pins.Gpio = append(pins.Gpio, p)
		case "OUTPUT_ODR":
			p.PinType = pm.OutputOD
			pins.Gpio = append(pins.Gpio, p)
		}
		p.Signal = row[signal]
		p.Pin = row[chip]
		p.Enum = row[enum]
	}

	return &pins, nil
}