summaryrefslogtreecommitdiff
path: root/cfa635/report.go
blob: 84541bcad595794fcfe2ed63c46769ead49da648 (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
// Copyright 2022 Benjamin Barenblat
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

package cfa635

import (
	"encoding/binary"
	"errors"
)

var (
	errUnknownReportType = errors.New("failed to read report: unknown type")
	errUnknownKey        = errors.New("failed to read key activity report: unknown key")
	errFBSCAB            = errors.New("failed to read fan speed report: FBSCAB module disconnected")
	errDOW               = errors.New("failed to read temperature report: DOW sensor error")
)

// KeyActivity is a report that a key has been pressed or released.
type KeyActivity struct {
	K       Key
	Pressed bool
}

// Key represents a button on the CFA635.
type Key int

const (
	_ Key = iota
	UpButton
	DownButton
	LeftButton
	RightButton
	EnterButton
	ExitButton
)

// FanSpeed is a report on the speed of a system fan.
type FanSpeed struct {
	N          int
	TachCycles int
	TimerTicks int
}

// Temperature is a report on the system temperature.
type Temperature struct {
	N       int // Sensor number.
	Celsius float64
}

// decodeReport converts a packet into either a *KeyActivity, a *FanSpeed, or a
// *Temperature, depending on the packet's type tag.
func decodeReport(p []byte) (any, error) {
	switch p[0] {
	case 0x80:
		return decodeKeyActivity(p[2])
	case 0x81:
		return decodeFanSpeed(p[2:6])
	case 0x82:
		return decodeTemperature(p[2:6])
	default:
		return nil, errUnknownReportType
	}
}

// decodeKeyActivity converts the data byte from a key activity report to a
// KeyActivity.
func decodeKeyActivity(b byte) (*KeyActivity, error) {
	if b == 0 || b > 12 {
		return nil, errUnknownKey
	}

	var a KeyActivity
	if b < 7 {
		a.Pressed = true
	} else {
		b -= 6
	}
	a.K = Key(b)
	return &a, nil
}

// decodeFanSpeed converts the data part of a fan speed report packet to a
// FanSpeed.
func decodeFanSpeed(b []byte) (*FanSpeed, error) {
	if b[1] == 0 && b[2] == 0 && b[3] == 0 {
		return nil, errFBSCAB
	}
	return &FanSpeed{int(b[0]), int(b[1]), int(binary.BigEndian.Uint16(b[2:4]))}, nil
}

// decodeTemperature converts the data part of a temperature report packet to a
// Temperature.
func decodeTemperature(b []byte) (*Temperature, error) {
	if b[3] == 0 {
		return nil, errDOW
	}
	return &Temperature{int(b[0]), float64(binary.BigEndian.Uint16(b[1:3])) / 16}, nil
}