Das Lesen der Pins ist schon richtig so (siehe auch
http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_port_pass).
Was nicht korrekt ist, ist die Funktion button_read() selber. Zum einen
wird die Variable return_value nicht initialisiert. Es ist also durchaus
möglich, daß die Funktion einen undefinierten Wert zurückliefert.
Viel schlimmer ist aber der logische Fehler. Anscheinend soll das eine
Statemachine sein. Die funktioniert aber nur dann so wie erwartet, wenn
der Taster entprellt ist und wenn die Funktion häufig genug aufgerufen
wird. Sonst kann es passieren, daß die Statemachine in einem Zustand
hängen bleibt.
Nehmen wir z.B. an, beim letzten Aufruf wäre die Statemachine in den
Zustand last_state == 1 (Tastendruck erkannt) übergegangen. Nun ist der
Taster zwischenzeitlich aber schon wieder losgelassen worden (bzw. hat
geprellt). Beim nächsten Aufruf der Funktion ist das Portbit also 1.
Dann wird keiner der if/else Zweige genommen. Denn von Zustand 1 ist
nur der eine Weg nach Zustand 2 vorgesehen, wenn der Taster gedrückt
bleibt (das Portbit beim Test gerade 0 ist). Und genau an dieser Stelle
wird dann auch ein undefinierter Wert von return_value zurückgegeben.
Um das sauber zu machen, muß die Statemachine in jedem Zustand jeden
möglichen Input bewerten. Man muß also auch die "unmöglichen" Übergänge
berücksichtigen. Weil die eben doch möglich sind.