; compile with

; nasm -o backlight.o -f elf32 backlight.s
; gcc -Wall -s -nostartfiles --nolibc --static backlight.o -o backlight

; install with

; sudo bash
; cp backlight /usr/local/sbin/
; chown root:root /usr/local/sbin/backlight
; chmod +s /usr/local/sbin/backlight

; then in openbox bind keys with

;    <keybind key="XF86MonBrightnessDown">
;      <action name="Execute">
;        <execute>/usr/local/sbin/backlight -</execute>
;      </action>
;    </keybind>
;    <keybind key="XF86MonBrightnessUp">
;      <action name="Execute">
;        <execute>/usr/local/sbin/backlight +</execute>
;      </action>
;    </keybind>

; note: This works for me on a Samsung N510 with nvidia driver 195.36.24. 
; If you have a different setup, don't blame me. The reason to hardcode
; the file is security, as the executable gets an SUID bit, we would not
; want it to write to another location.

section .text

EXIT	equ 1	; from asm/unistd32.h
READ	equ 3
WRITE	equ 4
OPEN	equ 5
CLOSE	equ 6
SEEK	equ 19

RDONLY	equ 0	; from bits/fcntl.h
WRONLY	equ 1
SEEKSET equ 0	; from fcntl.h

CURRENT	equ 43	; position of current brightness

global _start

_start:	pop ebx		; argc > 1
	cmp ebx, 1
	jle bye
	
	pop esi		; "./bl"
	pop esi		; "+" or "-"
	lodsb
	cmp al, '+'
	je  store

	cmp al, '-'
	je  store
	mov ebx, 1
	jmp bye

store:
	mov [flag], al
	mov eax, 3
	mov [len], eax
	
open:	mov ecx, RDONLY
	mov ebx, filename
	mov eax, 5
	int 80h

	cmp eax, 0
	jg  noerr
	mov ebx, 2
	jmp bye
noerr:
	mov [fh], eax

seek:	mov ecx, CURRENT
	mov ebx, eax
	mov eax, SEEK
	int 80h

read:	mov edx, 5
	mov ecx, buffer
	mov ebx, [fh]
	mov eax, READ
	int 80h
	push eax
	
rclose:	mov ebx, [fh]
	mov eax, CLOSE
	int 80h

	pop eax
	cmp eax, 4
	jg  bounds
	cmp eax, 3
	jl  bounds

	xor bl, bl
	mov [buffer - 1 + eax], bl

	mov bl, [flag]
	cmp bl, '-'
	je  lower

higher:	cmp eax, 4	; == "100", nothing to do
	je thx	
	mov bl, [buffer]
	cmp bl, '8'
	jl  hi2
	mov eax, 4
	mov [len], eax
	mov eax, 303030h ; "000\0"
	mov [buffer], eax
	mov bl, '0'
hi2:	inc bl
	mov [buffer], bl
	jmp wopen

lower:	cmp eax, 4
	jl  lo2
	mov eax, 3038h ; "90\0\0"
	mov [buffer], eax
	jmp wopen
lo2:	mov  bl, [buffer]
	cmp bl, '2'
	je  thx
	dec bl
	mov [buffer], bl
	jmp wopen

thx:	mov ebx, 0
bye:	mov eax, EXIT
	int 80h

wopen:	mov ecx, WRONLY
	mov ebx, filename
	mov eax, 5
	int 80h

write:	mov [fh], eax
	mov edx, 3 ; TODO: 4 if 100
	mov ecx, buffer	
	mov ebx, eax
	mov eax, WRITE
	int 80h

wclose:	mov ebx, [fh]
	mov eax, CLOSE
	int 80h

	jmp thx

bounds:	mov ebx, 3
	jmp bye

err:	mov ebx, eax
	jmp bye

section .data

filename dw '/proc/acpi/video/IGPU/LCD0/brightness', 0

section .bss
fh	 resd 1
len	 resd 1
flag	 resb 1
buffer	 resb 5
