====== Tablette Athesi AP1001CL — MX Linux (Le Pain d'Antan) ======
Procédure complète pour installer, configurer et cloner les tablettes Athesi AP1001CL utilisées au Pain d'Antan.
* **Matériel** : Athesi AP1001CL — Intel Atom x5-Z8350 (Cherry Trail), ~4 Go RAM, eMMC 58 Go, écran DSI 1200x1920 (portrait natif), tactile Goodix, caméra OV2680 (atomisp)
* **Système** : MX Linux 25.2 « Infinity » XFCE, édition AHS, démarrage **systemd**, noyau Liquorix
* **Tablette modèle** : ''pa-ixl-tab'' — utilisateur ''tablette''
* **Accès à distance** : RustDesk via ''rust.makeitsimple.be'' (Server Pro), carnet d'adresses **PainAntan**
* **Projet** : dossier ''tablette-mx'' (script ''installer-tablette.sh'', ''wallpaper.png'', ''bootloader.png'', ''LISEZMOI.md'')
===== 1. Pourquoi MX Linux et pas NixOS =====
NixOS a d'abord été essayé (installation reproductible par flake). Il a été abandonné à cause de gels répétés :
* Le bus I2C du circuit d'alimentation AXP288 (PMIC) est **partagé avec la P-Unit** (gestion d'énergie du SoC). Le noyau doit arbitrer l'accès par un sémaphore : option ''CONFIG_I2C_DESIGNWARE_BAYTRAIL''.
* Le noyau NixOS standard **n'active pas** cette option. Résultats : ''i2c_designware … timeout'', « No PMIC registered », écran DSI qui ne se rallume pas après une rotation (''flip_done timed out''), gels.
* Corriger demande de **recompiler tout le noyau** (l'option est dans un pilote intégré, pas un module), et cela à chaque mise à jour du noyau. Trop coûteux pour quelques tablettes.
* Le noyau Liquorix de MX a ''CONFIG_I2C_DESIGNWARE_BAYTRAIL=y'' : le problème disparaît.
Vérification sur une tablette :
grep DESIGNWARE_BAYTRAIL /boot/config-$(uname -r) # doit afficher =y
===== 2. Installation de MX sur la tablette modèle =====
==== 2.1 Démarrer sur la clé USB ====
- Redémarrer la tablette en appuyant sur **F7** (menu de démarrage du BIOS) ; choisir ''UEFI: USB DISK…''.
- Dans le menu GRUB de la clé, sélectionner l'entrée **(systemd)**, appuyer sur ''e'' et ajouter à la ligne ''linux'' :
lang=fr_BE kbd=be tz=Europe/Brussels intel_idle.max_cstate=1 reboot=hard
- Démarrer avec **F10**.
==== 2.2 Installateur MX ====
* Type : **installation classique sur tout le disque** — ''mmcblk0'' (eMMC 58 Go). //Ne pas confondre avec la clé USB (sdX).//
* Fichier d'échange de 2 Go (par défaut).
* Nom : ''pa-ixl-tab'' (modèle), domaine ''painantan.lan'', **Samba décoché**.
* Locale Belgique – français, fuseau Europe/Brussels, clavier ''be''.
* Utilisateur ''tablette'', **connexion automatique** cochée.
Les options ''intel_idle.max_cstate=1 reboot=hard'' saisies au démarrage live sont reprises dans le GRUB installé.
==== 2.3 Premier démarrage avec le PiKVM ====
Avec l'HDMI branché, MX place l'HDMI **à côté** de l'écran de la tablette (bureau étendu). Si le panneau ou le menu disparaît : débrancher puis rebrancher l'HDMI et choisir **Écran en miroir** dans la fenêtre qui s'ouvre.
Ne pas éteindre l'écran intégré (''xrandr --output DSI-1 --off'') pendant la session : le panneau XFCE s'y perd et l'affichage HDMI devient inexploitable.
Connecter ensuite le Wi-Fi **PainAntan** via l'icône réseau.
===== 3. Script d'installation =====
==== 3.1 Préparer le dossier ====
Dans ''~/tablette-mx/'' :
^ Fichier ^ Rôle ^ Obligatoire ^
| ''installer-tablette.sh'' | le script | oui |
| ''wallpaper.png'' | fond d'écran 1920x1200 | non |
| ''bootloader.png'' | logo affiché dans le menu GRUB | non |
| ''jeton-rustdesk.txt'' | jeton API de la console RustDesk Pro | non (sans lui, pas d'inscription automatique au carnet) |
Le jeton RustDesk ne va **jamais** dans git. Un ''.gitignore'' l'exclut.
Depuis une clé USB (montée sous ''/media/tablette//'') :
cd ~/tablette-mx
U=/media/tablette/MX-LIVE
cp $U/wallpaper.png $U/bootloader.png .
tr -d '\r\n ' < $U/RUSTDESK_TOKEN.TXT > jeton-rustdesk.txt && chmod 600 jeton-rustdesk.txt
==== 3.2 Lancer ====
cd ~/tablette-mx && sudo ./installer-tablette.sh 2>&1 | tee ~/installation.log
Puis **redémarrer**. Le script est **relançable sans risque** : il ne réécrit que ce qui change (lignes « ecrit : … »). Pour modifier un réglage : corriger le script, le relancer, redémarrer.
==== 3.3 Ce que fait le script ====
^ Étape ^ Détail ^
| Paquets | onboard, iio-sensor-proxy, xinput, xdotool, yad, v4l-utils, dconf-cli… |
| GRUB | ''quiet intel_idle.max_cstate=1 reboot=hard pcie_aspm=off'' — pas de ''splash'' (bloquait l'interface) |
| Wi-Fi Intel | ''options iwlwifi power_save=0 11n_disable=1 bt_coex_active=0 swcrypto=1'' |
| Caméra | firmware ''shisp_2401a0_v21.bin'' (vérifié par SHA-256) dans ''/lib/firmware/intel/ipu/'' ; ''intel_atomisp2_pm'' mis en liste noire |
| Xorg | pilote modesetting en **DRI2** (capture RustDesk) ; matrice tactile ; aucune mise en veille de l'écran |
| Session | connexion automatique LightDM ; variables ''MOZ_USE_XINPUT2'', ''GNOME_ACCESSIBILITY'', ''QT_ACCESSIBILITY'' ; curseur 48 |
| Firefox (politiques) | accessibilité forcée (clavier visuel) ; VA-API ; 2 processus ; pas de cache disque ; mots de passe non révélables ; outils de développement et ''about:config'' bloqués |
| Clavier visuel | onboard en AZERTY belge, ouverture automatique dans les champs texte, bouton flottant |
| Interface (''tablette-ui'') | rotation paysage, raccourcis Boucom / Shyfter / Infos PDA, DPI 144, thème de fenêtre ''Default-xhdpi'', panneaux et icônes agrandis, pas de veille, fond d'écran |
| Rotation (''tablette-rotation'') | accéléromètre → rotation de l'écran et du tactile ; bloquée en paysage si HDMI branché |
| Thème | Greybird + accents caramel, panneau brun foncé, dossiers Papirus bruns ; icônes MX par défaut retirées du bureau ; horloge (conky) désactivée |
| Performances | zram (zstd, 50 %, prioritaire), ''vm.swappiness=100'', pilote vidéo ''i965'', cups/ModemManager coupés, notificateur de mises à jour MX coupé, ''noatime'', TRIM hebdomadaire, journal limité à 64 Mo |
| GRUB graphique | ''bootloader.png'' centré sur fond brun, tourné d'un quart de tour (dalle en portrait natif) |
| RustDesk | dernière version .deb, serveur ''rust.makeitsimple.be'', mot de passe permanent aléatoire, inscription au carnet PainAntan |
| Clonage | installe ''tablette-preparer-clonage'' et le mécanisme de premier démarrage |
===== 4. Clonage =====
==== 4.1 Ordre ====
- Sur la tablette modèle : script d'installation (§3), redémarrage, **tests** (§6).
- Sur la modèle : sudo tablette-preparer-clonage Efface l'identité (ID et mot de passe RustDesk, clés SSH, machine-id), crée ''/etc/tablette/a-personnaliser'' et **éteint**.
- **Clonezilla** : image du disque ''mmcblk0'', puis restauration sur chaque tablette.
- **Premier démarrage** de chaque tablette (et de la modèle) :
* une fenêtre demande le **nom** (minuscules, chiffres, tirets — ex. ''pa-ixl-tab-02''), clavier visuel affiché ;
* nouvelle identité : machine-id, clés SSH, nouvel ID RustDesk, nouveau mot de passe RustDesk ;
* inscription dans le carnet **PainAntan** sous ce nom ;
* redémarrage.
==== 4.2 Fonctionnement interne ====
^ Élément ^ Rôle ^
| ''tablette-premier-demarrage.service'' | si ''/etc/tablette/a-personnaliser'' existe : machine-id, clés SSH, crée ''/run/tablette'' |
| ''tablette-demander-nom'' (autostart) | demande le nom (yad) et l'écrit dans ''/run/tablette/nom'' |
| ''tablette-nommer.path'' / ''.service'' | dès que le nom est déposé : ''hostnamectl'', ''/etc/hosts'', RustDesk, suppression du témoin, redémarrage |
| ''tablette-rustdesk'' | ''config'' / ''motdepasse'' / ''enregistrer NOM'' |
===== 5. RustDesk et sécurité =====
==== 5.1 Jeton de la console ====
Console RustDesk Pro → **Paramètres → Jetons → Créer** :
* **Périphérique** : lecture et écriture
* **Carnet d'adresses** : lecture et écriture
* rien d'autre ; **date d'expiration** recommandée, révoquer après le déploiement.
Le jeton est stocké dans ''/etc/rustdesk/token'' (root, 600) et se retrouve dans l'image Clonezilla.
==== 5.2 Mots de passe ====
* **Un mot de passe différent par tablette**, aléatoire, 20 caractères, généré au premier démarrage. Il n'est **pas** dans l'image.
* Lecture sur la tablette : ''sudo cat /etc/rustdesk/password''
* Stocké aussi dans le carnet PainAntan (serveur auto-hébergé). La console n'affiche que « défini / non défini ».
* Réinscription manuelle : ''sudo tablette-rustdesk enregistrer ''
==== 5.3 Recommandations ====
* Double authentification sur les comptes qui ont accès au carnet PainAntan.
* Lecture seule pour ceux qui ne font que se connecter ; écriture réservée à l'administrateur.
* Protéger le serveur RustDesk et ses sauvegardes (ils contiennent de quoi accéder aux tablettes).
* Tablette perdue ou volée : la retirer du carnet.
==== 5.4 Firefox ====
Politiques dans ''/etc/firefox/policies/policies.json'' : ''DisablePasswordReveal'', ''DisableDeveloperTools'', ''BlockAboutConfig'', ''DisableAppUpdate''. Les mots de passe enregistrés restent utilisables en remplissage automatique mais ne peuvent pas être affichés.
===== 6. Tests après installation =====
* [ ] Démarrage **sans HDMI** : le bureau s'affiche directement (pas d'écran noir avec seulement le curseur)
* [ ] Image dans le menu GRUB
* [ ] Rotation automatique dans les 4 sens (HDMI débranché)
* [ ] Clavier visuel AZERTY dans un champ texte de Firefox
* [ ] Raccourcis Boucom, Shyfter, Infos PDA
* [ ] Caméra
* [ ] Batterie visible (''ls /sys/class/power_supply'' → ''axp288_fuel_gauge'')
* [ ] RustDesk : connexion depuis le carnet PainAntan
* [ ] Mémoire compressée : ''swapon --show'' → ''/dev/zram0'' priorité 100
===== 7. Problèmes rencontrés et solutions =====
^ Symptôme ^ Cause ^ Solution ^
| Gels, ''i2c_designware … timeout'', écran DSI noir après rotation (NixOS) | noyau sans ''I2C_DESIGNWARE_BAYTRAIL'' | passer à MX (noyau Liquorix) |
| Écran noir avec seulement le curseur au démarrage sans HDMI | commande ''xrandr'' commune DSI + HDMI qui échoue si l'HDMI est absent ; rotation dans Xorg dès le démarrage | rotation faite par la session, commande séparée pour l'HDMI |
| Écran noir puis gel en tournant la tablette avec l'HDMI branché | rotation + recopie HDMI trop lourde pour le GPU Cherry Trail | rotation bloquée en paysage quand l'HDMI est branché |
| Clavier visuel qui ne s'ouvre jamais seul | onboard attend un « mode tablette » que la tablette ne signale pas | ''tablet-mode-detection-enabled=false'' (dconf), redémarrer onboard |
| onboard en QWERTY | lancé avant la disposition belge | autostart d'origine masqué ; lancement différé avec ''setxkbmap be'' |
| Icône de raccourci invisible sur le bureau | fichier ajouté après le démarrage du bureau | ''xfdesktop --reload'' |
| zram inactif | service ''zramswap'' masqué par MX | ''systemctl unmask zramswap'' |
| Image Plymouth : écran noir (NixOS) | ''i915'' chargé trop tôt (initrd) avant le pilote du rétroéclairage | pas de Plymouth ; image dans GRUB à la place |
| Panneau XFCE disparu | écran intégré éteint pendant la session | rebrancher l'HDMI et choisir « miroir » |
===== 8. Maintenance =====
* **Mises à jour** : à la main (MX Updater ou ''sudo apt update && sudo apt full-upgrade''). Après une mise à jour du noyau, redémarrer et vérifier la caméra.
* **Modifier un réglage** : corriger ''installer-tablette.sh'', le relancer sur les tablettes déjà déployées, redémarrer. Refaire l'image Clonezilla pour les futures tablettes.
* **Journal de la dernière installation** : ''~/installation.log''
* **Fichiers installés** : ''/usr/local/bin/tablette-*'', ''/usr/local/sbin/tablette-*'', ''/usr/local/share/tablette/'', ''/etc/xdg/autostart/tablette-*.desktop'', ''/etc/X11/xorg.conf.d/20-tablette.conf''
===== 9. Script complet =====
#!/bin/bash
# =============================================================================
# Tablette Athesi AP1001CL (Cherry Trail x5-Z8350) - MX Linux 25 (systemd)
# Installation / mise a jour de tous les reglages. Relancable sans risque.
#
# Usage : sudo ./installer-tablette.sh
# Fichiers optionnels a cote du script :
# wallpaper.png fond d'ecran
# jeton-rustdesk.txt jeton API de la console RustDesk Pro (jamais dans git)
# =============================================================================
set -euo pipefail
[ "$(id -u)" = 0 ] || exec sudo "$0" "$@"
ICI=$(cd "$(dirname "$0")" && pwd)
UTIL=tablette
RD_SERVEUR=rust.makeitsimple.be
RD_CLE='OhOcYR3xOjsI+4EInYR74DB3Ot1dd0aAl5W0odZXNVk='
RD_CARNET=PainAntan
PART=/usr/local/share/tablette # fichiers partages (fond d'ecran, raccourcis)
etape() { echo; echo "=== $* ==="; }
# Ecrit un fichier seulement si son contenu change (stdin -> chemin, mode)
ecrire() { local f=$1 m=${2:-644} t; t=$(mktemp); cat >"$t"
if ! cmp -s "$t" "$f" 2>/dev/null; then install -D -m "$m" "$t" "$f"; echo " ecrit : $f"; fi; rm -f "$t"; }
# Fixe VAR=valeur dans /etc/environment
env_var() { sed -i "/^$1=/d" /etc/environment; echo "$1=$2" >> /etc/environment; }
id "$UTIL" >/dev/null 2>&1 || { echo "Utilisateur $UTIL absent : cree-le pendant l'installation de MX."; exit 1; }
HOME_U=$(getent passwd "$UTIL" | cut -d: -f6)
# -----------------------------------------------------------------------------
etape "Paquets"
export DEBIAN_FRONTEND=noninteractive
apt-get update -q
apt-get install -y -q onboard iio-sensor-proxy xinput xdotool x11-xserver-utils \
v4l-utils yad curl ca-certificates dconf-cli at-spi2-core
# -----------------------------------------------------------------------------
etape "Demarrage (GRUB)"
# Cherry Trail : C-states profonds -> gels ; reboot ACPI qui ne redemarre pas.
# Pas de 'splash' : il bloquait l'interface graphique sur cette tablette.
CMDLINE="quiet intel_idle.max_cstate=1 reboot=hard pcie_aspm=off"
if ! grep -q "^GRUB_CMDLINE_LINUX_DEFAULT=\"$CMDLINE\"" /etc/default/grub; then
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"$CMDLINE\"|" /etc/default/grub
update-grub
fi
# -----------------------------------------------------------------------------
etape "Wi-Fi Intel (iwlwifi)"
ecrire /etc/modprobe.d/tablette-iwlwifi.conf <<'EOF'
# Stabilite Wi-Fi : pas d'economie d'energie, pas de 802.11n, pas de coexistence BT,
# chiffrement logiciel
options iwlwifi power_save=0 11n_disable=1 bt_coex_active=0 swcrypto=1
EOF
# -----------------------------------------------------------------------------
etape "Firmware camera (atomisp / OV2680)"
FW_SHA=e89359f4e4934c410c83d525e283f34c5fcce9cb5caa75ad8a32d66d3842d95c
FW=/lib/firmware/intel/ipu/shisp_2401a0_v21.bin
if ! echo "$FW_SHA $FW" | sha256sum -c --quiet 2>/dev/null; then
t=$(mktemp)
curl -fsSL -o "$t" https://raw.githubusercontent.com/intel-aero/meta-intel-aero-base/master/recipes-kernel/linux/linux-yocto/shisp_2401a0_v21.bin
echo "$FW_SHA $t" | sha256sum -c --quiet
install -D -m644 "$t" "$FW"; ln -sf intel/ipu/shisp_2401a0_v21.bin /lib/firmware/shisp_2401a0_v21.bin
rm -f "$t"
fi
# intel_atomisp2_pm s'accroche a l'ISP et empeche le pilote atomisp de le prendre
ecrire /etc/modprobe.d/tablette-camera.conf <<'EOF'
blacklist intel_atomisp2_pm
EOF
# -----------------------------------------------------------------------------
etape "Affichage et tactile (Xorg)"
ecrire /etc/X11/xorg.conf.d/20-tablette.conf <<'EOF'
# Pilote modesetting en DRI2 : necessaire pour la capture d'ecran RustDesk
Section "Device"
Identifier "Intel"
Driver "modesetting"
Option "DRI" "2"
Option "Monitor-DSI-1" "DSI-1"
Option "Monitor-HDMI-2" "HDMI-2"
EndSection
# Dalle native en portrait (1200x1920). La rotation en paysage est faite par la session
# (tablette-ui) : tournee des le demarrage de X, la dalle restait noire avec seulement
# le curseur jusqu'a la premiere rotation.
Section "Monitor"
Identifier "DSI-1"
Option "Primary" "true"
EndSection
# HDMI (PiKVM) superpose a l'ecran integre
Section "Monitor"
Identifier "HDMI-2"
Option "Position" "0 0"
EndSection
# Ecran tactile Goodix : meme rotation que l'affichage
Section "InputClass"
Identifier "tactile tourne"
MatchIsTouchscreen "on"
Option "TransformationMatrix" "0 1 0 -1 0 1 0 0 1"
EndSection
# Libre-service : jamais de mise en veille de l'ecran
Section "ServerFlags"
Option "BlankTime" "0"
Option "StandbyTime" "0"
Option "SuspendTime" "0"
Option "OffTime" "0"
EndSection
EOF
# -----------------------------------------------------------------------------
etape "Session : connexion automatique, variables, Firefox, onboard"
groupadd -rf autologin; usermod -aG autologin,video,audio,input,netdev "$UTIL" 2>/dev/null || true
ecrire /etc/lightdm/lightdm.conf.d/50-tablette.conf </dev/null || echo "$HOME/Bureau"); mkdir -p "$desk"
for f in "$PART"/raccourcis/*.desktop; do
dst="$desk/$(basename "$f")"; install -m755 "$f" "$dst"
gio set "$dst" metadata::xfce-exe-checksum "$(sha256sum "$dst" | cut -d' ' -f1)" 2>/dev/null || true
done
xfdesktop --reload 2>/dev/null || true # sinon une icone ajoutee apres son demarrage reste invisible
# Fenetres : pas de compositeur (perfs), theme a gros boutons
q -c xfwm4 -p /general/use_compositing -n -t bool -s false
q -c xfwm4 -p /general/theme -n -t string -s Default-xhdpi
q -c xfwm4 -p /general/title_font -n -t string -s "Sans Bold 11"
# Polices / DPI / curseur
q -c xsettings -p /Xft/DPI -n -t int -s 144
q -c xsettings -p /Gtk/CursorThemeSize -n -t int -s 48
# Tableaux de bord et icones plus grands
for p in $(q -c xfce4-panel -l | grep -oE '^/panels/panel-[0-9]+' | sort -u); do
q -c xfce4-panel -p "$p/size" -n -t uint -s 56
q -c xfce4-panel -p "$p/icon-size" -n -t uint -s 40
done
q -c xfce4-desktop -p /desktop-icons/icon-size -n -t uint -s 72
# Jamais de mise en veille ni de verrouillage
pm=/xfce4-power-manager
q -c xfce4-power-manager -p $pm/dpms-enabled -n -t bool -s false
q -c xfce4-power-manager -p $pm/blank-on-ac -n -t int -s 0
q -c xfce4-power-manager -p $pm/blank-on-battery -n -t int -s 0
q -c xfce4-power-manager -p $pm/lock-screen-suspend-hibernate -n -t bool -s false
xset s off -dpms 2>/dev/null || true
# Fond d'ecran sur chaque sortie connectee
if [ -f "$PART/wallpaper.png" ]; then
for out in $(xrandr --query | awk '/ connected/{print $1}'); do
b=/backdrop/screen0/monitor$out/workspace0
q -c xfce4-desktop -p $b/last-image -n -t string -s "$PART/wallpaper.png"
q -c xfce4-desktop -p $b/image-style -n -t int -s 5
done
fi
EOF
ecrire /etc/xdg/autostart/tablette-ui.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=Reglages tablette
Exec=/usr/local/bin/tablette-ui
X-GNOME-Autostart-enabled=true
EOF
# -----------------------------------------------------------------------------
etape "Rotation automatique (accelerometre)"
ecrire /usr/local/bin/tablette-rotation 755 <<'EOF'
#!/bin/bash
# Orientation physique (iio-sensor-proxy) -> rotation xrandr + matrice du tactile Goodix
touch="Goodix Capacitive TouchScreen"
last=
apply() {
case "$1" in
# Correspondance validee sur la tablette (capteur monte tete-beche)
normal) rot=inverted; m="-1 0 1 0 -1 1 0 0 1" ;;
left-up) rot=left; m="0 -1 1 1 0 0 0 0 1" ;;
right-up) rot=right; m="0 1 0 -1 0 1 0 0 1" ;;
bottom-up) rot=normal; m="1 0 0 0 1 0 0 0 1" ;;
*) return ;;
esac
# HDMI branche (PiKVM) : on reste en paysage. Tourner l'ecran integre tout en le
# recopiant sur l'HDMI a donne ecran noir et gels sur cette puce.
if xrandr | grep -q '^HDMI-2 connected'; then rot=right; m="0 1 0 -1 0 1 0 0 1"; fi
[ "$rot" = "$last" ] && return
last=$rot
xrandr --output DSI-1 --rotate "$rot" --transform none --scale 1x1
for id in $(xinput list | grep -F "$touch" | grep -o 'id=[0-9]*' | cut -d= -f2); do
xinput set-prop "$id" "Coordinate Transformation Matrix" $m 2>/dev/null
done
}
sleep 8 # apres les reglages de session
monitor-sensor | while read -r line; do
case "$line" in
*"orientation changed:"*|*"Has accelerometer"*orientation:*)
apply "$(echo "$line" | grep -oE '(normal|left-up|right-up|bottom-up)' | tail -1)" ;;
esac
done
EOF
ecrire /etc/xdg/autostart/tablette-rotation.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=Rotation automatique
Exec=/usr/local/bin/tablette-rotation
X-GNOME-Autostart-enabled=true
EOF
# -----------------------------------------------------------------------------
etape "Theme aux couleurs Le Pain d'Antan"
# Icones Papirus avec des dossiers bruns (au lieu du bleu) : on repointe les liens
# symboliques des dossiers *-blue* vers leur equivalent *-brown* livre avec Papirus
for d in /usr/share/icons/Papirus/*/places; do
for l in "$d"/*.svg; do
[ -L "$l" ] || continue
c=$(readlink "$l")
case "$c" in *-blue*) n=${c//-blue/-brown}; [ -e "$d/$n" ] && ln -sfn "$n" "$l" ;; esac
done
done
gtk-update-icon-cache -qf /usr/share/icons/Papirus 2>/dev/null || true
# Brun fonce du fond d'ecran, creme du logo, caramel pour les selections
install -d -o "$UTIL" -g "$UTIL" "$HOME_U/.config/gtk-3.0"
ecrire "$HOME_U/.config/gtk-3.0/gtk.css" <<'EOF'
/* Couleurs Le Pain d'Antan (tablette) */
@define-color theme_selected_bg_color #9a6a45;
@define-color theme_selected_fg_color #ffffff;
*:selected, selection, menuitem:hover, row:selected, treeview:selected {
background-color: #9a6a45; color: #ffffff; }
progressbar progress, scale highlight { background-color: #9a6a45; border-color: #6e4a30; }
#XfcePanelWindow, .xfce4-panel { background-color: #2e1d15; color: #f3e9d8; }
#XfcePanelWindow button, #XfcePanelWindow label, .xfce4-panel button, .xfce4-panel label { color: #f3e9d8; }
#XfcePanelWindow button:hover, #XfcePanelWindow button:checked { background-color: #4a2e20; }
EOF
chown "$UTIL:" "$HOME_U/.config/gtk-3.0/gtk.css"
ecrire /usr/local/bin/tablette-theme 755 <<'EOF'
#!/bin/bash
# Theme neutre + accents bruns ; retrait des icones MX par defaut du bureau
sleep 6
xfconf-query -c xsettings -p /Net/ThemeName -n -t string -s Greybird
xfconf-query -c xsettings -p /Net/IconThemeName -n -t string -s Papirus
xfconf-query -c xfce4-panel -p /panels/panel-1/background-style -n -t uint -s 0 2>/dev/null
desk=$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME/Bureau")
rm -f "$desk/FAQ.desktop" "$desk/Help.desktop" "$desk/Quick_System_Info.desktop"
EOF
ecrire /etc/xdg/autostart/tablette-theme.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=Theme tablette
Exec=/usr/local/bin/tablette-theme
X-GNOME-Autostart-enabled=true
EOF
# -----------------------------------------------------------------------------
etape "Performances (memoire, services, eMMC, video)"
apt-get install -y -q zram-tools i965-va-driver python3-pil
# Memoire compressee : moins d'echanges avec l'eMMC, lente
ecrire /etc/default/zramswap <<'EOF'
ALGO=zstd
PERCENT=50
PRIORITY=100
EOF
systemctl unmask zramswap >/dev/null 2>&1 || true; systemctl enable zramswap >/dev/null 2>&1 || true; systemctl restart zramswap || true
ecrire /etc/sysctl.d/90-tablette.conf <<'EOF'
vm.swappiness=100
EOF
sysctl -q --system || true
env_var LIBVA_DRIVER_NAME i965 # decodage video materiel (Cherry Trail)
# Services inutiles sur la tablette (Bluetooth conserve)
for s in cups cups-browsed ModemManager; do systemctl disable --now "$s" >/dev/null 2>&1 || true; done
# Pas de verification des mises a jour MX en arriere-plan (mises a jour faites a la main)
for f in /etc/xdg/autostart/*.desktop; do
if grep -qiE 'apt-notifier|mx-updater' "$f"; then
a=$(basename "$f")
printf '[Desktop Entry]\nType=Application\nName=%s\nHidden=true\n' "$a" | ecrire "$HOME_U/.config/autostart/$a"
chown "$UTIL:" "$HOME_U/.config/autostart/$a"
fi
done
# eMMC : pas d'ecriture a chaque lecture (noatime), TRIM hebdomadaire, journal limite
if ! awk '$2=="/" {print $4}' /etc/fstab | grep -q noatime; then
cp /etc/fstab /etc/fstab.avant-tablette
awk 'BEGIN{OFS="\t"} $1 !~ /^#/ && $2=="/" {$4=$4",noatime"} {print}' /etc/fstab.avant-tablette > /etc/fstab
fi
systemctl enable fstrim.timer >/dev/null 2>&1 || true
ecrire /etc/systemd/journald.conf.d/tablette.conf <<'EOF'
[Journal]
SystemMaxUse=64M
EOF
# -----------------------------------------------------------------------------
etape "Image du menu de demarrage (GRUB)"
# GRUB s'affiche sur la dalle en portrait natif : l'image est composee en paysage
# (logo centre sur le brun du fond d'ecran) puis tournee d'un quart de tour.
if [ -f "$ICI/bootloader.png" ]; then
python3 - "$ICI/bootloader.png" /boot/grub/tablette-fond.png <<'PY'
import sys
from PIL import Image
src = Image.open(sys.argv[1]).convert("RGBA")
fond = Image.new("RGBA", (1920, 1200), (74, 46, 32, 255))
boite = (1920, 1200) if src.width >= 1600 else (1150, 720)
src.thumbnail(boite)
fond.alpha_composite(src, ((1920 - src.width) // 2, (1200 - src.height) // 2))
fond.convert("RGB").transpose(Image.Transpose.ROTATE_270).save(sys.argv[2])
PY
sed -i -e '/^GRUB_THEME=/s/^/#/' -e '/^GRUB_BACKGROUND=/d' /etc/default/grub
echo 'GRUB_BACKGROUND="/boot/grub/tablette-fond.png"' >> /etc/default/grub
update-grub
fi
# -----------------------------------------------------------------------------
etape "RustDesk"
if ! command -v rustdesk >/dev/null; then
url=$(curl -fsSL https://api.github.com/repos/rustdesk/rustdesk/releases/latest \
| grep -oE '"browser_download_url": *"[^"]+x86_64\.deb"' | tail -n1 | cut -d'"' -f4)
t=$(mktemp --suffix=.deb); curl -fsSL -o "$t" "$url"
apt-get install -y -q "$t"; rm -f "$t"
fi
install -d -m700 /etc/rustdesk
[ -f "$ICI/jeton-rustdesk.txt" ] && install -m600 "$ICI/jeton-rustdesk.txt" /etc/rustdesk/token
ecrire /usr/local/sbin/tablette-rustdesk 755 <>/usr/local/sbin/tablette-rustdesk <<'EOF'
toml() { cat <&1) && case "$out" in *refused*|*rror*) ;; *) return 0 ;; esac
sleep 2
done; return 1
}
case "${1:-}" in
config)
systemctl stop rustdesk 2>/dev/null || true
h=$(getent passwd "$UTIL" | cut -d: -f6)
for d in /root/.config/rustdesk "$h/.config/rustdesk"; do
install -d -m700 "$d"; toml > "$d/RustDesk2.toml"; chmod 600 "$d/RustDesk2.toml"
done
chown -R "$UTIL:" "$h/.config/rustdesk"
systemctl enable --now rustdesk ;;
motdepasse)
[ -s /etc/rustdesk/password ] || ( umask 077; tr -dc 'A-Za-z0-9' /etc/rustdesk/password )
attendre_service "$(cat /etc/rustdesk/password)" && echo "mot de passe permanent applique" ;;
enregistrer)
nom=${2:?nom}
[ -s /etc/rustdesk/token ] || { echo "pas de jeton (/etc/rustdesk/token) : enregistrement ignore"; exit 0; }
sleep 10 # laisser le service s'annoncer aupres du serveur
out=$(rustdesk --assign --token "$(cat /etc/rustdesk/token)" --address_book_name "$CARNET" \
--address_book_alias "$nom" --address_book_password "$(cat /etc/rustdesk/password)" 2>&1)
echo "$out"; case "$out" in *rror*|*ailed*) exit 1 ;; esac
echo "ID RustDesk : $(rustdesk --get-id)" ;;
*) echo "usage : $0 config|motdepasse|enregistrer NOM"; exit 2 ;;
esac
EOF
chmod 755 /usr/local/sbin/tablette-rustdesk
tablette-rustdesk config
tablette-rustdesk motdepasse || echo " (mot de passe : le service n'a pas repondu, relancer le script)"
# -----------------------------------------------------------------------------
etape "Clonage : preparation et premier demarrage"
# 1) tablette-preparer-clonage : a lancer sur la tablette modele juste avant l'image Clonezilla
ecrire /usr/local/sbin/tablette-preparer-clonage 755 <<'EOF'
#!/bin/bash
# Efface l'identite de cette tablette puis l'eteint. Au prochain demarrage (modele ou clone),
# un nom est demande a l'ecran et une nouvelle identite est creee.
set -e
[ "$(id -u)" = 0 ] || exec sudo "$0" "$@"
[ -s /etc/rustdesk/token ] || echo "ATTENTION : pas de jeton RustDesk, les clones ne s'inscriront pas dans le carnet."
read -r -p "Effacer l'identite de cette tablette et l'eteindre ? [o/N] " r; [ "$r" = o ] || exit 1
systemctl stop rustdesk || true
rm -f /root/.config/rustdesk/RustDesk.toml /home/*/.config/rustdesk/RustDesk.toml # -> nouvel ID
rm -f /etc/rustdesk/password # -> nouveau mot de passe
rm -f /etc/ssh/ssh_host_* # -> nouvelles cles SSH
truncate -s0 /etc/machine-id; rm -f /var/lib/dbus/machine-id # -> nouveau machine-id
install -d /etc/tablette; touch /etc/tablette/a-personnaliser
journalctl --rotate >/dev/null 2>&1 && journalctl --vacuum-time=1s >/dev/null 2>&1 || true
echo "Prete pour l'image Clonezilla. Extinction."; sleep 2; poweroff
EOF
# 2) Au demarrage (root) : nouvelle identite, puis attente du nom saisi dans la session
ecrire /usr/local/sbin/tablette-premier-demarrage 755 <<'EOF'
#!/bin/bash
set -u
[ -s /var/lib/dbus/machine-id ] || ln -sf /etc/machine-id /var/lib/dbus/machine-id
ls /etc/ssh/ssh_host_*_key >/dev/null 2>&1 || ssh-keygen -A 2>/dev/null || true
install -d -m 770 -o root -g tablette /run/tablette # le nom y sera depose par la session
EOF
ecrire /etc/systemd/system/tablette-premier-demarrage.service <<'EOF'
[Unit]
Description=Tablette : nouvelle identite apres clonage
ConditionPathExists=/etc/tablette/a-personnaliser
Before=display-manager.service ssh.service rustdesk.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/tablette-premier-demarrage
[Install]
WantedBy=multi-user.target
EOF
# 3) Dans la session : demande du nom (clavier visuel affiche)
ecrire /usr/local/bin/tablette-demander-nom 755 <<'EOF'
#!/bin/bash
[ -e /etc/tablette/a-personnaliser ] || exit 0
sleep 12; pgrep -x onboard >/dev/null || (setxkbmap be; onboard &)
while :; do
nom=$(yad --entry --center --on-top --title "Nouvelle tablette" --width 600 \
--text "Nom de cette tablette ?\n(minuscules, chiffres et tirets - ex. pa-ixl-tab-02)" \
--button="Valider:0") || continue
nom=$(echo "$nom" | tr 'A-Z' 'a-z')
if [[ "$nom" =~ ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$ ]]; then break; fi
yad --error --center --text "Nom invalide : $nom" --button=OK:0
done
echo "$nom" > /run/tablette/nom
yad --info --center --no-buttons --timeout 120 --text "Configuration de '$nom'...\nLa tablette va redemarrer." &
EOF
ecrire /etc/xdg/autostart/tablette-demander-nom.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=Nom de la tablette
Exec=/usr/local/bin/tablette-demander-nom
X-GNOME-Autostart-enabled=true
EOF
# 4) Des que le nom est depose (root) : nom de machine, RustDesk, puis redemarrage
ecrire /usr/local/sbin/tablette-nommer 755 <<'EOF'
#!/bin/bash
set -u
nom=$(head -c 63 /run/tablette/nom | tr -cd 'a-z0-9-'); rm -f /run/tablette/nom
[ -n "$nom" ] || exit 1
hostnamectl set-hostname "$nom"
sed -i "/^127\.0\.1\.1/d" /etc/hosts; echo -e "127.0.1.1\t$nom" >> /etc/hosts
systemctl restart rustdesk; sleep 5
tablette-rustdesk motdepasse
if tablette-rustdesk enregistrer "$nom"; then
echo "Inscrite dans le carnet RustDesk sous '$nom'"
else
echo "Inscription RustDesk echouee : relancer 'sudo tablette-rustdesk enregistrer $nom'"
fi
rm -f /etc/tablette/a-personnaliser
sleep 3; systemctl reboot
EOF
ecrire /etc/systemd/system/tablette-nommer.path <<'EOF'
[Unit]
Description=Tablette : nom saisi au premier demarrage
ConditionPathExists=/etc/tablette/a-personnaliser
[Path]
PathExists=/run/tablette/nom
[Install]
WantedBy=multi-user.target
EOF
ecrire /etc/systemd/system/tablette-nommer.service <<'EOF'
[Unit]
Description=Tablette : nom, RustDesk, redemarrage
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/tablette-nommer
EOF
systemctl daemon-reload
systemctl enable tablette-premier-demarrage.service tablette-nommer.path
# -----------------------------------------------------------------------------
etape "Inscription RustDesk de cette tablette"
tablette-rustdesk enregistrer "$(hostname)" || echo " (a relancer plus tard : sudo tablette-rustdesk enregistrer $(hostname))"
etape "Termine"
echo "ID RustDesk : $(rustdesk --get-id 2>/dev/null)"
echo "Mot de passe permanent : sudo cat /etc/rustdesk/password"
echo "Redemarre la tablette pour appliquer GRUB, Xorg et la session."