Skip to content
This repository has been archived by the owner on Apr 19, 2024. It is now read-only.

Commit

Permalink
plugin: use RWMutex when applicable and only lock to OS Thread when n…
Browse files Browse the repository at this point in the history
…eeded; added doc
  • Loading branch information
zllovesuki committed Dec 7, 2020
1 parent e1f5409 commit d84c778
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 32 deletions.
4 changes: 4 additions & 0 deletions controller/controller_loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ func (c *Controller) handleWorkQueue(haltCtx context.Context) {
c.errorCh <- errors.Wrap(err, "[controller] error applying configurations")
return
}
c.notifyQueueCh <- util.Notification{
Title: "Settings Loaded from Registry",
Message: "Enjoy your bloat-free G14",
}

case ev := <-c.workQueueCh[fnHwCtrl].clean:
keyCode := ev.Data.(uint32)
Expand Down
62 changes: 41 additions & 21 deletions cxx/plugin/keyboard/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,22 @@ const (
HIGH = 0x03
)

// Control allows you to set the hid related functionalities directly
// Control allows you to set the hid related functionalities directly.
// The controller is safe for multiple goroutines.
type Control struct {
Config

mu sync.Mutex
mu sync.RWMutex
deviceCtrl *device.Control
currentBrightness Level

queue chan plugin.Notification
errChan chan error
}

// Config defines the behavior of Keyboard Control. If DryRun is set to true,
// no actual IOs will be performed. Remap defines the key remapping behavior or
// Fn+ArrowLeft/ArrowRight (see system/keyboard) to standard key scancode.
type Config struct {
DryRun bool
Remap map[uint32]uint16
Expand Down Expand Up @@ -142,7 +146,9 @@ func NewControl(config Config) (*Control, error) {
}, nil
}

// Initialize will send initialization buffer to the keyboard control device
// Initialize will send initialization buffer to the keyboard control device.
// Note: This should be called prior to calling any control methods, and after
// ACPI resume.
func (c *Control) Initialize() error {
c.mu.Lock()
defer c.mu.Unlock()
Expand All @@ -167,9 +173,6 @@ func (c *Control) loop(haltCtx context.Context, cb chan<- plugin.Callback) {
}
}()

runtime.LockOSThread()
defer runtime.UnlockOSThread()

for {
select {
case t := <-c.queue:
Expand All @@ -181,35 +184,36 @@ func (c *Control) loop(haltCtx context.Context, cb chan<- plugin.Callback) {
}
switch keycode {
case keyboard.KeyTpadToggle:
c.errChan <- c.toggleTouchPad()
c.errChan <- c.ToggleTouchPad()
case keyboard.KeyFnDown:
c.errChan <- c.brightnessDown()
c.errChan <- c.BrightnessDown()
cb <- plugin.Callback{
Event: plugin.CbPersistConfig,
}
case keyboard.KeyFnUp:
c.errChan <- c.brightnessUp()
c.errChan <- c.BrightnessUp()
cb <- plugin.Callback{
Event: plugin.CbPersistConfig,
}
case keyboard.KeyFnLeft, keyboard.KeyFnRight:
if remap, ok := c.Config.Remap[keycode]; ok {
c.emulateKeyPress(remap)
c.EmulateKeyPress(remap)
}
}
case plugin.EvtACPIResume, plugin.EvtSentinelInitKeyboard:
log.Println("kbCtrl: reinitialize kbCtrl")
c.errChan <- c.Initialize()
case plugin.EvtACPISuspend, plugin.EvtSentinelKeyboardBrightnessOff:
log.Println("kbCtrl: turning off keyboard backlight")
c.errChan <- c.setBrightness(OFF)
c.errChan <- c.SetBrightness(OFF)
}
case <-haltCtx.Done():
return
}
}
}

// Run satifies system/plugin.Plugin
func (c *Control) Run(haltCtx context.Context, cb chan<- plugin.Callback) <-chan error {
log.Println("kbCtrl: Starting queue loop")

Expand All @@ -218,14 +222,19 @@ func (c *Control) Run(haltCtx context.Context, cb chan<- plugin.Callback) <-chan
return c.errChan
}

// Notify satifies system/plugin.Plugin
func (c *Control) Notify(t plugin.Notification) {
c.queue <- t
}

func (c *Control) setBrightness(v Level) error {
// SetBrightness change the keyboard backlight directly
func (c *Control) SetBrightness(v Level) error {
c.mu.Lock()
defer c.mu.Unlock()

runtime.LockOSThread()
defer runtime.UnlockOSThread()

inputBuf := make([]byte, brightnessControlBufferLength)
copy(inputBuf, brightnessControlBuffer)
inputBuf[brightnessControlByteIndex] = byte(v)
Expand All @@ -240,7 +249,8 @@ func (c *Control) setBrightness(v Level) error {
return nil
}

func (c *Control) brightnessUp() error {
// BrightnessUp increases the keyboard backlight by one level
func (c *Control) BrightnessUp() error {
var targetLevel Level
switch c.currentBrightness {
case OFF:
Expand All @@ -252,10 +262,11 @@ func (c *Control) brightnessUp() error {
default:
return nil
}
return c.setBrightness(targetLevel)
return c.SetBrightness(targetLevel)
}

func (c *Control) brightnessDown() error {
// BrightnessDown decreases the keyboard backlight by one level
func (c *Control) BrightnessDown() error {
var targetLevel Level
switch c.currentBrightness {
case HIGH:
Expand All @@ -267,13 +278,17 @@ func (c *Control) brightnessDown() error {
default:
return nil
}
return c.setBrightness(targetLevel)
return c.SetBrightness(targetLevel)
}

func (c *Control) toggleTouchPad() error {
// ToggleTouchPad will toggle enabling/disabling the touchpad
func (c *Control) ToggleTouchPad() error {
c.mu.Lock()
defer c.mu.Unlock()

runtime.LockOSThread()
defer runtime.UnlockOSThread()

inputBuf := make([]byte, touchPadToggleControlBufferLength)
copy(inputBuf, touchPadToggleControlBuffer)

Expand All @@ -287,7 +302,12 @@ func (c *Control) toggleTouchPad() error {
return nil
}

func (c *Control) emulateKeyPress(keyCode uint16) error {
// EmulateKeyPress will emulate a keypress via SendInput() scancode.
// Note: some applications using DirectInput may not register this.
func (c *Control) EmulateKeyPress(keyCode uint16) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

if C.SendKeyPress(C.ushort(keyCode)) != 0 {
return fmt.Errorf("kbCtrl: cannot emulate key press")
}
Expand All @@ -304,8 +324,8 @@ func (c *Control) Name() string {

// Value satisfies persist.Registry
func (c *Control) Value() []byte {
c.mu.Lock()
defer c.mu.Unlock()
c.mu.RLock()
defer c.mu.RUnlock()

buf := make([]byte, 2)
binary.LittleEndian.PutUint16(buf, uint16(c.currentBrightness))
Expand All @@ -328,7 +348,7 @@ func (c *Control) Load(v []byte) error {
// Apply satisfies persist.Registry
func (c *Control) Apply() error {
// mutex already in setBrightness
return c.setBrightness(c.currentBrightness)
return c.SetBrightness(c.currentBrightness)
}

// Close satisfied persist.Registry
Expand Down
28 changes: 23 additions & 5 deletions cxx/plugin/volume/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type Control struct {

var _ plugin.Plugin = &Control{}

// NewVolumeControl returns a controller for toggling default input device's muted status.
// The controller is safe for multiple goroutines.
func NewVolumeControl(dryRun bool) (*Control, error) {
return &Control{
dryRun: dryRun,
Expand All @@ -34,6 +36,7 @@ func NewVolumeControl(dryRun bool) (*Control, error) {
}, nil
}

// Initialize satisfies system/plugin.Plugin
func (c *Control) Initialize() error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
Expand All @@ -49,16 +52,13 @@ func (c *Control) loop(haltCtx context.Context, cb chan<- plugin.Callback) {
}
}()

runtime.LockOSThread()
defer runtime.UnlockOSThread()

for {
select {
case t := <-c.queue:
if keycode, ok := t.Value.(uint32); ok {
switch keycode {
case keyboard.KeyMuteMic:
c.errChan <- c.doToggleMute()
c.errChan <- c.ToggleMuted()
}
}
case <-haltCtx.Done():
Expand All @@ -67,6 +67,7 @@ func (c *Control) loop(haltCtx context.Context, cb chan<- plugin.Callback) {
}
}

// Run satisfies system/plugin.Plugin
func (c *Control) Run(haltCtx context.Context, cb chan<- plugin.Callback) <-chan error {
log.Println("volCtrl: Starting queue loop")

Expand All @@ -75,6 +76,7 @@ func (c *Control) Run(haltCtx context.Context, cb chan<- plugin.Callback) <-chan
return c.errChan
}

// Notify satisfies system/plugin.Plugin
func (c *Control) Notify(t plugin.Notification) {
if c.dryRun {
return
Expand All @@ -88,6 +90,9 @@ func (c *Control) Notify(t plugin.Notification) {
}

func (c *Control) doCheckMute() error {
c.mu.Lock()
defer c.mu.Unlock()

ret := C.SetMicrophoneMute(1, 0)
switch ret {
case -1:
Expand All @@ -99,10 +104,23 @@ func (c *Control) doCheckMute() error {
}
}

func (c *Control) doToggleMute() error {
// CheckMuted returns the default recording device's muted status
func (c *Control) CheckMuted() (bool, error) {
if err := c.doCheckMute(); err != nil {
return false, err
}
return c.isMuted, nil
}

// ToggleMuted toggles the default recording device's muted status.
// Note: This should be called after CheckMuted() has been called once.
func (c *Control) ToggleMuted() error {
c.mu.Lock()
defer c.mu.Unlock()

runtime.LockOSThread()
defer runtime.UnlockOSThread()

var to int
if c.isMuted {
to = 1
Expand Down
15 changes: 9 additions & 6 deletions system/thermal/thermal.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ type Profile struct {
type Control struct {
Config

mu sync.Mutex
mu sync.RWMutex
wmi atkacpi.WMI
currentProfileIndex int

Expand Down Expand Up @@ -123,6 +123,9 @@ func (c *Control) setProfile(index int) (string, error) {
c.mu.Lock()
defer c.mu.Unlock()

runtime.LockOSThread()
defer runtime.UnlockOSThread()

nextProfile := c.Config.Profiles[index]

// note: always set thermal throttle plan first, then override with user fan curve
Expand Down Expand Up @@ -220,6 +223,7 @@ func (c *Control) setFanCurve(profile Profile) error {
return nil
}

// Initialize satisfies system/plugin.Plugin
func (c *Control) Initialize() error {
return nil
}
Expand All @@ -232,9 +236,6 @@ func (c *Control) loop(haltCtx context.Context, cb chan<- plugin.Callback) {
}
}()

runtime.LockOSThread()
defer runtime.UnlockOSThread()

for {
select {
case t := <-c.queue:
Expand Down Expand Up @@ -292,6 +293,7 @@ func (c *Control) loop(haltCtx context.Context, cb chan<- plugin.Callback) {
}
}

// Run satisfies system/plugin.Plugin
func (c *Control) Run(haltCtx context.Context, cb chan<- plugin.Callback) <-chan error {
log.Println("thermal: Starting queue loop")

Expand All @@ -300,6 +302,7 @@ func (c *Control) Run(haltCtx context.Context, cb chan<- plugin.Callback) <-chan
return c.errorCh
}

// Notify satisfies system/plugin.Plugin
func (c *Control) Notify(t plugin.Notification) {
c.queue <- t
}
Expand All @@ -313,8 +316,8 @@ func (c *Control) Name() string {

// Value satisfies persist.Registry
func (c *Control) Value() []byte {
c.mu.Lock()
defer c.mu.Unlock()
c.mu.RLock()
defer c.mu.RUnlock()

var buf bytes.Buffer
name := c.CurrentProfile().Name
Expand Down

0 comments on commit d84c778

Please sign in to comment.