readme and comment

This commit is contained in:
Clément SAILLANT
2025-03-26 18:00:23 +01:00
parent 2ba6845c16
commit 6c644a4a65
6 changed files with 275 additions and 113 deletions
+22 -8
View File
@@ -1,14 +1,28 @@
# 🍏 stm32-adb2usb
![Setup du projet](./assets/project-setup.jpeg)
*Un aperçu de mon setup avec un clavier Apple d'époque et une souris ADB.*
# 🍏 Apple ADB Ressurector
![PlatformIO](https://img.shields.io/badge/platform-PlatformIO-orange)
![Licence](https://img.shields.io/badge/licence-GNU%20GPL%20v3-blue)
![Status](https://img.shields.io/badge/status-Beta-yellow)
**stm32-adb2usb** : Parce que vos claviers et souris d'époque méritent une seconde vie ! 🕰️✨
Transformez vos périphériques Apple Desktop Bus (ADB) en périphériques USB modernes grâce à ce projet. Compatible avec les claviers et souris ADB des années 80 et 90, ce projet utilise une carte STM32F103 "Blue Pill" et repose sur PlatformIO. Et oui, ça fonctionne même avec les souris à un seul bouton ! 🖱️
**Apple ADB Ressurector** : Donnez une seconde vie à vos trésors vintage ! 🕰️✨
Transformez vos claviers et souris Apple Desktop Bus (ADB) des années 80 et 90 en périphériques USB modernes avec ce projet passionnant ! 🎉
Compatible même avec les légendaires souris à un seul bouton, ce projet utilise PlatformIO pour donner une nouvelle vie à vos reliques de la pomme arc en ciel. 🖱️✨
---
## 🔗 Basé sur le travail de
Ce projet est basé sur le travail initial de [Szymon Łopaciuk](https://github.com/szymonlopaciuk/stm32-adb2usb). Vous pouvez consulter son dépôt ici : [stm32-adb2usb](https://github.com/szymonlopaciuk/stm32-adb2usb). Merci à lui pour son incroyable contribution à la communauté open source ! 🙌
---
## 🌐 Mon dépôt
Le code source de ce projet est disponible sur mon dépôt GitHub : [Apple ADB Ressurector](https://github.com/electron-rare/Apple-ADB-Ressurector). N'hésitez pas à y jeter un œil, à contribuer ou à poser des questions ! 😊
<img src="./assets/project-setup.jpeg" alt="Setup du projet" width="400">
*Un aperçu de mon setup avec un clavier Apple d'époque et une souris ADB.*
---
@@ -16,8 +30,8 @@ Transformez vos périphériques Apple Desktop Bus (ADB) en périphériques USB m
1. Clonez ce magnifique dépôt :
```bash
git clone https://github.com/yourusername/stm32-adb2usb.git
cd stm32-adb2usb
git clone https://github.com/electron-rare/Apple-ADB-Ressurector.git
cd apple-adb-ressurector
```
2. Installez PlatformIO (si ce n'est pas déjà fait) :
+69 -53
View File
@@ -1,73 +1,91 @@
/**
* @file hid_keyboard.cpp
* @brief Implémentation des fonctionnalités HID pour les claviers.
* @part of Apple-ADB-Ressurector
* Inspiré et basé sur le travail initial de Szymon Łopaciuk https://github.com/szymonlopaciuk/stm32-adb2usb
*
*
* @date 2025
* @author Clément SAILLANT
* Dépôt actuel : https://github.com/electron-rare/Apple-ADB-Ressurector
* @license GNU GPL v3
*/
#include "hid_keyboard.h"
#include "usbd_hid_composite_if.h"
#include <Arduino.h>
void hid_keyboard_init()
{
/**
* @brief Initialise le clavier HID.
*/
void hid_keyboard_init() {
#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_HID
HID_Composite_Init(HID_KEYBOARD);
#endif
}
void hid_keyboard_close()
{
/**
* @brief Ferme le clavier HID.
*/
void hid_keyboard_close() {
#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_HID
HID_Composite_DeInit(HID_KEYBOARD);
#endif
}
void hid_keyboard_send_report(hid_key_report* report)
{
/**
* @brief Envoie un rapport HID pour le clavier.
*
* @param report Pointeur vers le rapport HID à envoyer.
*/
void hid_keyboard_send_report(hid_key_report* report) {
uint8_t buf[8] = {report->modifiers, 0, report->keys[0],
report->keys[1], report->keys[2], report->keys[3], report->keys[4],
report->keys[5]
};
report->keys[1], report->keys[2], report->keys[3],
report->keys[4], report->keys[5]};
#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_HID
HID_Composite_keyboard_sendReport(buf, 8);
#endif
}
bool hid_keyboard_set_keys_from_adb_register(
hid_key_report* report, adb_data<adb_kb_keypress> key_press) {
// Power button est un cas spécial, présent dans les deux octets:
/**
* @brief Met à jour les touches du rapport HID à partir d'un registre ADB.
*
* @param report Pointeur vers le rapport HID.
* @param key_press Données du registre ADB.
* @return true si le rapport a été modifié, false sinon.
*/
bool hid_keyboard_set_keys_from_adb_register(hid_key_report* report, adb_data<adb_kb_keypress> key_press) {
if (key_press.raw == ADBKey::KeyCode::POWER_DOWN)
return hid_keyboard_update_key_in_report(report, KEY_POWER, false);
else if (key_press.raw == ADBKey::KeyCode::POWER_UP)
return hid_keyboard_update_key_in_report(report, KEY_POWER, true);
// Autres touches:
bool report_changed = false;
// Higher octet key:
uint8_t key0 = key_press.data.key0;
if (ADBKeymap::isModifier(key0))
report_changed = hid_keyboard_update_modifier_in_report(
report, key0, key_press.data.released0);
report_changed = hid_keyboard_update_modifier_in_report(report, key0, key_press.data.released0);
else
report_changed = hid_keyboard_update_key_in_report(
report, ADBKeymap::toHID(key0), key_press.data.released0);
report_changed = hid_keyboard_update_key_in_report(report, ADBKeymap::toHID(key0), key_press.data.released0);
// Lower octet key:
uint8_t key1 = key_press.data.key1;
if (ADBKeymap::isModifier(key1))
report_changed = hid_keyboard_update_modifier_in_report(
report, key1, key_press.data.released1) || report_changed;
report_changed = hid_keyboard_update_modifier_in_report(report, key1, key_press.data.released1) || report_changed;
else
report_changed = hid_keyboard_update_key_in_report(
report, ADBKeymap::toHID(key1), key_press.data.released1) || report_changed;
report_changed = hid_keyboard_update_key_in_report(report, ADBKeymap::toHID(key1), key_press.data.released1) || report_changed;
return report_changed;
}
bool hid_keyboard_set_modifiers_from_adb_register(
hid_key_report* report, adb_data<adb_kb_keypress> reg) {
// TODO: don't seem necessary, as modifiers still register normal keypresses
return false;
}
/**
* @brief Met à jour une touche spécifique dans le rapport HID.
*
* @param report Pointeur vers le rapport HID.
* @param hid_keycode Code HID de la touche.
* @param released Indique si la touche est relâchée.
* @return true si le rapport a été modifié, false sinon.
*/
bool hid_keyboard_update_key_in_report(hid_key_report* report, uint8_t hid_keycode, bool released) {
// Sometimes the response from the ADB keyboard is rubbish:
// either an invalid key, or lifting a key that's not been pressed.
// This detects the first case, so we don't waste time processing it.
if (hid_keycode == KEY_NONE) return false;
if (released)
@@ -76,40 +94,38 @@ bool hid_keyboard_update_key_in_report(hid_key_report* report, uint8_t hid_keyco
return hid_keyboard_add_key_to_report(report, hid_keycode);
}
bool hid_keyboard_update_modifier_in_report(hid_key_report* report, uint8_t adb_keycode, bool released) {
uint8_t mask = ADBKeymap::getModifierMask(adb_keycode);
if (mask == 0) return false;
// No change if the modifier is already set
if (released == !(report->modifiers & mask)) return false;
// Flip the modifier
if (!released) report->modifiers |= mask;
else report->modifiers &= ~mask;
return true;
}
// Returns true if after execution the key is in the report
// in other words, returns false if insertion unsuccessful (report unchanged)
/**
* @brief Ajoute une touche au rapport HID.
*
* @param report Pointeur vers le rapport HID.
* @param hid_keycode Code HID de la touche.
* @return true si la touche a été ajoutée, false sinon.
*/
bool hid_keyboard_add_key_to_report(hid_key_report* report, uint8_t hid_keycode) {
int8_t free_slot = -1;
for (uint8_t i = 0; i < KEY_REPORT_KEYS_COUNT; i++) {
if (report->keys[i] == hid_keycode)
return true; // key is already in the report
return true;
if (report->keys[i] == 0 && free_slot == -1)
free_slot = i; // memorise empty entry idx
free_slot = i;
}
if (free_slot == -1)
return false; // key report is full
return false;
report->keys[free_slot] = hid_keycode;
return true;
}
/**
* @brief Supprime une touche du rapport HID.
*
* @param report Pointeur vers le rapport HID.
* @param hid_keycode Code HID de la touche.
* @return true si la touche a été supprimée, false sinon.
*/
bool hid_keyboard_remove_key_from_report(hid_key_report* report, uint8_t hid_keycode) {
bool report_changed = false;
for (uint8_t i = 0; i < KEY_REPORT_KEYS_COUNT; i++) {
+85 -5
View File
@@ -1,24 +1,104 @@
/**
* @file hid_keyboard.h
* @brief Gestion des fonctionnalités HID pour les claviers.
* @part of Apple-ADB-Ressurector
* Inspiré et basé sur le travail initial de Szymon Łopaciuk https://github.com/szymonlopaciuk/stm32-adb2usb
*
*
* @date 2025
* @author Clément SAILLANT
* Dépôt actuel : https://github.com/electron-rare/Apple-ADB-Ressurector
* @license GNU GPL v3
*/
#ifndef HID_KEYBOARD_h
#define HID_KEYBOARD_h
#include <cstdint> // Ajout pour définir uint8_t
#include "adb.h" // Inclusion de la bibliothèque ADB
#include <cstdint>
#include "adb.h"
#define KEY_REPORT_KEYS_COUNT 6
#define KEY_REPORT_KEYS_COUNT 6 /**< Nombre maximum de touches dans un rapport HID. */
/**
* @struct hid_key_report
* @brief Structure représentant un rapport HID pour un clavier.
*/
struct hid_key_report {
uint8_t modifiers;
uint8_t keys[KEY_REPORT_KEYS_COUNT];
uint8_t modifiers; /**< Modificateurs actifs (Ctrl, Alt, etc.). */
uint8_t keys[KEY_REPORT_KEYS_COUNT]; /**< Tableau des touches actives. */
};
/**
* @brief Initialise le clavier HID.
*/
void hid_keyboard_init();
/**
* @brief Ferme le clavier HID.
*/
void hid_keyboard_close();
/**
* @brief Envoie un rapport HID pour le clavier.
*
* @param report Pointeur vers le rapport HID à envoyer.
*/
void hid_keyboard_send_report(hid_key_report* report);
/**
* @brief Met à jour les touches du rapport HID à partir d'un registre ADB.
*
* @param report Pointeur vers le rapport HID.
* @param reg Données du registre ADB.
* @return true si le rapport a été modifié, false sinon.
*/
bool hid_keyboard_set_keys_from_adb_register(hid_key_report* report, adb_data<adb_kb_keypress> reg);
/**
* @brief Met à jour les modificateurs du rapport HID à partir d'un registre ADB.
*
* @param report Pointeur vers le rapport HID.
* @param reg Données du registre ADB.
* @return true si le rapport a été modifié, false sinon.
*/
bool hid_keyboard_set_modifiers_from_adb_register(hid_key_report* report, adb_data<adb_kb_keypress> reg);
/**
* @brief Met à jour une touche spécifique dans le rapport HID.
*
* @param report Pointeur vers le rapport HID.
* @param hid_keycode Code HID de la touche.
* @param released Indique si la touche est relâchée.
* @return true si le rapport a été modifié, false sinon.
*/
bool hid_keyboard_update_key_in_report(hid_key_report* report, uint8_t hid_keycode, bool released);
/**
* @brief Met à jour un modificateur spécifique dans le rapport HID.
*
* @param report Pointeur vers le rapport HID.
* @param adb_keycode Code ADB du modificateur.
* @param released Indique si le modificateur est relâché.
* @return true si le rapport a été modifié, false sinon.
*/
bool hid_keyboard_update_modifier_in_report(hid_key_report* report, uint8_t adb_keycode, bool released);
/**
* @brief Ajoute une touche au rapport HID.
*
* @param report Pointeur vers le rapport HID.
* @param hid_keycode Code HID de la touche.
* @return true si la touche a été ajoutée, false sinon.
*/
bool hid_keyboard_add_key_to_report(hid_key_report* report, uint8_t hid_keycode);
/**
* @brief Supprime une touche du rapport HID.
*
* @param report Pointeur vers le rapport HID.
* @param hid_keycode Code HID de la touche.
* @return true si la touche a été supprimée, false sinon.
*/
bool hid_keyboard_remove_key_from_report(hid_key_report* report, uint8_t hid_keycode);
#endif
+28 -4
View File
@@ -1,21 +1,45 @@
/**
* @file hid_mouse.cpp
* @brief Implémentation des fonctionnalités HID pour les souris.
* @part of Apple-ADB-Ressurector
* Inspiré et basé sur le travail initial de Szymon Łopaciuk https://github.com/szymonlopaciuk/stm32-adb2usb
*
*
* @date 2025
* @author Clément SAILLANT
* Dépôt actuel : https://github.com/electron-rare/Apple-ADB-Ressurector
* @license GNU GPL v3
*/
#include "hid_mouse.h"
#include "usbd_hid_composite_if.h"
#include <Arduino.h>
void hid_mouse_init()
{
/**
* @brief Initialise la souris HID.
*/
void hid_mouse_init() {
#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_HID
HID_Composite_Init(HID_MOUSE);
#endif
}
void hid_mouse_close()
{
/**
* @brief Ferme la souris HID.
*/
void hid_mouse_close() {
#ifdef PIO_FRAMEWORK_ARDUINO_ENABLE_HID
HID_Composite_DeInit(HID_MOUSE);
#endif
}
/**
* @brief Envoie un rapport HID pour la souris.
*
* @param button État du bouton de la souris (appuyé ou relâché).
* @param offset_x Déplacement horizontal de la souris.
* @param offset_y Déplacement vertical de la souris.
*/
void hid_mouse_send_report(bool button, int8_t offset_x, int8_t offset_y) {
uint8_t m[4];
m[0] = button;
+28
View File
@@ -1,10 +1,38 @@
/**
* @file hid_mouse.h
* @brief Gestion des fonctionnalités HID pour les souris.
* @part of Apple-ADB-Ressurector
* Inspiré et basé sur le travail initial de Szymon Łopaciuk https://github.com/szymonlopaciuk/stm32-adb2usb
*
*
* @date 2025
* @author Clément SAILLANT
* Dépôt actuel : https://github.com/electron-rare/Apple-ADB-Ressurector
* @license GNU GPL v3
*/
#ifndef HID_MOUSE_h
#define HID_MOUSE_h
#include <cstdint>
/**
* @brief Initialise la souris HID.
*/
void hid_mouse_init();
/**
* @brief Ferme la souris HID.
*/
void hid_mouse_close();
/**
* @brief Envoie un rapport HID pour la souris.
*
* @param button État du bouton de la souris (appuyé ou relâché).
* @param offset_x Déplacement horizontal de la souris.
* @param offset_y Déplacement vertical de la souris.
*/
void hid_mouse_send_report(bool button, int8_t offset_x, int8_t offset_y);
#endif
+43 -43
View File
@@ -1,21 +1,13 @@
/*
* This file is part of the stm32-adb2usb project.
* Inspiré et adapté du projet https://github.com/szymonlopaciuk/stm32-adb2usb
*
* Copyright (C) 2025 Clément SAILLANT - L'électron rare
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
/**
* @file main.cpp
* @brief Main file for the Apple ADB Ressurector project.
* Inspiré et basé sur le travail initial de Szymon Łopaciuk https://github.com/szymonlopaciuk/stm32-adb2usb
* @credits Szymon Łopaciuk
* @author Clément SAILLANT
* @date 2025
* Dépôt actuel : https://github.com/electron-rare/Apple-ADB-Ressurector
* @license GNU GPL v3
*/
#ifndef UNIT_TEST
@@ -26,21 +18,30 @@
#define POLL_DELAY 5
// Structure pour regrouper les états des périphériques
/**
* @struct DeviceState
* @brief Structure pour regrouper les états des périphériques.
*/
struct DeviceState {
bool apple_extended_detected = false;
bool keyboard_present = false;
bool mouse_present = false;
bool led_caps = false; // État de la LED Caps Lock
bool led_num = true; // État de la LED Num Lock (actif par défaut)
bool apple_extended_detected = false; /**< Détection du clavier Apple étendu. */
bool keyboard_present = false; /**< Présence d'un clavier. */
bool mouse_present = false; /**< Présence d'une souris. */
bool led_caps = false; /**< État de la LED Caps Lock. */
bool led_num = true; /**< État de la LED Num Lock (actif par défaut). */
};
// Instances globales
ADB adb(PB4); // Remplacez PB4 par la pin appropriée
ADBDevices adbDevices(adb);
DeviceState deviceState;
ADB adb(PB4); /**< Instance du bus ADB. */
ADBDevices adbDevices(adb); /**< Gestionnaire des périphériques ADB. */
DeviceState deviceState; /**< État des périphériques. */
// Fonction utilitaire pour initialiser un périphérique
/**
* @brief Initialise un périphérique ADB.
*
* @param addr Adresse du périphérique.
* @param handler_id Identifiant du gestionnaire de périphérique.
* @return true si l'initialisation a réussi, false sinon.
*/
bool initializeDevice(uint8_t addr, uint8_t handler_id) {
bool error = false;
adb_data<adb_register3> reg3 = {0}, mask = {0};
@@ -49,41 +50,39 @@ bool initializeDevice(uint8_t addr, uint8_t handler_id) {
return adbDevices.deviceUpdateRegister3(addr, reg3, mask.raw, &error) && !error;
}
/**
* @brief Fonction d'initialisation du programme.
*/
void setup() {
// Configuration de la LED d'état
pinMode(PC13, OUTPUT);
digitalWrite(PC13, LOW);
// Initialisation de la communication série
Serial.begin(115200);
// Initialisation du bus ADB
adb.init(PB4, true); // Active l'utilisation de ADBDevices
adb.init(PB4, true);
delay(1000); // Attente pour permettre aux périphériques de se réinitialiser
delay(1000);
// Initialisation des périphériques
deviceState.keyboard_present = initializeDevice(ADBKey::Address::KEYBOARD, 0x03);
deviceState.mouse_present = initializeDevice(ADBKey::Address::MOUSE, 0x02);
// Désactivation de la LED d'état après initialisation
digitalWrite(PC13, HIGH);
// Activation de Num Lock au démarrage
adbDevices.keyboardWriteLEDs(false, deviceState.led_caps, deviceState.led_num);
}
/**
* @brief Gère les événements du clavier.
*/
void handleKeyboard() {
static hid_key_report key_report = {0};
bool error = false;
// Lecture des touches pressées
auto key_press = adbDevices.keyboardReadKeyPress(&error);
if (error) return;
bool report_changed = hid_keyboard_set_keys_from_adb_register(&key_report, key_press);
// Gestion de Caps Lock - utilisation des constantes du namespace ADBKey
if ((key_press.data.key0 == ADBKey::KeyCode::CAPS_LOCK && !key_press.data.released0) ||
(key_press.data.key1 == ADBKey::KeyCode::CAPS_LOCK && !key_press.data.released1)) {
deviceState.led_caps = !deviceState.led_caps;
@@ -91,7 +90,6 @@ void handleKeyboard() {
report_changed = true;
}
// Gestion de Num Lock - utilisation des constantes du namespace ADBKey
if ((key_press.data.key0 == ADBKey::KeyCode::NUM_LOCK && !key_press.data.released0) ||
(key_press.data.key1 == ADBKey::KeyCode::NUM_LOCK && !key_press.data.released1)) {
deviceState.led_num = !deviceState.led_num;
@@ -99,27 +97,29 @@ void handleKeyboard() {
report_changed = true;
}
// Envoi du rapport HID si modifié
if (report_changed) {
hid_keyboard_send_report(&key_report);
}
}
/**
* @brief Gère les événements de la souris.
*/
void handleMouse() {
bool error = false;
// Lecture des données de la souris
auto mouse_data = adbDevices.mouseReadData(&error);
if (error || mouse_data.raw == 0) return;
// Conversion des axes avec adbMouseConvertAxis
int8_t mouse_x = adbMouseConvertAxis(mouse_data.data.x_offset);
int8_t mouse_y = adbMouseConvertAxis(mouse_data.data.y_offset);
// Envoi du rapport HID pour la souris
hid_mouse_send_report(mouse_data.data.button ? 0 : 1, mouse_x, mouse_y);
}
/**
* @brief Boucle principale du programme.
*/
void loop() {
if (deviceState.keyboard_present) {
handleKeyboard();