MacBookPro
aus openSUSE, der freien Wissensdatenbank
Inhaltsverzeichnis |
MacBookPro5,5
Hier will ich beschreiben, wie man OpenSUSE 11.1 auf dem aktuellen Macbook Pro zum Laufen bekommt.
Hardware
Diese Anleitung ist vom 24.09.2009 und bezieht sich auf das aktuelle MacBookPro Modell 13,3 Zoll. Es handelt sich um die Version 5,5. Unibody Alu Gehäuse, Touchpad ohne sichtbare Maustaste, Kein extra Line-IN, SD-Kartenslot. Es ist eine 128GB SSD von Apple eingebaut, 4GB Ram und der Prozessor hat 2,54GHz.
Ich weiß nicht in wie weit diese Anleitung sich auf andere Modelle übertragen lässt, ich habe es nur auf dem Gerät getestet.
Installation
Installiert wurde von DVD die x86_64 (64bit) Version. Die SSD habe ich komplett platt gemacht und die Partitionstabelle auf msdos umgestellt. Dadurch braucht man kein refit. Der Nachteil ist, dass das Notebook beim starten etwa 10Sekunden mit einem grauen Bildschirm hängt. Warum weiß ich nicht, scheint aber laut anderen Berichten normal zu sein.
Ab hier geht die Anleitung davon aus, dass die Installation abgeschlossen ist. Ich habe KDE 3 installiert, ansonsten ist alles Standard geblieben Jetzt wollen wir einfach mal die einzelnen verbauten Komponenten durchgehen und alles an den Start bringen :)
Hinweis
Ich bin mir nicht mehr sicher, aber bei manchen Modulen kam es zu Fehlern beim compilieren. Ich habe die entsprechenden Zeilen schlicht auskommentiert, danach kompilieren die Module und funktionieren auch noch.
Komponenten
Out of the Box
Ohne irgendetwas einzustellen funktioniert schon einmal folgendes, was sehr erfreulich ist:
- Bluetooth
- Die iSight Kamera (getestet mit Skype)
- Suspend to Ram und Suspend to Disk gehen einwandfrei
- Ethernet
- Tastatur und Touchpad (Touchpad nur rudimentär, siehe weiter unten)
- SD-Kartenslot
- Externer Monitor per DVI Adapter nach NVIDIA Installation. VGA siehe unter Probleme.
Grafiktreiber
Einfach die properitären Treiber von NVIDIA installieren, ich habe sie direkt von der Homepage genommen:
http://www.nvidia.de/object/linux_display_amd64_185.18.36_de.html
Meine xorg.conf ist weiter unten.
WLAN
Um WLAN zum laufen zu bekommen muss man folgende Pakete aus dem Packman repository installieren:
- broadcom-wl
- broadcom-wl-kmp-default
Danach geht auch das einwandfrei. Bis jetzt habe ich noch einige Probleme mit WPA-Enterprise aber normales WPA geht wunderbar.
Sound
Jetzt wirds das erste mal spannend und wir müssen ans Eingemachte. Sound funktioniert nämlich nur mit der aktuellsten ALSA Version. Also holen wir uns erstmal den neuesten snapshot und installieren ihn per Hand in das System:
wget ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/snapshot/alsa-driver-unstable-snapshot.tar.gz tar xf alsa-driver-unstable-snapshot.tar.gz cd alsa-driver-unstable sudo ./configure --enable-dynamic-minors --without-oss --with-cards="hda-intel" sudo make sudo make install
Danach geht auch der Sound. Das Mikrophon ist etwas leise, aber die Boxen sind ordentlich laut und werden noch besser, wenn man den Surround Regler hochzieht.
Tastaturbeleuchtung
Super Feature und wir wollen das natürlich auch nutzen. Leider geht auch das wieder nur mit der aktuellsten version des Kernel Moduls applesmc. Also wieder runterladen und per Hand installieren:
Die Version aus dem 2.31er Kernel gibt es hier:
http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.31.y.git;a=blob_plain;f=drivers/hwmon/applesmc.c;hb=HEAD
In dem gleichen Ordner wo die .c Datei gespeichert ist, legen wir eine Makefile mit folgendem Inhalt an (nur eine Zeile):
obj-m := applesmc.o
Wenn wir jetzt folgenden Befehl aufrufen, wird das Modul gebaut:
make -C /lib/modules/$(uname -r)/build SUBDIRS=$PWD modules
Das fertige Modul (.ko Datei) packen wir an seinen Bestimmungsort in "/lib/modules/KERNELVERSION/kernel/drivers/hwmon/" und bringen die Liste der Module mit einem "depmod -ae" wieder auf den aktuellen Stand. Anschließend kann man mit folgendem Befehl die Beleuchtung ein- und ausschalten und natürlich auch mit einem Wert zwischen 0 und 255 dimmen:
sh -c "echo 255 > /sys/devices/platform/applesmc.768/leds/smc::kbd_backlight/brightness"
Man kann es sogar automatisch regeln lassen, dazu guckt euch bitte das Programm "pommed" an. Ab Version 1.27 (findet man in der Factory) wird das Macbook unterstützt.
Jetzt muss das Modul nur noch beim Start mit geladen werden. Dies erreichen wir, indem wir den Namen des Moduls in der Datei "/etc/sysconfig/kernel" in die Variable MODULES_LOADED_ON_BOOT schreiben. Die Zeile sollte dann so aussehen:
MODULES_LOADED_ON_BOOT="applesmc"
Hintergrundbeleuchtung des Bildschirms
Jetzt wird es noch ein wenig heftiger, weil wir nun patchen müssen, aber auch das soll kein Problem sein. Zuerst mal wieder eine aktuelle Version des Moduls runterladen:
http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.31.y.git;a=blob_plain;f=drivers/video/backlight/mbp_nvidia_bl.c;hb=74fca6a42863ffacaf7ba6f1936a9f228950f657
Und den Patch, damit auch alles schön funktioniert brauchen wir auch:
http://spuriousinterrupt.org/stuff/mbp_nvidia_bl-add_mmio_backlight_reg-2.6.31rc1.diff
Beides kommt zusammen in einen Ordner und wir passen in dem Patch oben noch 2 Zeilen an indem wir den langem Pfad durch Folgendes ersetzen:
--- a/mbp_nvidia_bl.c +++ b/mbp_nvidia_bl.c
Dann wird gepatch:
patch mbp_nvidia_bl.c < mbp_nvidia_bl-add_mmio_backlight_reg-2.6.31rc1.diff
Jetzt machen wir wieder eine Makefile (wieder nur eine Zeile darin):
obj-m := mbp_nvidiaa_bl.o
Und erstellen unser Modul wie schon vorhin mit:
make -C /lib/modules/$(uname -r)/build SUBDIRS=$PWD modules
Das Original welches unter "/lib/modules/KERNELVERSION/kernel/drivers/video/backlight/" wird ersetzt und mal wieder "depmod -ae" aufgerufen. Anschließend kann mit KPowersave die Helligkeit angepasst werden (oder dem GNOME Äquivalent - nicht getestet)
Wir tragen das Modul wieder für den Start ein. Die Zeile sieht jetzt so aus:
MODULES_LOADED_ON_BOOT="applesmc mbp_nvidia_bl"
Touchpad
Das Touchpad funktioniert zwar schon direkt nach der Installation, aber nur sehr rudimentär. Wir wollen es so einrichten, dass man mit 2 Fingern Rechtsklicken kann, mit 3 Fingern einen mittleren Klick macht und auch das Scrollen mit 2 Fingern möglich wird.
Dazu brauchen wir zuerst die folgende Version des bcm5974 Moduls:
http://ppa.launchpad.net/mactel-support/ppa/ubuntu/pool/main/b/bcm5974-dkms/bcm5974-dkms_1.1.3-0ubuntu1~mactel-support1~jaunty1.tar.gz
In dem Tar suchen wir die Datei "bcm5974.c" und packen sie in einen neuen Ordner in welchem wir auch wieder eine Makefile erstellen:
obj-m := bcm5974.o
Kompiliert wird wie immer mit:
make -C /lib/modules/$(uname -r)/build SUBDIRS=$PWD modules
Das fertige Modul muss nach "/lib/modules/KERNELVERSION/kernel/drivers/input/mouse/" und ein "depmod -ae" braucht es auch wieder.
Weil es wohl ein Problem mit dem Modul usbhid gibt muss jetzt noch die Reihenfolge, in der die Module geladen werden, eindeutig festgelegt werden. Dazu blacklisten wir zuerst das Modul "usbhid" damit es nicht automatisch geladen wird.
Dazu muss man an die Datei "/etc/modprobe.d/blacklist" eine Zeile anfügen:
blacklist usbhid
Jetzt ist es ganz wichtig, dass der nächste Schritt auch durchgeführt wird, weil sonst das Keyboard und die Maus nicht mehr funktioniert.
Die Module müssen per Hand, wie schon die Vorherigen, geladen werden. Die Zeile sollte jetzt so aussehen:
MODULES_LOADED_ON_BOOT="applesmc mbp_nvidia_bl bcm5974 usbhid"
Die Reihenfolge IST wichtig! bcm5974 muss vor usbhid geladen werden, weil das Modul sonst das Touchpad vor dem anderen wegschnappt und es dann nicht funktioniert.
Damit das Touchpad aktiv wird, muss die "/etc/X11/xorg.conf" noch angepasst werden. Sie kann auch komplett übernommen werden.
Anmerkungen
Das Touchpad muss jeder Selber anpassen. Irgendwie scheint die Handballendetection nicht richtig zu funktionieren.
Die Infrarot Schnittstelle habe ich auf Grund der fehlenden Apple Fernbedienung noch nicht testen können. Angeblich soll die Fernbedienung aber als normale Tastatur angemeldet sein und dann entsprechend Tastendrücke simulieren.
Probleme
Ich habe es noch nicht geschafft einen Externen Monitor per VGA Adapter anzuschließen. Dabei ist das Bild immer komplett gestört. Ich meine gelesen zu haben, dass der Analogmonitor einfach nicht richtig erkannt wird und man kann diese Auto-Erkennung irgendwie in der Xorg.conf ausschalten. Da ich zur Zeit aber nur einen DVI Monitor benutze, habe ich mich noch nicht weiter damit beschäftigt.
Schlussbemerkung
Ich glaube man kann jetzt behaupten, dass das Macbook komplett unterstützt wird. Mir fällt jetzt so spontan auch nichts mehr ein, dass nicht richtig funktioniert und man kann sehr zufrieden sein mit einem super Stück Hardware.
Die Akkulaufzeit liegt bei mir etwa bei 5 Stunden, aber da geht bestimmt noch einiges, da der Akku neu und noch nicht eingespielt ist. Ich würde mich freuen, wenn die nächste OpenSUSE Version das Macbook komplett out-of-the-box unterstützt.
Anhänge
Hier ein paar nützliche Dateien
xorg.conf
# nvidia-settings: X configuration file generated by nvidia-settings
# nvidia-settings: version 1.0 (buildmeister@builder58) Fri Aug 14 18:34:43 PDT 2009
Section "ServerLayout"
Identifier "Layout0"
Screen 0 "Screen0" 0 0
InputDevice "Keyboard0" "CoreKeyboard"
InputDevice "Touchpad0" "CorePointer"
InputDevice "Mouse0" "SendCoreEvents"
EndSection
Section "Files"
InputDevices "/dev/gpmdata"
InputDevices "/dev/input/mice"
FontPath "/usr/share/fonts/misc:unscaled"
FontPath "/usr/share/fonts/local"
FontPath "/usr/share/fonts/75dpi:unscaled"
FontPath "/usr/share/fonts/100dpi:unscaled"
FontPath "/usr/share/fonts/Type1"
FontPath "/usr/share/fonts/URW"
FontPath "/usr/share/fonts/Speedo"
FontPath "/usr/share/fonts/PEX"
FontPath "/usr/share/fonts/cyrillic"
FontPath "/usr/share/fonts/latin2/misc:unscaled"
FontPath "/usr/share/fonts/latin2/75dpi:unscaled"
FontPath "/usr/share/fonts/latin2/100dpi:unscaled"
FontPath "/usr/share/fonts/latin2/Type1"
FontPath "/usr/share/fonts/latin7/75dpi:unscaled"
FontPath "/usr/share/fonts/baekmuk:unscaled"
FontPath "/usr/share/fonts/japanese:unscaled"
FontPath "/usr/share/fonts/kwintv"
FontPath "/usr/share/fonts/truetype"
FontPath "/usr/share/fonts/uni:unscaled"
FontPath "/usr/share/fonts/CID"
FontPath "/usr/share/fonts/ucs/misc:unscaled"
FontPath "/usr/share/fonts/ucs/75dpi:unscaled"
FontPath "/usr/share/fonts/ucs/100dpi:unscaled"
FontPath "/usr/share/fonts/hellas/misc:unscaled"
FontPath "/usr/share/fonts/hellas/75dpi:unscaled"
FontPath "/usr/share/fonts/hellas/100dpi:unscaled"
FontPath "/usr/share/fonts/hellas/Type1"
FontPath "/usr/share/fonts/misc/sgi:unscaled"
FontPath "/usr/share/fonts/xtest"
FontPath "/opt/kde3/share/fonts"
EndSection
Section "Module"
Load "dbe"
Load "extmod"
Load "type1"
Load "freetype"
Load "extmod"
Load "glx"
#Load "synaptics"
EndSection
Section "ServerFlags"
Option "Xinerama" "0"
Option "AllowMouseOpenFail" "on"
Option "ZapWarning" "on"
EndSection
Section "InputDevice"
Identifier "Touchpad0"
Driver "synaptics"
Option "SendCoreEvents" "true"
Option "Device" "/dev/psaux"
Option "Protocol" "auto-dev"
# Tasten zuordnen
Option "TapButton1" "1"
Option "TapButton2" "3"
Option "TapButton3" "2"
Option "ClickFinger1" "1"
Option "ClickFinger2" "3"
Option "ClickFinger3" "2"
# Ecken als Buttons?
Option "RTCornerButton" "0"
Option "RBCornerButton" "0"
Option "LTCornerButton" "0"
Option "LBCornerButton" "0"
# Raender definieren
Option "LeftEdge" "51"
Option "RightEdge" "1229"
Option "TopEdge" "44"
Option "BottomEdge" "756"
# Scrollen einstellen
Option "HorizEdgeScroll" "0"
Option "VertEdgeScroll" "0"
Option "HorizTwoFingerScroll" "0"
Option "VertTwoFingerScroll" "1"
Option "HorizScrollDelta" "45"
Option "VertScrollDelta" "15"
# Klick Einstellungen
Option "FingerLow" "25"
Option "FingerHigh" "30"
Option "FingerPress" "256" # Boeser Wert der fuers abdriften verantwortlich ist!!!
Option "MaxTapTime" "180"
Option "MaxTapMove" "220"
Option "MaxDoubleTapTime" "180"
Option "SingleTapTimeout" "180"
Option "ClickTime" "100"
Option "FastTaps" "0"
# Geschwindigkeit
Option "MinSpeed" "0.79"
Option "MaxSpeed" "0.88"
Option "AccelFactor" "0.0015"
# Sonstiges
Option "PalmDetect" "on"
Option "PalmMinWidth" "10"
Option "PalmMinZ" "200"
Option "TouchpadOff" "0"
Option "GuestMouseOff" "0"
Option "SHMConfig" "on"
# Unbekannter Krams
Option "PressureMotionMinZ" "30"
Option "PressureMotionMaxZ" "160"
Option "PressureMotionMinFactor" "1"
Option "PressureMotionMaxFactor" "1"
Option "GrabEventDevice" "1"
EndSection
Section "InputDevice"
Identifier "Mouse0"
Driver "mouse"
Option "Buttons" "5"
Option "Device" "/dev/input/mice"
Option "Name" "Apple Internal Keyboard / Trackpad"
Option "Protocol" "explorerps/2"
Option "Vendor" "Sysp"
Option "ZAxisMapping" "4 5"
EndSection
Section "InputDevice"
Identifier "Keyboard0"
Driver "kbd"
Option "Protocol" "Standard"
Option "XkbLayout" "de"
Option "XkbModel" "macintosh"
Option "XkbRules" "xfree86"
Option "XkbVariant" "nodeadkeys"
EndSection
Section "Monitor"
# HorizSync source: edid, VertRefresh source: edid
Identifier "Monitor0"
VendorName "Unknown"
ModelName "Apple Color LCD"
HorizSync 30.0 - 75.0
VertRefresh 60.0
Option "DPMS"
EndSection
Section "Device"
Identifier "Device0"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "GeForce 9400M"
EndSection
Section "Screen"
Identifier "Screen0"
Device "Device0"
Monitor "Monitor0"
DefaultDepth 24
Option "TwinView" "0"
Option "metamodes" "nvidia-auto-select +0+0"
SubSection "Display"
Depth 24
EndSubSection
EndSection
Autolight Daemon
Ich habe mir ein kleines C-Programm geschrieben, dass die Helligkeit des Monitors automatisch anpasst und die Tastaturbeleuchtung automatisch anschaltet.
Um das Programm kurzzeitig zu deaktivieren kann man eine Datei mit dem Namen "disableautolight.tmp" in "/dev/shm" anlegen. Damit das Programm auch nach dem Suspend noch richtig funktioniert habe ich KPowersave so eingestellt, dass es eine Datei mit dem Namen "fromsuspend.tmp" in "/dev/shm/" anlegt. Das sorgt dafür, dass beim Auffwachen die Werte einmal neu initialisiert werden.
touch /dev/shm/disableautolight.tmp touch /dev/shm/fromsuspend.tmp
Den Code einfach mit
gcc -o autolight autolight.c
compilieren. Hier ist der Code, bestimmt nicht sonderlich schön, macht aber was er soll:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
int file_exists(char * filename)
{
if(open(filename, O_RDONLY) == -1)
{
return 0;
}
close(filename);
return 1;
}
int get_kbd_light()
{
int fd;
fd = open("/sys/devices/platform/applesmc.768/leds/smc::kbd_backlight/brightness", O_RDONLY);
char buf[3];
memset(buf, 0, 3);
int ret;
ret = read(fd, buf, 3);
ret = atoi(buf);
close(fd);
return ret;
}
void set_kbd_light(int value)
{
int fd;
fd = open("/sys/devices/platform/applesmc.768/leds/smc::kbd_backlight/brightness", O_WRONLY);
char buf[3];
memset(buf, 0, 3);
sprintf(buf,"%d",value);
write(fd, buf, strlen(buf));
close(fd);
}
int get_lcd_light()
{
int fd;
fd = open("/sys/class/backlight/mbp_backlight/brightness", O_RDONLY);
char buf[3];
memset(buf, 0, 3);
int ret;
ret = read(fd, buf, 3);
ret = atoi(buf);
close(fd);
return ret;
}
void set_lcd_light(int value)
{
int fd;
fd = open("/sys/class/backlight/mbp_backlight/brightness", O_WRONLY);
char buf[3];
memset(buf, 0, 3);
sprintf(buf,"%d",value);
write(fd, buf, strlen(buf));
close(fd);
}
int get_amb_light()
{
int fd;
fd = open("/sys/devices/platform/applesmc.768/light", O_RDONLY);
char buf[9];
memset(buf, 0, 9);
int ret;
ret = read(fd, buf, 9);
char tmpbuf;
char buf2[3];
memset(buf2, 0, 3);
int counter = 1;
while(tmpbuf != ',')
{
if(counter > 8)
return -1;
tmpbuf = buf[counter];
buf2[counter - 1] = buf[counter];
counter++;
}
ret = atoi(buf2);
close(fd);
return ret;
}
int main (int argc, char **argv)
{
while(1)
{
if(!file_exists("/dev/shm/disableautolight.tmp"))
{
if(file_exists("/dev/shm/fromsuspend.tmp"))
{
sleep(5);
int tmp;
tmp = get_kbd_light();
tmp = tmp - 1;
set_kbd_light(tmp);
tmp = tmp + 1;
set_kbd_light(tmp);
tmp = get_lcd_light();
tmp = tmp - 1;
set_lcd_light(tmp);
tmp = tmp + 1;
set_lcd_light(tmp);
remove("/dev/shm/fromsuspend.tmp");
}
int amb_light = get_amb_light();
if(amb_light >= 0)
{
int kbd_light = get_kbd_light();
int kbd_trigger_light = 3;
int kbd_new_light = 150;
if(amb_light < kbd_trigger_light)
{
if(kbd_light != kbd_new_light)
{
set_kbd_light(kbd_new_light);
}
}
else
{
if(kbd_light != 0)
{
set_kbd_light(0);
}
}
int lcd_light = get_lcd_light();
int lcd_new_light = amb_light / 60;
lcd_new_light = lcd_new_light * 3;
lcd_new_light = lcd_new_light + 3;
if(lcd_light != lcd_new_light)
{
set_lcd_light(lcd_new_light);
}
}
}
sleep(5);
}
}
Ich hab das Programm nach "/usr/sbin/" gepackt und nutze folgendes init-script:
#!/bin/sh
#
### BEGIN INIT INFO
# Provides: autolight
# Required-Start: $remote_fs
# Required-Stop: $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: autolight sets lcd and keyboard light automatically
# Description: Start autolight to set lcd and keyboard light automatically
### END INIT INFO
# Check for missing binaries (stale symlinks should not happen)
# Note: Special treatment of stop for LSB conformance
AUTOLIGHT_BIN=/usr/sbin/autolight
. /etc/rc.status
# Reset status of this service
rc_reset
case "$1" in
start)
echo -n "Starting autolight "
## Start daemon with startproc(8). If this fails
## the return value is set appropriately by startproc.
/sbin/startproc $AUTOLIGHT_BIN
# Remember status and be verbose
rc_status -v
;;
stop)
echo -n "Shutting down autolight "
## Stop daemon with killproc(8) and if this fails
## killproc sets the return value according to LSB.
/sbin/killproc -TERM $AUTOLIGHT_BIN
# Remember status and be verbose
rc_status -v
;;
try-restart|condrestart)
## Do a restart only if the service was active before.
## Note: try-restart is now part of LSB (as of 1.9).
## RH has a similar command named condrestart.
if test "$1" = "condrestart"; then
echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
fi
$0 status
if test $? = 0; then
$0 restart
else
rc_reset # Not running is not a failure.
fi
# Remember status and be quiet
rc_status
;;
restart)
## Stop the service and regardless of whether it was
## running or not, start it again.
$0 stop
$0 start
# Remember status and be quiet
rc_status
;;
force-reload)
## Signal the daemon to reload its config. Most daemons
## do this on signal 1 (SIGHUP).
## If it does not support it, restart the service if it
## is running.
echo -n "Reload service autolight "
$0 try-restart
rc_status
;;
reload)
## Like force-reload, but if daemon does not support
## signaling, do nothing (!)
rc_failed 3
rc_status -v
;;
status)
echo -n "Checking for service autolight "
## Check status with checkproc(8), if process is running
## checkproc will return with exit status 0.
# Return value is slightly different for the status command:
# 0 - service up and running
# 1 - service dead, but /var/run/ pid file exists
# 2 - service dead, but /var/lock/ lock file exists
# 3 - service not running (unused)
# 4 - service status unknown :-(
# 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.)
# NOTE: checkproc returns LSB compliant status values.
/sbin/checkproc $AUTOLIGHT_BIN
# NOTE: rc_status knows that we called this init script with
# "status" option and adapts its messages accordingly.
rc_status -v
;;
*)
echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload}"
exit 1
;;
esac
rc_exit

