164 lines
4.2 KiB
Go
164 lines
4.2 KiB
Go
package hwinfo
|
|
|
|
/*
|
|
#include <windows.h>
|
|
#include "hwisenssm2.h"
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
"unsafe"
|
|
|
|
"github.com/shayne/hwinfo-streamdeck/internal/hwinfo/shmem"
|
|
"github.com/shayne/hwinfo-streamdeck/internal/hwinfo/util"
|
|
)
|
|
|
|
// SharedMemory provides access to the HWiNFO shared memory
|
|
type SharedMemory struct {
|
|
data []byte
|
|
shmem C.PHWiNFO_SENSORS_SHARED_MEM2
|
|
}
|
|
|
|
// ReadSharedMem reads data from HWiNFO shared memory
|
|
// creating a copy of the data
|
|
func ReadSharedMem() (*SharedMemory, error) {
|
|
data, err := shmem.ReadBytes()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &SharedMemory{
|
|
data: append([]byte(nil), data...),
|
|
shmem: C.PHWiNFO_SENSORS_SHARED_MEM2(unsafe.Pointer(&data[0])),
|
|
}, nil
|
|
}
|
|
|
|
// Result for streamed shared memory updates
|
|
type Result struct {
|
|
Shmem *SharedMemory
|
|
Err error
|
|
}
|
|
|
|
func readAndSend(ch chan<- Result) {
|
|
shmem, err := ReadSharedMem()
|
|
ch <- Result{Shmem: shmem, Err: err}
|
|
}
|
|
|
|
// StreamSharedMem delivers shared memory hardware sensors updates
|
|
// over a channel
|
|
func StreamSharedMem() <-chan Result {
|
|
ch := make(chan Result)
|
|
go func() {
|
|
readAndSend(ch)
|
|
// TODO: don't use time.Tick, cancellable?
|
|
for range time.Tick(1 * time.Second) {
|
|
readAndSend(ch)
|
|
}
|
|
}()
|
|
return ch
|
|
}
|
|
|
|
// Signature "HWiS" if active, 'DEAD' when inactive
|
|
func (s *SharedMemory) Signature() string {
|
|
return util.DecodeCharPtr(unsafe.Pointer(&s.shmem.dwSignature), C.sizeof_DWORD)
|
|
}
|
|
|
|
// Version v1 is latest
|
|
func (s *SharedMemory) Version() int {
|
|
return int(s.shmem.dwVersion)
|
|
}
|
|
|
|
// Revision revision of version
|
|
func (s *SharedMemory) Revision() int {
|
|
return int(s.shmem.dwRevision)
|
|
}
|
|
|
|
// PollTime last polling time
|
|
func (s *SharedMemory) PollTime() uint64 {
|
|
addr := unsafe.Pointer(uintptr(unsafe.Pointer(&s.shmem.dwRevision)) + C.sizeof_DWORD)
|
|
return uint64(*(*C.__time64_t)(addr))
|
|
}
|
|
|
|
// OffsetOfSensorSection offset of the Sensor section from beginning of HWiNFO_SENSORS_SHARED_MEM2
|
|
func (s *SharedMemory) OffsetOfSensorSection() int {
|
|
return int(s.shmem.dwOffsetOfSensorSection)
|
|
}
|
|
|
|
// SizeOfSensorElement size of each sensor element = sizeof( HWiNFO_SENSORS_SENSOR_ELEMENT )
|
|
func (s *SharedMemory) SizeOfSensorElement() int {
|
|
return int(s.shmem.dwSizeOfSensorElement)
|
|
}
|
|
|
|
// NumSensorElements number of sensor elements
|
|
func (s *SharedMemory) NumSensorElements() int {
|
|
return int(s.shmem.dwNumSensorElements)
|
|
}
|
|
|
|
// OffsetOfReadingSection offset of the Reading section from beginning of HWiNFO_SENSORS_SHARED_MEM2
|
|
func (s *SharedMemory) OffsetOfReadingSection() int {
|
|
return int(s.shmem.dwOffsetOfReadingSection)
|
|
}
|
|
|
|
// SizeOfReadingElement size of each Reading element = sizeof( HWiNFO_SENSORS_READING_ELEMENT )
|
|
func (s *SharedMemory) SizeOfReadingElement() int {
|
|
return int(s.shmem.dwSizeOfReadingElement)
|
|
}
|
|
|
|
// NumReadingElements number of Reading elements
|
|
func (s *SharedMemory) NumReadingElements() int {
|
|
return int(s.shmem.dwNumReadingElements)
|
|
}
|
|
|
|
func (s *SharedMemory) dataForSensor(pos int) ([]byte, error) {
|
|
if pos >= s.NumSensorElements() {
|
|
return nil, fmt.Errorf("dataForSensor pos out of range, %d for size %d", pos, s.NumSensorElements())
|
|
}
|
|
start := s.OffsetOfSensorSection() + (pos * s.SizeOfSensorElement())
|
|
end := start + s.SizeOfSensorElement()
|
|
return s.data[start:end], nil
|
|
}
|
|
|
|
// IterSensors iterate over each sensor
|
|
func (s *SharedMemory) IterSensors() <-chan Sensor {
|
|
ch := make(chan Sensor)
|
|
go func() {
|
|
for i := 0; i < s.NumSensorElements(); i++ {
|
|
data, err := s.dataForSensor(i)
|
|
if err != nil {
|
|
log.Fatalf("TODO: failed to read dataForSensor: %v", err)
|
|
}
|
|
ch <- NewSensor(data)
|
|
}
|
|
close(ch)
|
|
}()
|
|
return ch
|
|
}
|
|
|
|
func (s *SharedMemory) dataForReading(pos int) ([]byte, error) {
|
|
if pos >= s.NumReadingElements() {
|
|
return nil, fmt.Errorf("dataForReading pos out of range, %d for size %d", pos, s.NumSensorElements())
|
|
}
|
|
start := s.OffsetOfReadingSection() + (pos * s.SizeOfReadingElement())
|
|
end := start + s.SizeOfReadingElement()
|
|
return s.data[start:end], nil
|
|
}
|
|
|
|
// IterReadings iterate over each sensor
|
|
func (s *SharedMemory) IterReadings() <-chan Reading {
|
|
ch := make(chan Reading)
|
|
go func() {
|
|
for i := 0; i < s.NumReadingElements(); i++ {
|
|
data, err := s.dataForReading(i)
|
|
if err != nil {
|
|
log.Fatalf("TODO: failed to read dataForReading: %v", err)
|
|
}
|
|
ch <- NewReading(data)
|
|
}
|
|
close(ch)
|
|
}()
|
|
return ch
|
|
}
|